diff --git a/src/renderer/gl_engine/tvgGlCommon.h b/src/renderer/gl_engine/tvgGlCommon.h index b9f6f0c5..34fb14ad 100644 --- a/src/renderer/gl_engine/tvgGlCommon.h +++ b/src/renderer/gl_engine/tvgGlCommon.h @@ -208,4 +208,9 @@ struct GlGaussianBlur { float extend{}; }; +struct GlEffectParams { + // fill: [0..3]: color + float params[4+4+4]; +}; + #endif /* _TVG_GL_COMMON_H_ */ diff --git a/src/renderer/gl_engine/tvgGlRenderTask.cpp b/src/renderer/gl_engine/tvgGlRenderTask.cpp index d94ec81f..af6dbce5 100644 --- a/src/renderer/gl_engine/tvgGlRenderTask.cpp +++ b/src/renderer/gl_engine/tvgGlRenderTask.cpp @@ -434,3 +434,27 @@ void GlGaussianBlurTask::run() } GL_CHECK(glEnable(GL_BLEND)); } + +void GlEffectColorTransformTask::run() +{ + // const auto vp = getViewport(); + const auto width = mDstFbo->getWidth(); + const auto height = mDstFbo->getHeight(); + // get targets handles and pass to shader + GLuint dstCopyTexId = mDstCopyFbo->getColorTexture(); + GLint srcTextureLoc = getProgram()->getUniformLocation("uSrcTexture"); + addBindResource({ 0, dstCopyTexId, srcTextureLoc }); + + GL_CHECK(glViewport(0, 0, width, height)); + GL_CHECK(glScissor(0, 0, width, height)); + // we need to make full copy of dst to intermediate buffers to be sure, that they are not contained 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)); + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, mDstFbo->getFboId())); + + // run transform + 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/tvgGlRenderTask.h b/src/renderer/gl_engine/tvgGlRenderTask.h index 1ccc0a66..9edfc314 100644 --- a/src/renderer/gl_engine/tvgGlRenderTask.h +++ b/src/renderer/gl_engine/tvgGlRenderTask.h @@ -237,4 +237,17 @@ private: GlRenderTarget* mDstCopyFbo1; }; +class GlEffectColorTransformTask: public GlRenderTask +{ +public: + GlEffectColorTransformTask(GlProgram* program, GlRenderTarget* dstFbo, GlRenderTarget* dstCopyFbo): + GlRenderTask(program), mDstFbo(dstFbo), mDstCopyFbo(dstCopyFbo) {}; + ~GlEffectColorTransformTask() {}; + + void run() override; +private: + GlRenderTarget* mDstFbo; + GlRenderTarget* mDstCopyFbo; +}; + #endif /* _TVG_GL_RENDER_TASK_H_ */ diff --git a/src/renderer/gl_engine/tvgGlRenderer.cpp b/src/renderer/gl_engine/tvgGlRenderer.cpp index 593dddec..3513cf1a 100644 --- a/src/renderer/gl_engine/tvgGlRenderer.cpp +++ b/src/renderer/gl_engine/tvgGlRenderer.cpp @@ -144,6 +144,7 @@ void GlRenderer::initShaders() // effects mPrograms.push(new GlProgram(EFFECT_VERTEX, GAUSSIAN_VERTICAL)); mPrograms.push(new GlProgram(EFFECT_VERTEX, GAUSSIAN_HORIZONTAL)); + mPrograms.push(new GlProgram(EFFECT_VERTEX, EFFECT_FILL)); } @@ -961,6 +962,19 @@ void GlRenderer::effectGaussianBlurUpdate(RenderEffectGaussianBlur* effect, cons } +void GlRenderer::effectFillUpdate(RenderEffectFill* effect, const Matrix& transform) +{ + auto params = (GlEffectParams*)effect->rd; + if (!params) params = tvg::malloc(sizeof(GlEffectParams)); + params->params[0] = effect->color[0] / 255.0f; + params->params[1] = effect->color[1] / 255.0f; + params->params[2] = effect->color[2] / 255.0f; + params->params[3] = effect->color[3] / 255.0f; + effect->rd = params; + effect->valid = true; +} + + bool GlRenderer::effectGaussianBlurRegion(RenderEffectGaussianBlur* effect) { auto gaussianBlur = (GlGaussianBlur*)effect->rd; @@ -984,6 +998,7 @@ void GlRenderer::prepare(RenderEffect* effect, const Matrix& transform) switch (effect->type) { case SceneEffect::GaussianBlur: effectGaussianBlurUpdate(static_cast(effect), transform); break; + case SceneEffect::Fill: effectFillUpdate(static_cast(effect), transform); break; default: break; } effect->valid = true; @@ -994,6 +1009,7 @@ bool GlRenderer::region(RenderEffect* effect) { switch (effect->type) { case SceneEffect::GaussianBlur: return effectGaussianBlurRegion(static_cast(effect)); + case SceneEffect::Fill: return true; default: return false; } return false; @@ -1041,6 +1057,24 @@ bool GlRenderer::render(TVG_UNUSED RenderCompositor* cmp, const RenderEffect* ef gaussianTask->vertTask->setDrawRange(ioffset, 6); // add task to render pipeline pass->addRenderTask(gaussianTask); + } // effect fill + else if (effect->type == SceneEffect::Fill) { + GlProgram* program{}; + if (effect->type == SceneEffect::Fill) program = mPrograms[RT_EffectFill]; + // 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 + 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)}); + task->addVertexLayout(GlVertexLayout{0, 2, 2 * sizeof(float), voffset}); + task->setDrawRange(ioffset, 6); + // add task to render pipeline + pass->addRenderTask(task); } return false; } diff --git a/src/renderer/gl_engine/tvgGlRenderer.h b/src/renderer/gl_engine/tvgGlRenderer.h index c938c6e7..b91e1c4c 100644 --- a/src/renderer/gl_engine/tvgGlRenderer.h +++ b/src/renderer/gl_engine/tvgGlRenderer.h @@ -62,6 +62,10 @@ public: RT_GaussianVert, RT_GaussianHorz, + //RT_DropShadow, + RT_EffectFill, + RT_EffectTint, + RT_EffectTritone, RT_None, }; @@ -120,6 +124,8 @@ private: void endRenderPass(RenderCompositor* cmp); void effectGaussianBlurUpdate(RenderEffectGaussianBlur* effect, const Matrix& transform); + void effectFillUpdate(RenderEffectFill* effect, const Matrix& transform); + bool effectGaussianBlurRegion(RenderEffectGaussianBlur* effect); void flush(); diff --git a/src/renderer/gl_engine/tvgGlShaderSrc.cpp b/src/renderer/gl_engine/tvgGlShaderSrc.cpp index f2101953..7375a8ea 100644 --- a/src/renderer/gl_engine/tvgGlShaderSrc.cpp +++ b/src/renderer/gl_engine/tvgGlShaderSrc.cpp @@ -820,3 +820,20 @@ void main() FragColor = colorSum / weightSum; } )"; + +const char* EFFECT_FILL = 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); + vec4 fill = uParams.params[0]; + FragColor = fill * orig.a * fill.a; +} +)"; diff --git a/src/renderer/gl_engine/tvgGlShaderSrc.h b/src/renderer/gl_engine/tvgGlShaderSrc.h index c1b66f7e..2012851a 100644 --- a/src/renderer/gl_engine/tvgGlShaderSrc.h +++ b/src/renderer/gl_engine/tvgGlShaderSrc.h @@ -57,5 +57,6 @@ extern const char* EXCLUSION_BLEND_FRAG; extern const char* EFFECT_VERTEX; extern const char* GAUSSIAN_VERTICAL; extern const char* GAUSSIAN_HORIZONTAL; +extern const char* EFFECT_FILL; #endif /* _TVG_GL_SHADERSRC_H_ */