mirror of
https://github.com/thorvg/thorvg.git
synced 2025-07-18 20:36:43 +00:00
gl_engine: revised the effect logic
Some checks are pending
Android / build_x86_64 (push) Waiting to run
Android / build_aarch64 (push) Waiting to run
iOS / build_x86_64 (push) Waiting to run
iOS / build_arm64 (push) Waiting to run
macOS / build (push) Waiting to run
macOS / compact_test (push) Waiting to run
macOS / unit_test (push) Waiting to run
Ubuntu / build (push) Waiting to run
Ubuntu / compact_test (push) Waiting to run
Ubuntu / unit_test (push) Waiting to run
Windows / build (push) Waiting to run
Windows / compact_test (push) Waiting to run
Windows / unit_test (push) Waiting to run
Some checks are pending
Android / build_x86_64 (push) Waiting to run
Android / build_aarch64 (push) Waiting to run
iOS / build_x86_64 (push) Waiting to run
iOS / build_arm64 (push) Waiting to run
macOS / build (push) Waiting to run
macOS / compact_test (push) Waiting to run
macOS / unit_test (push) Waiting to run
Ubuntu / build (push) Waiting to run
Ubuntu / compact_test (push) Waiting to run
Ubuntu / unit_test (push) Waiting to run
Windows / build (push) Waiting to run
Windows / compact_test (push) Waiting to run
Windows / unit_test (push) Waiting to run
- consolidated the effect implementation from renderer - applied the deferred initialization
This commit is contained in:
parent
a80b0aa188
commit
52f23f6acd
7 changed files with 435 additions and 281 deletions
|
@ -1,6 +1,7 @@
|
||||||
source_file = [
|
source_file = [
|
||||||
'tvgGl.h',
|
'tvgGl.h',
|
||||||
'tvgGlCommon.h',
|
'tvgGlCommon.h',
|
||||||
|
'tvgGlEffect.h',
|
||||||
'tvgGlGpuBuffer.h',
|
'tvgGlGpuBuffer.h',
|
||||||
'tvgGlProgram.h',
|
'tvgGlProgram.h',
|
||||||
'tvgGlRenderer.h',
|
'tvgGlRenderer.h',
|
||||||
|
@ -10,6 +11,7 @@ source_file = [
|
||||||
'tvgGlShader.h',
|
'tvgGlShader.h',
|
||||||
'tvgGlShaderSrc.h',
|
'tvgGlShaderSrc.h',
|
||||||
'tvgGl.cpp',
|
'tvgGl.cpp',
|
||||||
|
'tvgGlEffect.cpp',
|
||||||
'tvgGlGeometry.cpp',
|
'tvgGlGeometry.cpp',
|
||||||
'tvgGlGpuBuffer.cpp',
|
'tvgGlGpuBuffer.cpp',
|
||||||
'tvgGlProgram.cpp',
|
'tvgGlProgram.cpp',
|
||||||
|
|
|
@ -161,24 +161,5 @@ struct GlCompositor : RenderCompositor
|
||||||
GlCompositor(const RenderRegion& box) : bbox(box) {}
|
GlCompositor(const RenderRegion& box) : bbox(box) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GL_GAUSSIAN_MAX_LEVEL 3
|
|
||||||
struct GlGaussianBlur {
|
|
||||||
int level{};
|
|
||||||
float sigma{};
|
|
||||||
float scale{};
|
|
||||||
float extend{};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GlDropShadow: GlGaussianBlur {
|
|
||||||
float color[4];
|
|
||||||
float offset[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
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 [11]: blender
|
|
||||||
float params[4+4+4];
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* _TVG_GL_COMMON_H_ */
|
#endif /* _TVG_GL_COMMON_H_ */
|
358
src/renderer/gl_engine/tvgGlEffect.cpp
Normal file
358
src/renderer/gl_engine/tvgGlEffect.cpp
Normal file
|
@ -0,0 +1,358 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tvgMath.h"
|
||||||
|
#include "tvgGlRenderTask.h"
|
||||||
|
#include "tvgGlGpuBuffer.h"
|
||||||
|
#include "tvgGlRenderPass.h"
|
||||||
|
#include "tvgGlShaderSrc.h"
|
||||||
|
#include "tvgGlEffect.h"
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* Gaussian Blur */
|
||||||
|
/************************************************************************/
|
||||||
|
|
||||||
|
#define GL_GAUSSIAN_MAX_LEVEL 3
|
||||||
|
|
||||||
|
struct GlGaussianBlur {
|
||||||
|
int level{};
|
||||||
|
float sigma{};
|
||||||
|
float scale{};
|
||||||
|
float extend{};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
bool GlEffect::region(RenderEffectGaussianBlur* effect)
|
||||||
|
{
|
||||||
|
auto gaussianBlur = (GlGaussianBlur*)effect->rd;
|
||||||
|
if (effect->direction != 2) {
|
||||||
|
effect->extend.min.x = -gaussianBlur->extend;
|
||||||
|
effect->extend.max.x = +gaussianBlur->extend;
|
||||||
|
}
|
||||||
|
if (effect->direction != 1) {
|
||||||
|
effect->extend.min.y = -gaussianBlur->extend;
|
||||||
|
effect->extend.max.y = +gaussianBlur->extend;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void GlEffect::update(RenderEffectGaussianBlur* effect, const Matrix& transform)
|
||||||
|
{
|
||||||
|
GlGaussianBlur* blur = (GlGaussianBlur*)effect->rd;
|
||||||
|
if (!blur) blur = tvg::malloc<GlGaussianBlur*>(sizeof(GlGaussianBlur));
|
||||||
|
blur->sigma = effect->sigma;
|
||||||
|
blur->scale = std::sqrt(transform.e11 * transform.e11 + transform.e12 * transform.e12);
|
||||||
|
blur->extend = 2 * blur->sigma * blur->scale;
|
||||||
|
blur->level = int(GL_GAUSSIAN_MAX_LEVEL * ((effect->quality - 1) * 0.01f)) + 1;
|
||||||
|
effect->rd = blur;
|
||||||
|
effect->valid = (blur->extend > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GlRenderTask* GlEffect::render(RenderEffectGaussianBlur* effect, GlRenderTarget* dstFbo, Array<GlRenderTargetPool*>& blendPool, const RenderRegion& vp, uint32_t voffset, uint32_t ioffset)
|
||||||
|
{
|
||||||
|
if (!pBlurV) pBlurV = new GlProgram(EFFECT_VERTEX, GAUSSIAN_VERTICAL);
|
||||||
|
if (!pBlurH) pBlurH = new GlProgram(EFFECT_VERTEX, GAUSSIAN_HORIZONTAL);
|
||||||
|
|
||||||
|
// get current and intermidiate framebuffers
|
||||||
|
auto dstCopyFbo0 = blendPool[0]->getRenderTarget(vp);
|
||||||
|
auto dstCopyFbo1 = blendPool[1]->getRenderTarget(vp);
|
||||||
|
|
||||||
|
// add uniform data
|
||||||
|
auto blurOffset = gpuBuffer->push((GlGaussianBlur*)(effect->rd), sizeof(GlGaussianBlur), true);
|
||||||
|
|
||||||
|
// create gaussian blur tasks
|
||||||
|
auto task = new GlGaussianBlurTask(dstFbo, dstCopyFbo0, dstCopyFbo1);
|
||||||
|
task->effect = effect;
|
||||||
|
task->setViewport({{0, 0}, {vp.sw(), vp.sh()}});
|
||||||
|
// horizontal blur task and geometry
|
||||||
|
task->horzTask = new GlRenderTask(pBlurH);
|
||||||
|
task->horzTask->addBindResource(GlBindingResource{0, pBlurH->getUniformBlockIndex("Gaussian"), gpuBuffer->getBufferId(), blurOffset, sizeof(GlGaussianBlur)});
|
||||||
|
task->horzTask->addVertexLayout(GlVertexLayout{0, 2, 2 * sizeof(float), voffset});
|
||||||
|
task->horzTask->setDrawRange(ioffset, 6);
|
||||||
|
// vertical blur task and geometry
|
||||||
|
task->vertTask = new GlRenderTask(pBlurV);
|
||||||
|
task->vertTask->addBindResource(GlBindingResource{0, pBlurV->getUniformBlockIndex("Gaussian"), gpuBuffer->getBufferId(), blurOffset, sizeof(GlGaussianBlur)});
|
||||||
|
task->vertTask->addVertexLayout(GlVertexLayout{0, 2, 2 * sizeof(float), voffset});
|
||||||
|
task->vertTask->setDrawRange(ioffset, 6);
|
||||||
|
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* DropShadow */
|
||||||
|
/************************************************************************/
|
||||||
|
|
||||||
|
struct GlDropShadow: GlGaussianBlur {
|
||||||
|
float color[4];
|
||||||
|
float offset[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
bool GlEffect::region(RenderEffectDropShadow* effect)
|
||||||
|
{
|
||||||
|
auto gaussianBlur = (GlDropShadow*)effect->rd;
|
||||||
|
effect->extend.min.x = -gaussianBlur->extend;
|
||||||
|
effect->extend.max.x = +gaussianBlur->extend;
|
||||||
|
effect->extend.min.y = -gaussianBlur->extend;
|
||||||
|
effect->extend.max.y = +gaussianBlur->extend;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void GlEffect::update(RenderEffectDropShadow* effect, const Matrix& transform)
|
||||||
|
{
|
||||||
|
GlDropShadow* dropShadow = (GlDropShadow*)effect->rd;
|
||||||
|
if (!dropShadow) dropShadow = tvg::malloc<GlDropShadow*>(sizeof(GlDropShadow));
|
||||||
|
const float sigma = effect->sigma;
|
||||||
|
const float scale = std::sqrt(transform.e11 * transform.e11 + transform.e12 * transform.e12);
|
||||||
|
const float radian = tvg::deg2rad(90.0f - effect->angle);
|
||||||
|
const Point offset = {
|
||||||
|
-effect->distance * cosf(radian) * scale,
|
||||||
|
-effect->distance * sinf(radian) * scale
|
||||||
|
};
|
||||||
|
dropShadow->sigma = sigma;
|
||||||
|
dropShadow->scale = scale;
|
||||||
|
dropShadow->level = int(GL_GAUSSIAN_MAX_LEVEL * ((effect->quality - 1) * 0.01f)) + 1;
|
||||||
|
dropShadow->color[3] = effect->color[3] / 255.0f;
|
||||||
|
//Drop shadow effect applies blending in the shader (GL_BLEND disabled), so the color should be premultiplied:
|
||||||
|
dropShadow->color[0] = effect->color[0] / 255.0f * dropShadow->color[3];
|
||||||
|
dropShadow->color[1] = effect->color[1] / 255.0f * dropShadow->color[3];
|
||||||
|
dropShadow->color[2] = effect->color[2] / 255.0f * dropShadow->color[3];
|
||||||
|
dropShadow->offset[0] = offset.x;
|
||||||
|
dropShadow->offset[1] = offset.y;
|
||||||
|
dropShadow->extend = 2 * std::max(sigma * scale + std::abs(offset.x), sigma * scale + std::abs(offset.y));
|
||||||
|
effect->rd = dropShadow;
|
||||||
|
effect->valid = (dropShadow->extend > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GlRenderTask* GlEffect::render(RenderEffectDropShadow* effect, GlRenderTarget* dstFbo, Array<GlRenderTargetPool*>& blendPool, const RenderRegion& vp, uint32_t voffset, uint32_t ioffset)
|
||||||
|
{
|
||||||
|
if (!pBlurV) pBlurV = new GlProgram(EFFECT_VERTEX, GAUSSIAN_VERTICAL);
|
||||||
|
if (!pBlurH) pBlurH = new GlProgram(EFFECT_VERTEX, GAUSSIAN_HORIZONTAL);
|
||||||
|
if (!pDropShadow) pDropShadow = new GlProgram(EFFECT_VERTEX, EFFECT_DROPSHADOW);
|
||||||
|
|
||||||
|
// get current and intermidiate framebuffers
|
||||||
|
auto dstCopyFbo0 = blendPool[0]->getRenderTarget(vp);
|
||||||
|
auto dstCopyFbo1 = blendPool[1]->getRenderTarget(vp);
|
||||||
|
|
||||||
|
// add uniform data
|
||||||
|
GlDropShadow* params = (GlDropShadow*)(effect->rd);
|
||||||
|
auto paramsOffset = gpuBuffer->push(params, sizeof(GlDropShadow), true);
|
||||||
|
|
||||||
|
// create gaussian blur tasks
|
||||||
|
auto task = new GlEffectDropShadowTask(pDropShadow, dstFbo, dstCopyFbo0, dstCopyFbo1);
|
||||||
|
task->effect = (RenderEffectDropShadow*)effect;
|
||||||
|
task->setViewport({{0, 0}, {vp.sw(), vp.sh()}});
|
||||||
|
task->addBindResource(GlBindingResource{0, pDropShadow->getUniformBlockIndex("DropShadow"), gpuBuffer->getBufferId(), paramsOffset, sizeof(GlDropShadow)});
|
||||||
|
task->addVertexLayout(GlVertexLayout{0, 2, 2 * sizeof(float), voffset});
|
||||||
|
task->setDrawRange(ioffset, 6);
|
||||||
|
|
||||||
|
// horizontal blur task and geometry
|
||||||
|
task->horzTask = new GlRenderTask(pBlurH);
|
||||||
|
task->horzTask->addBindResource(GlBindingResource{0, pBlurH->getUniformBlockIndex("Gaussian"), gpuBuffer->getBufferId(), paramsOffset, sizeof(GlGaussianBlur)});
|
||||||
|
task->horzTask->addVertexLayout(GlVertexLayout{0, 2, 2 * sizeof(float), voffset});
|
||||||
|
task->horzTask->setDrawRange(ioffset, 6);
|
||||||
|
|
||||||
|
// vertical blur task and geometry
|
||||||
|
task->vertTask = new GlRenderTask(pBlurV);
|
||||||
|
task->vertTask->addBindResource(GlBindingResource{0, pBlurV->getUniformBlockIndex("Gaussian"), gpuBuffer->getBufferId(), paramsOffset, sizeof(GlGaussianBlur)});
|
||||||
|
task->vertTask->addVertexLayout(GlVertexLayout{0, 2, 2 * sizeof(float), voffset});
|
||||||
|
task->vertTask->setDrawRange(ioffset, 6);
|
||||||
|
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* ColorReplacement */
|
||||||
|
/************************************************************************/
|
||||||
|
|
||||||
|
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 [11]: blender
|
||||||
|
float params[4+4+4];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void GlEffect::update(RenderEffectFill* effect, const Matrix& transform)
|
||||||
|
{
|
||||||
|
auto params = (GlEffectParams*)effect->rd;
|
||||||
|
if (!params) params = tvg::malloc<GlEffectParams*>(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GlEffect::update(RenderEffectTint* effect, const Matrix& transform)
|
||||||
|
{
|
||||||
|
effect->valid = (effect->intensity > 0);
|
||||||
|
if (!effect->valid) return;
|
||||||
|
|
||||||
|
auto params = (GlEffectParams*)effect->rd;
|
||||||
|
if (!params) params = tvg::malloc<GlEffectParams*>(sizeof(GlEffectParams));
|
||||||
|
params->params[0] = effect->black[0] / 255.0f;
|
||||||
|
params->params[1] = effect->black[1] / 255.0f;
|
||||||
|
params->params[2] = effect->black[2] / 255.0f;
|
||||||
|
params->params[3] = 0.0f;
|
||||||
|
params->params[4] = effect->white[0] / 255.0f;
|
||||||
|
params->params[5] = effect->white[1] / 255.0f;
|
||||||
|
params->params[6] = effect->white[2] / 255.0f;
|
||||||
|
params->params[7] = 0.0f;
|
||||||
|
params->params[8] = effect->intensity / 255.0f;
|
||||||
|
effect->rd = params;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GlEffect::update(RenderEffectTritone* effect, const Matrix& transform)
|
||||||
|
{
|
||||||
|
effect->valid = (effect->blender < 255);
|
||||||
|
if (!effect->valid) return;
|
||||||
|
|
||||||
|
auto params = (GlEffectParams*)effect->rd;
|
||||||
|
if (!params) params = tvg::malloc<GlEffectParams*>(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] = effect->blender / 255.0f;
|
||||||
|
effect->rd = params;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GlRenderTask* GlEffect::render(RenderEffect* effect, GlRenderTarget* dstFbo, Array<GlRenderTargetPool*>& blendPool, const RenderRegion& vp, uint32_t voffset, uint32_t ioffset)
|
||||||
|
{
|
||||||
|
//common color replacement effects
|
||||||
|
GlProgram* program = nullptr;
|
||||||
|
if (effect->type == SceneEffect::Fill) {
|
||||||
|
if (!pFill) pFill = new GlProgram(EFFECT_VERTEX, EFFECT_FILL);
|
||||||
|
program = pFill;
|
||||||
|
} else if (effect->type == SceneEffect::Tint) {
|
||||||
|
if (!pTint) pTint = new GlProgram(EFFECT_VERTEX, EFFECT_TINT);
|
||||||
|
program = pTint;
|
||||||
|
} else if (effect->type == SceneEffect::Tritone) {
|
||||||
|
if (!pTritone) pTritone = new GlProgram(EFFECT_VERTEX, EFFECT_TRITONE);
|
||||||
|
program = pTritone;
|
||||||
|
} else return nullptr;
|
||||||
|
|
||||||
|
// get current and intermidiate framebuffers
|
||||||
|
auto dstCopyFbo = blendPool[0]->getRenderTarget(vp);
|
||||||
|
|
||||||
|
// add uniform data
|
||||||
|
auto params = (GlEffectParams*)(effect->rd);
|
||||||
|
auto paramsOffset = gpuBuffer->push(params, sizeof(GlEffectParams), true);
|
||||||
|
|
||||||
|
// create and setup task
|
||||||
|
auto task = new GlEffectColorTransformTask(program, dstFbo, dstCopyFbo);
|
||||||
|
task->setViewport({{0, 0}, {vp.sw(), vp.sh()}});
|
||||||
|
task->addBindResource(GlBindingResource{0, program->getUniformBlockIndex("Params"), gpuBuffer->getBufferId(), paramsOffset, sizeof(GlEffectParams)});
|
||||||
|
task->addVertexLayout(GlVertexLayout{0, 2, 2 * sizeof(float), voffset});
|
||||||
|
task->setDrawRange(ioffset, 6);
|
||||||
|
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* External Class Implementation */
|
||||||
|
/************************************************************************/
|
||||||
|
|
||||||
|
void GlEffect::update(RenderEffect* effect, const Matrix& transform)
|
||||||
|
{
|
||||||
|
switch (effect->type) {
|
||||||
|
case SceneEffect::GaussianBlur: update(static_cast<RenderEffectGaussianBlur*>(effect), transform); break;
|
||||||
|
case SceneEffect::DropShadow : update(static_cast<RenderEffectDropShadow*>(effect), transform); break;
|
||||||
|
case SceneEffect::Fill: update(static_cast<RenderEffectFill*>(effect), transform); break;
|
||||||
|
case SceneEffect::Tint: update(static_cast<RenderEffectTint*>(effect), transform); break;
|
||||||
|
case SceneEffect::Tritone: update(static_cast<RenderEffectTritone*>(effect), transform); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool GlEffect::region(RenderEffect* effect)
|
||||||
|
{
|
||||||
|
switch (effect->type) {
|
||||||
|
case SceneEffect::GaussianBlur: return region(static_cast<RenderEffectGaussianBlur*>(effect));
|
||||||
|
case SceneEffect::DropShadow : return region(static_cast<RenderEffectDropShadow*>(effect));
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool GlEffect::render(RenderEffect* effect, GlRenderPass* pass, Array<GlRenderTargetPool*>& blendPool)
|
||||||
|
{
|
||||||
|
if (pass->isEmpty()) return false;
|
||||||
|
auto vp = pass->getViewport();
|
||||||
|
|
||||||
|
// add render geometry
|
||||||
|
const float vdata[] = {-1.0f, +1.0f, +1.0f, +1.0f, +1.0f, -1.0f, -1.0f, -1.0f};
|
||||||
|
const uint32_t idata[] = { 0, 1, 2, 0, 2, 3 };
|
||||||
|
auto voffset = gpuBuffer->push((void*)vdata, sizeof(vdata));
|
||||||
|
auto ioffset = gpuBuffer->pushIndex((void*)idata, sizeof(idata));
|
||||||
|
GlRenderTask* output = nullptr;
|
||||||
|
|
||||||
|
if (effect->type == SceneEffect::GaussianBlur) {
|
||||||
|
output = render(static_cast<RenderEffectGaussianBlur*>(effect), pass->getFbo(), blendPool, vp, voffset, ioffset);
|
||||||
|
} else if (effect->type == SceneEffect::DropShadow) {
|
||||||
|
output = render(static_cast<RenderEffectDropShadow*>(effect), pass->getFbo(), blendPool, vp, voffset, ioffset);
|
||||||
|
} else {
|
||||||
|
output = render(effect, pass->getFbo(), blendPool, vp, voffset, ioffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!output) return false;
|
||||||
|
|
||||||
|
pass->addRenderTask(output);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GlEffect::GlEffect(GlStageBuffer* buffer) : gpuBuffer(buffer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GlEffect::~GlEffect()
|
||||||
|
{
|
||||||
|
delete(pBlurV);
|
||||||
|
delete(pBlurH);
|
||||||
|
delete(pDropShadow);
|
||||||
|
delete(pFill);
|
||||||
|
delete(pTint);
|
||||||
|
delete(pTritone);
|
||||||
|
}
|
64
src/renderer/gl_engine/tvgGlEffect.h
Normal file
64
src/renderer/gl_engine/tvgGlEffect.h
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TVG_GL_EFFECT_H_
|
||||||
|
#define _TVG_GL_EFFECT_H_
|
||||||
|
|
||||||
|
#include "tvgRender.h"
|
||||||
|
#include "tvgGlProgram.h"
|
||||||
|
|
||||||
|
|
||||||
|
class GlEffect
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
GlStageBuffer* gpuBuffer; //shared resource with GlRenderer
|
||||||
|
|
||||||
|
GlProgram* pBlurV{};
|
||||||
|
GlProgram* pBlurH{};
|
||||||
|
GlProgram* pDropShadow{};
|
||||||
|
GlProgram* pFill{};
|
||||||
|
GlProgram* pTint{};
|
||||||
|
GlProgram* pTritone{};
|
||||||
|
|
||||||
|
void update(RenderEffectGaussianBlur* effect, const Matrix& transform);
|
||||||
|
void update(RenderEffectDropShadow* effect, const Matrix& transform);
|
||||||
|
void update(RenderEffectFill* effect, const Matrix& transform);
|
||||||
|
void update(RenderEffectTint* effect, const Matrix& transform);
|
||||||
|
void update(RenderEffectTritone* effect, const Matrix& transform);
|
||||||
|
|
||||||
|
bool region(RenderEffectGaussianBlur* effect);
|
||||||
|
bool region(RenderEffectDropShadow* effect);
|
||||||
|
|
||||||
|
GlRenderTask* render(RenderEffectGaussianBlur* effect, GlRenderTarget* dstFbo, Array<GlRenderTargetPool*>& blendPool, const RenderRegion& vp, uint32_t voffset, uint32_t ioffset);
|
||||||
|
GlRenderTask* render(RenderEffectDropShadow* effect, GlRenderTarget* dstFbo, Array<GlRenderTargetPool*>& blendPool, const RenderRegion& vp, uint32_t voffset, uint32_t ioffset);
|
||||||
|
GlRenderTask* render(RenderEffect* effect, GlRenderTarget* dstFbo, Array<GlRenderTargetPool*>& blendPool, const RenderRegion& vp, uint32_t voffset, uint32_t ioffset);
|
||||||
|
|
||||||
|
public:
|
||||||
|
GlEffect(GlStageBuffer* buffer);
|
||||||
|
~GlEffect();
|
||||||
|
|
||||||
|
void update(RenderEffect* effect, const Matrix& transform);
|
||||||
|
bool region(RenderEffect* effect);
|
||||||
|
bool render(RenderEffect* effect, GlRenderPass* pass, Array<GlRenderTargetPool*>& blendPool);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _TVG_GL_EFFECT_H_ */
|
|
@ -21,13 +21,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include "tvgFill.h"
|
||||||
#include "tvgGlCommon.h"
|
#include "tvgGlCommon.h"
|
||||||
#include "tvgGlRenderer.h"
|
#include "tvgGlRenderer.h"
|
||||||
#include "tvgGlGpuBuffer.h"
|
#include "tvgGlGpuBuffer.h"
|
||||||
#include "tvgGlRenderTask.h"
|
#include "tvgGlRenderTask.h"
|
||||||
#include "tvgGlProgram.h"
|
#include "tvgGlProgram.h"
|
||||||
#include "tvgGlShaderSrc.h"
|
#include "tvgGlShaderSrc.h"
|
||||||
#include "tvgFill.h"
|
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* Internal Class Implementation */
|
/* Internal Class Implementation */
|
||||||
|
@ -79,7 +80,7 @@ void GlRenderer::currentContext()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GlRenderer::GlRenderer()
|
GlRenderer::GlRenderer() : mEffect(GlEffect(&mGpuBuffer))
|
||||||
{
|
{
|
||||||
++rendererCnt;
|
++rendererCnt;
|
||||||
}
|
}
|
||||||
|
@ -92,8 +93,6 @@ GlRenderer::~GlRenderer()
|
||||||
flush();
|
flush();
|
||||||
|
|
||||||
ARRAY_FOREACH(p, mPrograms) delete(*p);
|
ARRAY_FOREACH(p, mPrograms) delete(*p);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -159,14 +158,6 @@ void GlRenderer::initShaders()
|
||||||
mPrograms.push(new GlProgram(MASK_VERT_SHADER, SOFT_LIGHT_BLEND_FRAG));
|
mPrograms.push(new GlProgram(MASK_VERT_SHADER, SOFT_LIGHT_BLEND_FRAG));
|
||||||
mPrograms.push(new GlProgram(MASK_VERT_SHADER, DIFFERENCE_BLEND_FRAG));
|
mPrograms.push(new GlProgram(MASK_VERT_SHADER, DIFFERENCE_BLEND_FRAG));
|
||||||
mPrograms.push(new GlProgram(MASK_VERT_SHADER, EXCLUSION_BLEND_FRAG));
|
mPrograms.push(new GlProgram(MASK_VERT_SHADER, EXCLUSION_BLEND_FRAG));
|
||||||
|
|
||||||
// effects
|
|
||||||
mPrograms.push(new GlProgram(EFFECT_VERTEX, GAUSSIAN_VERTICAL));
|
|
||||||
mPrograms.push(new GlProgram(EFFECT_VERTEX, GAUSSIAN_HORIZONTAL));
|
|
||||||
mPrograms.push(new GlProgram(EFFECT_VERTEX, EFFECT_DROPSHADOW));
|
|
||||||
mPrograms.push(new GlProgram(EFFECT_VERTEX, EFFECT_FILL));
|
|
||||||
mPrograms.push(new GlProgram(EFFECT_VERTEX, EFFECT_TINT));
|
|
||||||
mPrograms.push(new GlProgram(EFFECT_VERTEX, EFFECT_TRITONE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -946,254 +937,25 @@ bool GlRenderer::endComposite(RenderCompositor* cmp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GlRenderer::effectGaussianBlurUpdate(RenderEffectGaussianBlur* effect, const Matrix& transform)
|
|
||||||
{
|
|
||||||
GlGaussianBlur* blur = (GlGaussianBlur*)effect->rd;
|
|
||||||
if (!blur) blur = tvg::malloc<GlGaussianBlur*>(sizeof(GlGaussianBlur));
|
|
||||||
blur->sigma = effect->sigma;
|
|
||||||
blur->scale = std::sqrt(transform.e11 * transform.e11 + transform.e12 * transform.e12);
|
|
||||||
blur->extend = 2 * blur->sigma * blur->scale;
|
|
||||||
blur->level = int(GL_GAUSSIAN_MAX_LEVEL * ((effect->quality - 1) * 0.01f)) + 1;
|
|
||||||
effect->rd = blur;
|
|
||||||
effect->valid = (blur->extend > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void GlRenderer::effectDropShadowUpdate(RenderEffectDropShadow* effect, const Matrix& transform)
|
|
||||||
{
|
|
||||||
GlDropShadow* dropShadow = (GlDropShadow*)effect->rd;
|
|
||||||
if (!dropShadow) dropShadow = tvg::malloc<GlDropShadow*>(sizeof(GlDropShadow));
|
|
||||||
const float sigma = effect->sigma;
|
|
||||||
const float scale = std::sqrt(transform.e11 * transform.e11 + transform.e12 * transform.e12);
|
|
||||||
const float radian = tvg::deg2rad(90.0f - effect->angle);
|
|
||||||
const Point offset = {
|
|
||||||
-effect->distance * cosf(radian) * scale,
|
|
||||||
-effect->distance * sinf(radian) * scale
|
|
||||||
};
|
|
||||||
dropShadow->sigma = sigma;
|
|
||||||
dropShadow->scale = scale;
|
|
||||||
dropShadow->level = int(GL_GAUSSIAN_MAX_LEVEL * ((effect->quality - 1) * 0.01f)) + 1;
|
|
||||||
dropShadow->color[3] = effect->color[3] / 255.0f;
|
|
||||||
//Drop shadow effect applies blending in the shader (GL_BLEND disabled), so the color should be premultiplied:
|
|
||||||
dropShadow->color[0] = effect->color[0] / 255.0f * dropShadow->color[3];
|
|
||||||
dropShadow->color[1] = effect->color[1] / 255.0f * dropShadow->color[3];
|
|
||||||
dropShadow->color[2] = effect->color[2] / 255.0f * dropShadow->color[3];
|
|
||||||
dropShadow->offset[0] = offset.x;
|
|
||||||
dropShadow->offset[1] = offset.y;
|
|
||||||
dropShadow->extend = 2 * std::max(sigma * scale + std::abs(offset.x), sigma * scale + std::abs(offset.y));
|
|
||||||
effect->rd = dropShadow;
|
|
||||||
effect->valid = (dropShadow->extend > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void GlRenderer::effectFillUpdate(RenderEffectFill* effect, const Matrix& transform)
|
|
||||||
{
|
|
||||||
auto params = (GlEffectParams*)effect->rd;
|
|
||||||
if (!params) params = tvg::malloc<GlEffectParams*>(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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void GlRenderer::effectTintUpdate(RenderEffectTint* effect, const Matrix& transform)
|
|
||||||
{
|
|
||||||
effect->valid = (effect->intensity > 0);
|
|
||||||
if (!effect->valid) return;
|
|
||||||
|
|
||||||
auto params = (GlEffectParams*)effect->rd;
|
|
||||||
if (!params) params = tvg::malloc<GlEffectParams*>(sizeof(GlEffectParams));
|
|
||||||
params->params[0] = effect->black[0] / 255.0f;
|
|
||||||
params->params[1] = effect->black[1] / 255.0f;
|
|
||||||
params->params[2] = effect->black[2] / 255.0f;
|
|
||||||
params->params[3] = 0.0f;
|
|
||||||
params->params[4] = effect->white[0] / 255.0f;
|
|
||||||
params->params[5] = effect->white[1] / 255.0f;
|
|
||||||
params->params[6] = effect->white[2] / 255.0f;
|
|
||||||
params->params[7] = 0.0f;
|
|
||||||
params->params[8] = effect->intensity / 255.0f;
|
|
||||||
effect->rd = params;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void GlRenderer::effectTritoneUpdate(RenderEffectTritone* effect, const Matrix& transform)
|
|
||||||
{
|
|
||||||
effect->valid = (effect->blender < 255);
|
|
||||||
if (!effect->valid) return;
|
|
||||||
|
|
||||||
auto params = (GlEffectParams*)effect->rd;
|
|
||||||
if (!params) params = tvg::malloc<GlEffectParams*>(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] = effect->blender / 255.0f;
|
|
||||||
effect->rd = params;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool GlRenderer::effectGaussianBlurRegion(RenderEffectGaussianBlur* effect)
|
|
||||||
{
|
|
||||||
auto gaussianBlur = (GlGaussianBlur*)effect->rd;
|
|
||||||
if (effect->direction != 2) {
|
|
||||||
effect->extend.min.x = -gaussianBlur->extend;
|
|
||||||
effect->extend.max.x = +gaussianBlur->extend;
|
|
||||||
}
|
|
||||||
if (effect->direction != 1) {
|
|
||||||
effect->extend.min.y = -gaussianBlur->extend;
|
|
||||||
effect->extend.max.y = +gaussianBlur->extend;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
bool GlRenderer::effectDropShadowRegion(RenderEffectDropShadow* effect)
|
|
||||||
{
|
|
||||||
auto gaussianBlur = (GlDropShadow*)effect->rd;
|
|
||||||
effect->extend.min.x = -gaussianBlur->extend;
|
|
||||||
effect->extend.max.x = +gaussianBlur->extend;
|
|
||||||
effect->extend.min.y = -gaussianBlur->extend;
|
|
||||||
effect->extend.max.y = +gaussianBlur->extend;
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void GlRenderer::prepare(RenderEffect* effect, const Matrix& transform)
|
void GlRenderer::prepare(RenderEffect* effect, const Matrix& transform)
|
||||||
{
|
{
|
||||||
// we must be sure, that we have intermidiate FBOs
|
// we must be sure, that we have intermidiate FBOs
|
||||||
if (mBlendPool.count < 1) mBlendPool.push(new GlRenderTargetPool(surface.w, surface.h));
|
if (mBlendPool.count < 1) mBlendPool.push(new GlRenderTargetPool(surface.w, surface.h));
|
||||||
if (mBlendPool.count < 2) mBlendPool.push(new GlRenderTargetPool(surface.w, surface.h));
|
if (mBlendPool.count < 2) mBlendPool.push(new GlRenderTargetPool(surface.w, surface.h));
|
||||||
|
|
||||||
switch (effect->type) {
|
mEffect.update(effect, transform);
|
||||||
case SceneEffect::GaussianBlur: effectGaussianBlurUpdate(static_cast<RenderEffectGaussianBlur*>(effect), transform); break;
|
|
||||||
case SceneEffect::DropShadow : effectDropShadowUpdate(static_cast<RenderEffectDropShadow*>(effect), transform); break;
|
|
||||||
case SceneEffect::Fill: effectFillUpdate(static_cast<RenderEffectFill*>(effect), transform); break;
|
|
||||||
case SceneEffect::Tint: effectTintUpdate(static_cast<RenderEffectTint*>(effect), transform); break;
|
|
||||||
case SceneEffect::Tritone: effectTritoneUpdate(static_cast<RenderEffectTritone*>(effect), transform); break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool GlRenderer::region(RenderEffect* effect)
|
bool GlRenderer::region(RenderEffect* effect)
|
||||||
{
|
{
|
||||||
switch (effect->type) {
|
return mEffect.region(effect);
|
||||||
case SceneEffect::GaussianBlur: return effectGaussianBlurRegion(static_cast<RenderEffectGaussianBlur*>(effect));
|
|
||||||
case SceneEffect::DropShadow : return effectDropShadowRegion(static_cast<RenderEffectDropShadow*>(effect));
|
|
||||||
case SceneEffect::Fill:
|
|
||||||
case SceneEffect::Tint:
|
|
||||||
case SceneEffect::Tritone: return true;
|
|
||||||
default: return false;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool GlRenderer::render(TVG_UNUSED RenderCompositor* cmp, const RenderEffect* effect, bool direct)
|
bool GlRenderer::render(TVG_UNUSED RenderCompositor* cmp, const RenderEffect* effect, TVG_UNUSED bool direct)
|
||||||
{
|
{
|
||||||
// get current pass and properties
|
return mEffect.render(const_cast<RenderEffect*>(effect), currentPass(), mBlendPool);
|
||||||
auto pass = currentPass();
|
|
||||||
if (pass->isEmpty()) return false;
|
|
||||||
auto vp = pass->getViewport();
|
|
||||||
|
|
||||||
// add render geometry
|
|
||||||
const float vdata[] = {-1.0f, +1.0f, +1.0f, +1.0f, +1.0f, -1.0f, -1.0f, -1.0f};
|
|
||||||
const uint32_t idata[] = { 0, 1, 2, 0, 2, 3 };
|
|
||||||
auto voffset = mGpuBuffer.push((void*)vdata, sizeof(vdata));
|
|
||||||
auto ioffset = mGpuBuffer.pushIndex((void*)idata, sizeof(idata));
|
|
||||||
|
|
||||||
if (effect->type == SceneEffect::GaussianBlur) {
|
|
||||||
// get gaussian programs
|
|
||||||
GlProgram* programHorz = mPrograms[RT_GaussianHorz];
|
|
||||||
GlProgram* programVert = mPrograms[RT_GaussianVert];
|
|
||||||
// get current and intermidiate framebuffers
|
|
||||||
auto dstFbo = pass->getFbo();
|
|
||||||
auto dstCopyFbo0 = mBlendPool[0]->getRenderTarget(vp);
|
|
||||||
auto dstCopyFbo1 = mBlendPool[1]->getRenderTarget(vp);
|
|
||||||
// add uniform data
|
|
||||||
GlGaussianBlur* blur = (GlGaussianBlur*)(effect->rd);
|
|
||||||
auto blurOffset = mGpuBuffer.push(blur, sizeof(GlGaussianBlur), true);
|
|
||||||
|
|
||||||
// create gaussian blur tasks
|
|
||||||
auto gaussianTask = new GlGaussianBlurTask(dstFbo, dstCopyFbo0, dstCopyFbo1);
|
|
||||||
gaussianTask->effect = (RenderEffectGaussianBlur*)effect;
|
|
||||||
gaussianTask->setViewport({{0, 0}, {vp.sw(), vp.sh()}});
|
|
||||||
// horizontal blur task and geometry
|
|
||||||
gaussianTask->horzTask = new GlRenderTask(programHorz);
|
|
||||||
gaussianTask->horzTask->addBindResource(GlBindingResource{0, programHorz->getUniformBlockIndex("Gaussian"), mGpuBuffer.getBufferId(), blurOffset, sizeof(GlGaussianBlur)});
|
|
||||||
gaussianTask->horzTask->addVertexLayout(GlVertexLayout{0, 2, 2 * sizeof(float), voffset});
|
|
||||||
gaussianTask->horzTask->setDrawRange(ioffset, 6);
|
|
||||||
// vertical blur task and geometry
|
|
||||||
gaussianTask->vertTask = new GlRenderTask(programVert);
|
|
||||||
gaussianTask->vertTask->addBindResource(GlBindingResource{0, programVert->getUniformBlockIndex("Gaussian"), mGpuBuffer.getBufferId(), blurOffset, sizeof(GlGaussianBlur)});
|
|
||||||
gaussianTask->vertTask->addVertexLayout(GlVertexLayout{0, 2, 2 * sizeof(float), voffset});
|
|
||||||
gaussianTask->vertTask->setDrawRange(ioffset, 6);
|
|
||||||
// add task to render pipeline
|
|
||||||
pass->addRenderTask(gaussianTask);
|
|
||||||
} else if (effect->type == SceneEffect::DropShadow) {
|
|
||||||
// get programs
|
|
||||||
GlProgram* program = mPrograms[RT_DropShadow];
|
|
||||||
GlProgram* programHorz = mPrograms[RT_GaussianHorz];
|
|
||||||
GlProgram* programVert = mPrograms[RT_GaussianVert];
|
|
||||||
// get current and intermidiate framebuffers
|
|
||||||
auto dstFbo = pass->getFbo();
|
|
||||||
auto dstCopyFbo0 = mBlendPool[0]->getRenderTarget(vp);
|
|
||||||
auto dstCopyFbo1 = mBlendPool[1]->getRenderTarget(vp);
|
|
||||||
// add uniform data
|
|
||||||
GlDropShadow* params = (GlDropShadow*)(effect->rd);
|
|
||||||
auto paramsOffset = mGpuBuffer.push(params, sizeof(GlDropShadow), true);
|
|
||||||
|
|
||||||
// create gaussian blur tasks
|
|
||||||
auto task = new GlEffectDropShadowTask(program, dstFbo, dstCopyFbo0, dstCopyFbo1);
|
|
||||||
task->effect = (RenderEffectDropShadow*)effect;
|
|
||||||
task->setViewport({{0, 0}, {vp.sw(), vp.sh()}});
|
|
||||||
task->addBindResource(GlBindingResource{0, program->getUniformBlockIndex("DropShadow"), mGpuBuffer.getBufferId(), paramsOffset, sizeof(GlDropShadow)});
|
|
||||||
task->addVertexLayout(GlVertexLayout{0, 2, 2 * sizeof(float), voffset});
|
|
||||||
task->setDrawRange(ioffset, 6);
|
|
||||||
// horizontal blur task and geometry
|
|
||||||
task->horzTask = new GlRenderTask(programHorz);
|
|
||||||
task->horzTask->addBindResource(GlBindingResource{0, programHorz->getUniformBlockIndex("Gaussian"), mGpuBuffer.getBufferId(), paramsOffset, sizeof(GlGaussianBlur)});
|
|
||||||
task->horzTask->addVertexLayout(GlVertexLayout{0, 2, 2 * sizeof(float), voffset});
|
|
||||||
task->horzTask->setDrawRange(ioffset, 6);
|
|
||||||
// vertical blur task and geometry
|
|
||||||
task->vertTask = new GlRenderTask(programVert);
|
|
||||||
task->vertTask->addBindResource(GlBindingResource{0, programVert->getUniformBlockIndex("Gaussian"), mGpuBuffer.getBufferId(), paramsOffset, sizeof(GlGaussianBlur)});
|
|
||||||
task->vertTask->addVertexLayout(GlVertexLayout{0, 2, 2 * sizeof(float), voffset});
|
|
||||||
task->vertTask->setDrawRange(ioffset, 6);
|
|
||||||
// add task to render pipeline
|
|
||||||
pass->addRenderTask(task);
|
|
||||||
} 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 and setup task
|
|
||||||
auto task = new GlEffectColorTransformTask(program, dstFbo, dstCopyFbo);
|
|
||||||
task->setViewport({{0, 0}, {vp.sw(), vp.sh()}});
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "tvgGlRenderTask.h"
|
#include "tvgGlRenderTask.h"
|
||||||
#include "tvgGlGpuBuffer.h"
|
#include "tvgGlGpuBuffer.h"
|
||||||
#include "tvgGlRenderPass.h"
|
#include "tvgGlRenderPass.h"
|
||||||
|
#include "tvgGlEffect.h"
|
||||||
|
|
||||||
class GlRenderer : public RenderMethod
|
class GlRenderer : public RenderMethod
|
||||||
{
|
{
|
||||||
|
@ -60,13 +61,6 @@ public:
|
||||||
RT_DifferenceBlend,
|
RT_DifferenceBlend,
|
||||||
RT_ExclusionBlend,
|
RT_ExclusionBlend,
|
||||||
|
|
||||||
RT_GaussianVert,
|
|
||||||
RT_GaussianHorz,
|
|
||||||
RT_DropShadow,
|
|
||||||
RT_EffectFill,
|
|
||||||
RT_EffectTint,
|
|
||||||
RT_EffectTritone,
|
|
||||||
|
|
||||||
RT_None,
|
RT_None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -125,15 +119,6 @@ private:
|
||||||
void prepareCmpTask(GlRenderTask* task, const RenderRegion& vp, uint32_t cmpWidth, uint32_t cmpHeight);
|
void prepareCmpTask(GlRenderTask* task, const RenderRegion& vp, uint32_t cmpWidth, uint32_t cmpHeight);
|
||||||
void endRenderPass(RenderCompositor* cmp);
|
void endRenderPass(RenderCompositor* cmp);
|
||||||
|
|
||||||
void effectGaussianBlurUpdate(RenderEffectGaussianBlur* effect, const Matrix& transform);
|
|
||||||
void effectDropShadowUpdate(RenderEffectDropShadow* 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);
|
|
||||||
bool effectDropShadowRegion(RenderEffectDropShadow* effect);
|
|
||||||
|
|
||||||
void flush();
|
void flush();
|
||||||
void clearDisposes();
|
void clearDisposes();
|
||||||
void currentContext();
|
void currentContext();
|
||||||
|
@ -143,6 +128,7 @@ private:
|
||||||
GLint mTargetFboId = 0;
|
GLint mTargetFboId = 0;
|
||||||
GlStageBuffer mGpuBuffer;
|
GlStageBuffer mGpuBuffer;
|
||||||
GlRenderTarget mRootTarget;
|
GlRenderTarget mRootTarget;
|
||||||
|
GlEffect mEffect;
|
||||||
Array<GlProgram*> mPrograms;
|
Array<GlProgram*> mPrograms;
|
||||||
Array<GlRenderTargetPool*> mComposePool;
|
Array<GlRenderTargetPool*> mComposePool;
|
||||||
Array<GlRenderTargetPool*> mBlendPool;
|
Array<GlRenderTargetPool*> mBlendPool;
|
||||||
|
|
|
@ -58,6 +58,7 @@ extern const char* HARD_LIGHT_BLEND_FRAG;
|
||||||
extern const char* SOFT_LIGHT_BLEND_FRAG;
|
extern const char* SOFT_LIGHT_BLEND_FRAG;
|
||||||
extern const char* DIFFERENCE_BLEND_FRAG;
|
extern const char* DIFFERENCE_BLEND_FRAG;
|
||||||
extern const char* EXCLUSION_BLEND_FRAG;
|
extern const char* EXCLUSION_BLEND_FRAG;
|
||||||
|
|
||||||
extern const char* EFFECT_VERTEX;
|
extern const char* EFFECT_VERTEX;
|
||||||
extern const char* GAUSSIAN_VERTICAL;
|
extern const char* GAUSSIAN_VERTICAL;
|
||||||
extern const char* GAUSSIAN_HORIZONTAL;
|
extern const char* GAUSSIAN_HORIZONTAL;
|
||||||
|
|
Loading…
Add table
Reference in a new issue