diff --git a/src/renderer/gl_engine/tvgGlCommon.h b/src/renderer/gl_engine/tvgGlCommon.h index a2faff60..dab396cd 100644 --- a/src/renderer/gl_engine/tvgGlCommon.h +++ b/src/renderer/gl_engine/tvgGlCommon.h @@ -211,6 +211,7 @@ struct GlGaussianBlur { struct GlEffectParams { // fill: [0..3]: color // tint: [0..2]: black, [4..6]: white, [8]: intensity + // tritone: [0..2]: shadow, [4..6]: midtone, [8..10]: highlight float params[4+4+4]; }; diff --git a/src/renderer/gl_engine/tvgGlRenderTask.cpp b/src/renderer/gl_engine/tvgGlRenderTask.cpp index 5f596985..4d6c1250 100644 --- a/src/renderer/gl_engine/tvgGlRenderTask.cpp +++ b/src/renderer/gl_engine/tvgGlRenderTask.cpp @@ -437,7 +437,6 @@ void GlGaussianBlurTask::run() void GlEffectColorTransformTask::run() { - // const auto vp = getViewport(); const auto width = mDstFbo->getWidth(); const auto height = mDstFbo->getHeight(); // get targets handles and pass to shader @@ -447,7 +446,7 @@ void GlEffectColorTransformTask::run() GL_CHECK(glViewport(0, 0, width, height)); GL_CHECK(glScissor(0, 0, width, height)); - // we need to make full copy of dst to intermidiate buffers to be shure, that they are not containe prev data + // we need to make a full copy of dst to intermediate buffers to be sure that they don’t contain prev data. GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, mDstFbo->getFboId())); GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDstCopyFbo->getResolveFboId())); GL_CHECK(glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST)); @@ -457,4 +456,4 @@ void GlEffectColorTransformTask::run() GL_CHECK(glDisable(GL_BLEND)); GlRenderTask::run(); GL_CHECK(glEnable(GL_BLEND)); -} \ No newline at end of file +} diff --git a/src/renderer/gl_engine/tvgGlRenderer.cpp b/src/renderer/gl_engine/tvgGlRenderer.cpp index 9e98c814..0eb3a64e 100644 --- a/src/renderer/gl_engine/tvgGlRenderer.cpp +++ b/src/renderer/gl_engine/tvgGlRenderer.cpp @@ -146,6 +146,7 @@ void GlRenderer::initShaders() mPrograms.push(new GlProgram(EFFECT_VERTEX, GAUSSIAN_HORIZONTAL)); mPrograms.push(new GlProgram(EFFECT_VERTEX, EFFECT_FILL)); mPrograms.push(new GlProgram(EFFECT_VERTEX, EFFECT_TINT)); + mPrograms.push(new GlProgram(EFFECT_VERTEX, EFFECT_TRITONE)); } @@ -994,6 +995,27 @@ void GlRenderer::effectTintUpdate(RenderEffectTint* effect, const Matrix& transf } +void GlRenderer::effectTritoneUpdate(RenderEffectTritone* effect, const Matrix& transform) +{ + auto params = (GlEffectParams*)effect->rd; + if (!params) params = tvg::malloc(sizeof(GlEffectParams)); + params->params[0] = effect->shadow[0] / 255.0f; + params->params[1] = effect->shadow[1] / 255.0f; + params->params[2] = effect->shadow[2] / 255.0f; + params->params[3] = 0.0f; + params->params[4] = effect->midtone[0] / 255.0f; + params->params[5] = effect->midtone[1] / 255.0f; + params->params[6] = effect->midtone[2] / 255.0f; + params->params[7] = 0.0f; + params->params[8] = effect->highlight[0] / 255.0f; + params->params[9] = effect->highlight[1] / 255.0f; + params->params[10] = effect->highlight[2] / 255.0f; + params->params[11] = 0.0f; + effect->rd = params; + effect->valid = true; +} + + bool GlRenderer::effectGaussianBlurRegion(RenderEffectGaussianBlur* effect) { auto gaussianBlur = (GlGaussianBlur*)effect->rd; @@ -1019,6 +1041,7 @@ void GlRenderer::prepare(RenderEffect* effect, const Matrix& transform) case SceneEffect::GaussianBlur: effectGaussianBlurUpdate(static_cast(effect), transform); break; case SceneEffect::Fill: effectFillUpdate(static_cast(effect), transform); break; case SceneEffect::Tint: effectTintUpdate(static_cast(effect), transform); break; + case SceneEffect::Tritone: effectTritoneUpdate(static_cast(effect), transform); break; default: break; } effect->valid = true; @@ -1029,8 +1052,9 @@ bool GlRenderer::region(RenderEffect* effect) { switch (effect->type) { case SceneEffect::GaussianBlur: return effectGaussianBlurRegion(static_cast(effect)); - case SceneEffect::Fill: return true; - case SceneEffect::Tint: return true; + case SceneEffect::Fill: + case SceneEffect::Tint: + case SceneEffect::Tritone: return true; default: return false; } return false; @@ -1079,17 +1103,19 @@ bool GlRenderer::render(TVG_UNUSED RenderCompositor* cmp, const RenderEffect* ef // add task to render pipeline pass->addRenderTask(gaussianTask); } // effect fill - else if ((effect->type == SceneEffect::Fill) || (effect->type == SceneEffect::Tint)) { + else if ((effect->type == SceneEffect::Fill) || (effect->type == SceneEffect::Tint) || (effect->type == SceneEffect::Tritone)) { GlProgram* program{}; if (effect->type == SceneEffect::Fill) program = mPrograms[RT_EffectFill]; else if (effect->type == SceneEffect::Tint) program = mPrograms[RT_EffectTint]; + else if (effect->type == SceneEffect::Tritone) program = mPrograms[RT_EffectTritone]; + else return false; // get current and intermidiate framebuffers auto dstFbo = pass->getFbo(); auto dstCopyFbo = mBlendPool[0]->getRenderTarget(vp); // add uniform data auto params = (GlEffectParams*)(effect->rd); auto paramsOffset = mGpuBuffer.push(params, sizeof(GlEffectParams), true); - // create gaussian blur tasks + // create and setup task auto task = new GlEffectColorTransformTask(program, dstFbo, dstCopyFbo); task->setViewport({0, 0, vp.w, vp.h}); task->addBindResource(GlBindingResource{0, program->getUniformBlockIndex("Params"), mGpuBuffer.getBufferId(), paramsOffset, sizeof(GlEffectParams)}); diff --git a/src/renderer/gl_engine/tvgGlRenderer.h b/src/renderer/gl_engine/tvgGlRenderer.h index 21b24db3..c736740c 100644 --- a/src/renderer/gl_engine/tvgGlRenderer.h +++ b/src/renderer/gl_engine/tvgGlRenderer.h @@ -126,6 +126,7 @@ private: void effectGaussianBlurUpdate(RenderEffectGaussianBlur* effect, const Matrix& transform); void effectFillUpdate(RenderEffectFill* effect, const Matrix& transform); void effectTintUpdate(RenderEffectTint* effect, const Matrix& transform); + void effectTritoneUpdate(RenderEffectTritone* effect, const Matrix& transform); bool effectGaussianBlurRegion(RenderEffectGaussianBlur* effect); diff --git a/src/renderer/gl_engine/tvgGlShaderSrc.cpp b/src/renderer/gl_engine/tvgGlShaderSrc.cpp index ecd9fdee..ef78e58b 100644 --- a/src/renderer/gl_engine/tvgGlShaderSrc.cpp +++ b/src/renderer/gl_engine/tvgGlShaderSrc.cpp @@ -776,7 +776,7 @@ void main() for (int y = -radius; y <= radius; ++y) { float weight = gaussian(float(y), sigma); - vec2 offset = min(vec2(1.0), vec2(0.0, float(y) * texelSize.y)); + vec2 offset = vec2(0.0, float(y) * texelSize.y); colorSum += texture(uSrcTexture, vUV + offset) * weight; weightSum += weight; } @@ -812,8 +812,7 @@ void main() for (int y = -radius; y <= radius; ++y) { float weight = gaussian(float(y), sigma); - //vec2 offset = vec2(float(y) * texelSize.x, 0.0); - vec2 offset = min(vec2(1.0), vec2(float(y) * texelSize.x, 0.0)); + vec2 offset = vec2(float(y) * texelSize.x, 0.0); colorSum += texture(uSrcTexture, vUV + offset) * weight; weightSum += weight; } @@ -858,3 +857,29 @@ void main() FragColor = mix(orig, mix(white, black, luma), intens) * orig.a; } )"; + +const char* EFFECT_TRITONE = R"( +uniform sampler2D uSrcTexture; +layout(std140) uniform Params { + vec4 params[3]; +} uParams; + +in vec2 vUV; +out vec4 FragColor; + +void main() +{ + vec4 orig = texture(uSrcTexture, vUV); + float luma = dot(orig.rgb, vec3(0.2125, 0.7154, 0.0721)); + vec4 shadow = uParams.params[0]; + vec4 midtone = uParams.params[1]; + vec4 highlight = uParams.params[2]; + + FragColor = vec4( + luma >= 0.5f ? mix(midtone.r, highlight.r, (luma - 0.5f)*2.0f) : mix(shadow.r, midtone.r, luma * 2.0f), + luma >= 0.5f ? mix(midtone.g, highlight.g, (luma - 0.5f)*2.0f) : mix(shadow.g, midtone.g, luma * 2.0f), + luma >= 0.5f ? mix(midtone.b, highlight.b, (luma - 0.5f)*2.0f) : mix(shadow.b, midtone.b, luma * 2.0f), + luma >= 0.5f ? mix(midtone.a, highlight.a, (luma - 0.5f)*2.0f) : mix(shadow.a, midtone.a, luma * 2.0f) + ) * orig.a; +} +)"; diff --git a/src/renderer/gl_engine/tvgGlShaderSrc.h b/src/renderer/gl_engine/tvgGlShaderSrc.h index bf8225f9..1bf5ce67 100644 --- a/src/renderer/gl_engine/tvgGlShaderSrc.h +++ b/src/renderer/gl_engine/tvgGlShaderSrc.h @@ -59,5 +59,6 @@ extern const char* GAUSSIAN_VERTICAL; extern const char* GAUSSIAN_HORIZONTAL; extern const char* EFFECT_FILL; extern const char* EFFECT_TINT; +extern const char* EFFECT_TRITONE; #endif /* _TVG_GL_SHADERSRC_H_ */