From 4c82c96369fad745c4788c08fbe959a1cdded7ca Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Mon, 30 Nov 2015 02:22:20 -0400 Subject: [PATCH] Added a new texture wrap mode "clampzero", which outputs transparent black (or opaque black for textures without an alpha channel) rather than the texture's edge colors, when it's drawn or sampled from outside of its regular texture coordinate range. --- src/modules/graphics/Graphics.cpp | 1 + src/modules/graphics/Graphics.h | 1 + src/modules/graphics/Texture.cpp | 13 ++++---- src/modules/graphics/Texture.h | 1 + src/modules/graphics/opengl/Canvas.cpp | 11 +------ src/modules/graphics/opengl/Canvas.h | 1 - src/modules/graphics/opengl/Graphics.cpp | 2 ++ src/modules/graphics/opengl/OpenGL.cpp | 41 +++++++++++++++--------- src/modules/graphics/opengl/OpenGL.h | 4 +++ 9 files changed, 43 insertions(+), 32 deletions(-) diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index 5b43b8bbd..8dbfd21da 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -182,6 +182,7 @@ StringMap Graphics::lineJoins( StringMap::Entry Graphics::supportEntries[] = { { "multicanvasformats", SUPPORT_MULTI_CANVAS_FORMATS }, + { "clampzero", SUPPORT_CLAMP_ZERO }, }; StringMap Graphics::support(Graphics::supportEntries, sizeof(Graphics::supportEntries)); diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index 81326da4c..ede4eba0d 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -99,6 +99,7 @@ public: enum Support { SUPPORT_MULTI_CANVAS_FORMATS, + SUPPORT_CLAMP_ZERO, SUPPORT_MAX_ENUM }; diff --git a/src/modules/graphics/Texture.cpp b/src/modules/graphics/Texture.cpp index d1e268dd7..fd21c947f 100644 --- a/src/modules/graphics/Texture.cpp +++ b/src/modules/graphics/Texture.cpp @@ -114,18 +114,19 @@ bool Texture::getConstant(WrapMode in, const char *&out) StringMap::Entry Texture::filterModeEntries[] = { - { "linear", Texture::FILTER_LINEAR }, - { "nearest", Texture::FILTER_NEAREST }, - { "none", Texture::FILTER_NONE }, + { "linear", FILTER_LINEAR }, + { "nearest", FILTER_NEAREST }, + { "none", FILTER_NONE }, }; StringMap Texture::filterModes(Texture::filterModeEntries, sizeof(Texture::filterModeEntries)); StringMap::Entry Texture::wrapModeEntries[] = { - { "clamp", Texture::WRAP_CLAMP }, - { "repeat", Texture::WRAP_REPEAT }, - { "mirroredrepeat", Texture::WRAP_MIRRORED_REPEAT }, + { "clamp", WRAP_CLAMP }, + { "clampzero", WRAP_CLAMP_ZERO }, + { "repeat", WRAP_REPEAT }, + { "mirroredrepeat", WRAP_MIRRORED_REPEAT }, }; StringMap Texture::wrapModes(Texture::wrapModeEntries, sizeof(Texture::wrapModeEntries)); diff --git a/src/modules/graphics/Texture.h b/src/modules/graphics/Texture.h index fb6082a75..3176c0b1d 100644 --- a/src/modules/graphics/Texture.h +++ b/src/modules/graphics/Texture.h @@ -43,6 +43,7 @@ public: enum WrapMode { WRAP_CLAMP, + WRAP_CLAMP_ZERO, WRAP_REPEAT, WRAP_MIRRORED_REPEAT, WRAP_MAX_ENUM diff --git a/src/modules/graphics/opengl/Canvas.cpp b/src/modules/graphics/opengl/Canvas.cpp index 1770a81e5..d173bc30b 100644 --- a/src/modules/graphics/opengl/Canvas.cpp +++ b/src/modules/graphics/opengl/Canvas.cpp @@ -407,9 +407,6 @@ void Canvas::startGrab(const std::vector &canvases) if (canvases.size() > 0) { - if (!isMultiCanvasSupported()) - throw love::Exception("Multi-canvas rendering is not supported on this system."); - if ((int) canvases.size() + 1 > gl.getMaxRenderTargets()) throw love::Exception("This system can't simultaneously render to %d canvases.", canvases.size()+1); @@ -804,15 +801,9 @@ bool Canvas::isSupported() return GLAD_ES_VERSION_2_0 || GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object || GLAD_EXT_framebuffer_object; } -bool Canvas::isMultiCanvasSupported() -{ - // system must support at least 4 simultaneous active canvases. - return gl.getMaxRenderTargets() >= 4; -} - bool Canvas::isMultiFormatMultiCanvasSupported() { - return isMultiCanvasSupported() && (GLAD_ES_VERSION_3_0 || GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object); + return gl.getMaxRenderTargets() > 1 && (GLAD_ES_VERSION_3_0 || GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object); } bool Canvas::supportedFormats[] = {false}; diff --git a/src/modules/graphics/opengl/Canvas.h b/src/modules/graphics/opengl/Canvas.h index 23e89c215..45c5367ee 100644 --- a/src/modules/graphics/opengl/Canvas.h +++ b/src/modules/graphics/opengl/Canvas.h @@ -118,7 +118,6 @@ public: } static bool isSupported(); - static bool isMultiCanvasSupported(); static bool isMultiFormatMultiCanvasSupported(); static bool isFormatSupported(Format format); diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 956a6e83e..8331c57ca 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -1491,6 +1491,8 @@ bool Graphics::isSupported(Support feature) const { case SUPPORT_MULTI_CANVAS_FORMATS: return Canvas::isMultiFormatMultiCanvasSupported(); + case SUPPORT_CLAMP_ZERO: + return gl.isClampZeroTextureWrapSupported(); default: return false; } diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index dcf7c9727..72032db5a 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -602,24 +602,35 @@ void OpenGL::setTextureFilter(graphics::Texture::Filter &f) f.anisotropy = 1.0f; } +GLint OpenGL::getGLWrapMode(Texture::WrapMode wmode) +{ + if (wmode == Texture::WRAP_CLAMP_ZERO && !isClampZeroTextureWrapSupported()) + wmode = Texture::WRAP_CLAMP; + + switch (wmode) + { + case Texture::WRAP_CLAMP: + default: + return GL_CLAMP_TO_EDGE; + case Texture::WRAP_CLAMP_ZERO: + return GL_CLAMP_TO_BORDER; + case Texture::WRAP_REPEAT: + return GL_REPEAT; + case Texture::WRAP_MIRRORED_REPEAT: + return GL_MIRRORED_REPEAT; + } + +} + void OpenGL::setTextureWrap(const graphics::Texture::Wrap &w) { - auto glWrapMode = [](Texture::WrapMode wmode) -> GLint - { - switch (wmode) - { - case Texture::WRAP_CLAMP: - default: - return GL_CLAMP_TO_EDGE; - case Texture::WRAP_REPEAT: - return GL_REPEAT; - case Texture::WRAP_MIRRORED_REPEAT: - return GL_MIRRORED_REPEAT; - } - }; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, getGLWrapMode(w.s)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, getGLWrapMode(w.t)); +} - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapMode(w.s)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapMode(w.t)); +bool OpenGL::isClampZeroTextureWrapSupported() const +{ + return GLAD_VERSION_1_3 || GLAD_EXT_texture_border_clamp || GLAD_NV_texture_border_clamp; } int OpenGL::getMaxTextureSize() const diff --git a/src/modules/graphics/opengl/OpenGL.h b/src/modules/graphics/opengl/OpenGL.h index d4ec16deb..33b6c0b1d 100644 --- a/src/modules/graphics/opengl/OpenGL.h +++ b/src/modules/graphics/opengl/OpenGL.h @@ -312,6 +312,8 @@ public: **/ void setTextureWrap(const graphics::Texture::Wrap &w); + bool isClampZeroTextureWrapSupported() const; + /** * Returns the maximum supported width or height of a texture. **/ @@ -354,6 +356,8 @@ private: void initMatrices(); void createDefaultTexture(); + GLint getGLWrapMode(Texture::WrapMode wmode); + bool contextInitialized; float maxAnisotropy;