diff --git a/es-core/src/components/ImageComponent.cpp b/es-core/src/components/ImageComponent.cpp index 6b11eefe7..7c54521c9 100644 --- a/es-core/src/components/ImageComponent.cpp +++ b/es-core/src/components/ImageComponent.cpp @@ -50,6 +50,7 @@ ImageComponent::ImageComponent(bool forceLoad, bool dynamic) , mLinearInterpolation {false} , mTopLeftCrop {0.0f, 0.0f} , mBottomRightCrop {1.0f, 1.0f} + , mClipRegion {0.0f, 0.0f, 0.0f, 0.0f} { updateColors(); } @@ -367,6 +368,34 @@ void ImageComponent::setDimming(float dimming) mDimming = dimming; } +void ImageComponent::setClipRegion(const glm::vec4& clipRegion) +{ + if (mVertices[0].clipregion == clipRegion) + return; + + mClipRegion = clipRegion; + + if (mClipRegion == glm::vec4 {0.0f, 0.0f, 0.0f, 0.0f}) { + if (mVertices[0].shaderFlags & Renderer::ShaderFlags::CLIPPING) { + mVertices[0].shaderFlags ^= Renderer::ShaderFlags::CLIPPING; + mVertices[1].shaderFlags ^= Renderer::ShaderFlags::CLIPPING; + mVertices[2].shaderFlags ^= Renderer::ShaderFlags::CLIPPING; + mVertices[3].shaderFlags ^= Renderer::ShaderFlags::CLIPPING; + } + } + else { + mVertices[0].shaderFlags |= Renderer::ShaderFlags::CLIPPING; + mVertices[1].shaderFlags |= Renderer::ShaderFlags::CLIPPING; + mVertices[2].shaderFlags |= Renderer::ShaderFlags::CLIPPING; + mVertices[3].shaderFlags |= Renderer::ShaderFlags::CLIPPING; + } + + mVertices[0].clipregion = clipRegion; + mVertices[1].clipregion = clipRegion; + mVertices[2].clipregion = clipRegion; + mVertices[3].clipregion = clipRegion; +} + void ImageComponent::updateVertices() { if (!mTexture) @@ -401,6 +430,8 @@ void ImageComponent::updateVertices() for (int i = 0; i < 4; ++i) mVertices[i].texcoord[1] = py - mVertices[i].texcoord[1]; } + + setClipRegion(mClipRegion); } void ImageComponent::updateColors() @@ -436,7 +467,11 @@ void ImageComponent::render(const glm::mat4& parentTrans) glm::vec2 targetSizePos {(mTargetSize - mSize) * mOrigin * glm::vec2 {-1.0f}}; mRenderer->drawRect(targetSizePos.x, targetSizePos.y, mTargetSize.x, mTargetSize.y, 0xFF000033, 0xFF000033); - mRenderer->drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0xFF000033, 0xFF000033); + if (mClipRegion == glm::vec4 {0.0f, 0.0f, 0.0f, 0.0f}) + mRenderer->drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0xFF000033, 0xFF000033); + else + mRenderer->drawRect(mClipRegion.x, mClipRegion.y, mClipRegion.z - mClipRegion.x, + mClipRegion.w - mClipRegion.y, 0xFF000033, 0xFF000033); } // An image with zero size would normally indicate a corrupt image file. if (mTexture->getSize() != glm::ivec2 {}) { diff --git a/es-core/src/components/ImageComponent.h b/es-core/src/components/ImageComponent.h index ad59e52b0..e127c209c 100644 --- a/es-core/src/components/ImageComponent.h +++ b/es-core/src/components/ImageComponent.h @@ -82,6 +82,7 @@ public: void setOpacity(float opacity) override; void setSaturation(float saturation) override; void setDimming(float dimming) override; + void setClipRegion(const glm::vec4& clipRegion); void setReflectionsFalloff(float falloff) override { mReflectionsFalloff = falloff; } void setFlipX(bool flip) override; // Mirror on the X axis. @@ -154,6 +155,7 @@ private: glm::vec2 mTopLeftCrop; glm::vec2 mBottomRightCrop; + glm::vec4 mClipRegion; }; #endif // ES_CORE_COMPONENTS_IMAGE_COMPONENT_H diff --git a/es-core/src/renderers/Renderer.h b/es-core/src/renderers/Renderer.h index e0ca1d1a6..289216083 100644 --- a/es-core/src/renderers/Renderer.h +++ b/es-core/src/renderers/Renderer.h @@ -51,7 +51,8 @@ public: enum ShaderFlags { BGRA_TO_RGBA = 0x00000001, FONT_TEXTURE = 0x00000002, - POST_PROCESSING = 0x00000004 + POST_PROCESSING = 0x00000004, + CLIPPING = 0x00000008 }; // clang-format on @@ -59,6 +60,7 @@ public: glm::vec2 position; glm::vec2 texcoord; unsigned int color; + glm::vec4 clipregion; float opacity; float saturation; float dimming; @@ -76,10 +78,14 @@ public: { } - Vertex(const glm::vec2& position, const glm::vec2& textureCoord, const unsigned int color) + Vertex(const glm::vec2& position, + const glm::vec2& textureCoord, + const unsigned int color, + const glm::vec4& clipRegion = glm::vec4 {0.0f, 0.0f, 0.0f, 0.0f}) : position(position) , texcoord(textureCoord) , color(color) + , clipregion(clipRegion) , opacity {1.0f} , saturation {1.0f} , dimming {1.0f} diff --git a/es-core/src/renderers/RendererOpenGL.cpp b/es-core/src/renderers/RendererOpenGL.cpp index 89745991b..afc984bea 100644 --- a/es-core/src/renderers/RendererOpenGL.cpp +++ b/es-core/src/renderers/RendererOpenGL.cpp @@ -420,6 +420,7 @@ void RendererOpenGL::drawTriangleStrips(const Vertex* vertices, mCoreShader->setAttribPointers(); GL_CHECK_ERROR(glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * numVertices, vertices, GL_DYNAMIC_DRAW)); + mCoreShader->setClipRegion(vertices->clipregion); mCoreShader->setOpacity(vertices->opacity); mCoreShader->setSaturation(vertices->saturation); mCoreShader->setDimming(vertices->dimming); diff --git a/es-core/src/renderers/ShaderOpenGL.cpp b/es-core/src/renderers/ShaderOpenGL.cpp index d223b32a2..ec119407f 100644 --- a/es-core/src/renderers/ShaderOpenGL.cpp +++ b/es-core/src/renderers/ShaderOpenGL.cpp @@ -121,6 +121,7 @@ void ShaderOpenGL::getVariableLocations(GLuint programID) mShaderTextureCoord = glGetAttribLocation(mProgramID, "texCoordVertex"); mShaderColor = glGetAttribLocation(mProgramID, "colorVertex"); mShaderTextureSize = glGetUniformLocation(mProgramID, "textureSize"); + mShaderClipRegion = glGetUniformLocation(mProgramID, "clipRegion"); mShaderOpacity = glGetUniformLocation(mProgramID, "opacity"); mShaderSaturation = glGetUniformLocation(mProgramID, "saturation"); mShaderDimming = glGetUniformLocation(mProgramID, "dimming"); @@ -158,6 +159,13 @@ void ShaderOpenGL::setTextureSize(std::array shaderVec2) GL_CHECK_ERROR(glUniform2f(mShaderTextureSize, shaderVec2[0], shaderVec2[1])); } +void ShaderOpenGL::setClipRegion(glm::vec4 clipRegion) +{ + if (mShaderClipRegion != -1) + GL_CHECK_ERROR(glUniform4f(mShaderClipRegion, clipRegion[0], clipRegion[1], clipRegion[2], + clipRegion[3])); +} + void ShaderOpenGL::setOpacity(GLfloat opacity) { if (mShaderOpacity != -1) diff --git a/es-core/src/renderers/ShaderOpenGL.h b/es-core/src/renderers/ShaderOpenGL.h index 7eee3c8fa..48a13daae 100644 --- a/es-core/src/renderers/ShaderOpenGL.h +++ b/es-core/src/renderers/ShaderOpenGL.h @@ -68,6 +68,7 @@ public: void setAttribPointers(); void setTextureSize(std::array shaderVec2); + void setClipRegion(glm::vec4 clipRegion); void setOpacity(GLfloat opacity); void setSaturation(GLfloat saturation); void setDimming(GLfloat dimming); @@ -92,6 +93,7 @@ private: GLint mShaderPosition; GLint mShaderTextureCoord; GLint mShaderColor; + GLint mShaderClipRegion; GLint mShaderTextureSize; GLint mShaderOpacity; GLint mShaderSaturation; diff --git a/resources/shaders/glsl/core.glsl b/resources/shaders/glsl/core.glsl index 4982d86ee..b8ffb6302 100644 --- a/resources/shaders/glsl/core.glsl +++ b/resources/shaders/glsl/core.glsl @@ -4,7 +4,7 @@ // core.glsl // // Core shader functionality: -// opacity, saturation, dimming and BGRA to RGBA conversion. +// clipping, opacity, saturation, dimming and BGRA to RGBA conversion. // // Vertex section of code: @@ -15,12 +15,14 @@ in vec2 positionVertex; in vec2 texCoordVertex; in vec4 colorVertex; -out vec4 color; +out vec2 position; out vec2 texCoord; +out vec4 color; void main(void) { gl_Position = MVPMatrix * vec4(positionVertex.xy, 0.0, 1.0); + position = positionVertex; texCoord = texCoordVertex; color.rgba = colorVertex.abgr; } @@ -32,8 +34,11 @@ void main(void) precision mediump float; #endif -in vec4 color; +in vec2 position; in vec2 texCoord; +in vec4 color; + +uniform vec4 clipRegion; uniform float opacity; uniform float saturation; uniform float dimming; @@ -47,9 +52,22 @@ out vec4 FragColor; // 0x00000001 - BGRA to RGBA conversion // 0x00000002 - Font texture // 0x00000004 - Post processing +// 0x00000008 - Clipping void main() { + // Discard any pixels outside the clipping region. + if (0u != (shaderFlags & 8u)) { + if (position.x < clipRegion.x) + discard; + else if (position.y < clipRegion.y) + discard; + else if (position.x > clipRegion.z) + discard; + else if (position.y > clipRegion.w) + discard; + } + vec4 sampledColor = texture(textureSampler, texCoord); // For fonts the alpha information is stored in the red channel.