mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-13 11:36:25 +00:00
gl_engine: support advance compose method
This commit is contained in:
parent
221005bb25
commit
269537a411
5 changed files with 322 additions and 64 deletions
|
@ -61,6 +61,8 @@ public:
|
||||||
|
|
||||||
GLuint getFboId() { return mFbo->getFboId(); }
|
GLuint getFboId() { return mFbo->getFboId(); }
|
||||||
|
|
||||||
|
GLuint getTextureId() { return mFbo->getColorTexture(); }
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
T* endRenderPass(GlProgram* program, GLuint targetFbo) {
|
T* endRenderPass(GlProgram* program, GLuint targetFbo) {
|
||||||
return new T(program, targetFbo, mFbo->getFboId(), std::move(mTasks));
|
return new T(program, targetFbo, mFbo->getFboId(), std::move(mTasks));
|
||||||
|
|
|
@ -116,7 +116,7 @@ bool GlRenderer::sync()
|
||||||
|
|
||||||
RenderRegion GlRenderer::region(TVG_UNUSED RenderData data)
|
RenderRegion GlRenderer::region(TVG_UNUSED RenderData data)
|
||||||
{
|
{
|
||||||
return {0, 0, 0, 0};
|
return {0, 0, static_cast<int32_t>(surface.w), static_cast<int32_t>(surface.h)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -150,18 +150,14 @@ bool GlRenderer::beginComposite(Compositor* cmp, CompositeMethod method, uint8_t
|
||||||
{
|
{
|
||||||
if (!cmp) return false;
|
if (!cmp) return false;
|
||||||
|
|
||||||
// TODO handle other composite method with recursive begin composite
|
|
||||||
|
|
||||||
cmp->method = method;
|
cmp->method = method;
|
||||||
cmp->opacity = opacity;
|
cmp->opacity = opacity;
|
||||||
|
|
||||||
if (cmp->method == CompositeMethod::None) {
|
|
||||||
if (mPoolIndex >= mComposePool.size()) {
|
if (mPoolIndex >= mComposePool.size()) {
|
||||||
mComposePool.emplace_back(make_unique<GlRenderTarget>(surface.w, surface.h));
|
mComposePool.emplace_back(make_unique<GlRenderTarget>(surface.w, surface.h));
|
||||||
mComposePool.back()->init(mTargetFboId);
|
mComposePool.back()->init(mTargetFboId);
|
||||||
}
|
}
|
||||||
mRenderPassStack.emplace_back(GlRenderPass(mComposePool[mPoolIndex++].get()));
|
mRenderPassStack.emplace_back(GlRenderPass(mComposePool[mPoolIndex++].get()));
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -469,6 +465,16 @@ void GlRenderer::initShaders()
|
||||||
|
|
||||||
// image Renderer
|
// image Renderer
|
||||||
mPrograms.push_back(make_unique<GlProgram>(GlShader::gen(IMAGE_VERT_SHADER, IMAGE_FRAG_SHADER)));
|
mPrograms.push_back(make_unique<GlProgram>(GlShader::gen(IMAGE_VERT_SHADER, IMAGE_FRAG_SHADER)));
|
||||||
|
|
||||||
|
// compose Renderer
|
||||||
|
mPrograms.push_back(make_unique<GlProgram>(GlShader::gen(MASK_VERT_SHADER, MASK_ALPHA_FRAG_SHADER)));
|
||||||
|
mPrograms.push_back(make_unique<GlProgram>(GlShader::gen(MASK_VERT_SHADER, MASK_INV_ALPHA_FRAG_SHADER)));
|
||||||
|
mPrograms.push_back(make_unique<GlProgram>(GlShader::gen(MASK_VERT_SHADER, MASK_LUMA_FRAG_SHADER)));
|
||||||
|
mPrograms.push_back(make_unique<GlProgram>(GlShader::gen(MASK_VERT_SHADER, MASK_INV_LUMA_FRAG_SHADER)));
|
||||||
|
mPrograms.push_back(make_unique<GlProgram>(GlShader::gen(MASK_VERT_SHADER, MASK_ADD_FRAG_SHADER)));
|
||||||
|
mPrograms.push_back(make_unique<GlProgram>(GlShader::gen(MASK_VERT_SHADER, MASK_SUB_FRAG_SHADER)));
|
||||||
|
mPrograms.push_back(make_unique<GlProgram>(GlShader::gen(MASK_VERT_SHADER, MASK_INTERSECT_FRAG_SHADER)));
|
||||||
|
mPrograms.push_back(make_unique<GlProgram>(GlShader::gen(MASK_VERT_SHADER, MASK_DIFF_FRAG_SHADER)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -612,7 +618,7 @@ GlRenderPass* GlRenderer::currentPass()
|
||||||
return &mRenderPassStack.back();
|
return &mRenderPassStack.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlRenderer::prepareCmpTask(GlRenderTask* task)
|
void GlRenderer::prepareCmpTask(GlRenderTask* task, float opacity)
|
||||||
{
|
{
|
||||||
// we use 1:1 blit mapping since compositor fbo is same size as root fbo
|
// we use 1:1 blit mapping since compositor fbo is same size as root fbo
|
||||||
Array<float> vertices;
|
Array<float> vertices;
|
||||||
|
@ -626,25 +632,25 @@ void GlRenderer::prepareCmpTask(GlRenderTask* task)
|
||||||
// left top point
|
// left top point
|
||||||
vertices.push(left);
|
vertices.push(left);
|
||||||
vertices.push(top);
|
vertices.push(top);
|
||||||
vertices.push(1.f);
|
vertices.push(opacity);
|
||||||
vertices.push(0.f);
|
vertices.push(0.f);
|
||||||
vertices.push(1.f);
|
vertices.push(1.f);
|
||||||
// left bottom point
|
// left bottom point
|
||||||
vertices.push(left);
|
vertices.push(left);
|
||||||
vertices.push(bottom);
|
vertices.push(bottom);
|
||||||
vertices.push(1.f);
|
vertices.push(opacity);
|
||||||
vertices.push(0.f);
|
vertices.push(0.f);
|
||||||
vertices.push(0.f);
|
vertices.push(0.f);
|
||||||
// right top point
|
// right top point
|
||||||
vertices.push(right);
|
vertices.push(right);
|
||||||
vertices.push(top);
|
vertices.push(top);
|
||||||
vertices.push(1.f);
|
vertices.push(opacity);
|
||||||
vertices.push(1.f);
|
vertices.push(1.f);
|
||||||
vertices.push(1.f);
|
vertices.push(1.f);
|
||||||
// right bottom point
|
// right bottom point
|
||||||
vertices.push(right);
|
vertices.push(right);
|
||||||
vertices.push(bottom);
|
vertices.push(bottom);
|
||||||
vertices.push(1.f);
|
vertices.push(opacity);
|
||||||
vertices.push(1.f);
|
vertices.push(1.f);
|
||||||
vertices.push(0.f);
|
vertices.push(0.f);
|
||||||
|
|
||||||
|
@ -676,17 +682,77 @@ void GlRenderer::prepareCmpTask(GlRenderTask* task)
|
||||||
void GlRenderer::endRenderPass(Compositor* cmp)
|
void GlRenderer::endRenderPass(Compositor* cmp)
|
||||||
{
|
{
|
||||||
if (cmp->method != CompositeMethod::None) {
|
if (cmp->method != CompositeMethod::None) {
|
||||||
//TODO support advance composite method with recursive compositor
|
auto self_pass = std::move(mRenderPassStack.back());
|
||||||
|
mRenderPassStack.pop_back();
|
||||||
|
|
||||||
|
// mask is pushed first
|
||||||
|
auto mask_pass = std::move(mRenderPassStack.back());
|
||||||
|
mRenderPassStack.pop_back();
|
||||||
|
|
||||||
|
GlProgram* program = nullptr;
|
||||||
|
switch(cmp->method) {
|
||||||
|
case CompositeMethod::ClipPath:
|
||||||
|
case CompositeMethod::AlphaMask:
|
||||||
|
program = mPrograms[RT_MaskAlpha].get();
|
||||||
|
break;
|
||||||
|
case CompositeMethod::InvAlphaMask:
|
||||||
|
program = mPrograms[RT_MaskAlphaInv].get();
|
||||||
|
break;
|
||||||
|
case CompositeMethod::LumaMask:
|
||||||
|
program = mPrograms[RT_MaskLuma].get();
|
||||||
|
break;
|
||||||
|
case CompositeMethod::InvLumaMask:
|
||||||
|
program = mPrograms[RT_MaskLumaInv].get();
|
||||||
|
break;
|
||||||
|
case CompositeMethod::AddMask:
|
||||||
|
program = mPrograms[RT_MaskAdd].get();
|
||||||
|
break;
|
||||||
|
case CompositeMethod::SubtractMask:
|
||||||
|
program = mPrograms[RT_MaskSub].get();
|
||||||
|
break;
|
||||||
|
case CompositeMethod::IntersectMask:
|
||||||
|
program = mPrograms[RT_MaskIntersect].get();
|
||||||
|
break;
|
||||||
|
case CompositeMethod::DifferenceMask:
|
||||||
|
program = mPrograms[RT_MaskDifference].get();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (program == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto prev_task = mask_pass.endRenderPass<GlComposeTask>(nullptr, currentPass()->getFboId());
|
||||||
|
|
||||||
|
currentPass()->addRenderTask(prev_task);
|
||||||
|
|
||||||
|
auto compose_task = self_pass.endRenderPass<GlDrawBlitTask>(program, currentPass()->getFboId());
|
||||||
|
|
||||||
|
prepareCmpTask(compose_task, cmp->opacity / 255.f);
|
||||||
|
|
||||||
|
{
|
||||||
|
uint32_t loc = program->getUniformLocation("uSrcTexture");
|
||||||
|
compose_task->addBindResource(GlBindingResource{0, self_pass.getTextureId(), loc});
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
uint32_t loc = program->getUniformLocation("uMaskTexture");
|
||||||
|
compose_task->addBindResource(GlBindingResource{1, mask_pass.getTextureId(), loc});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
currentPass()->addRenderTask(compose_task);
|
||||||
|
} else {
|
||||||
|
|
||||||
auto renderPass = std::move(mRenderPassStack.back());
|
auto renderPass = std::move(mRenderPassStack.back());
|
||||||
mRenderPassStack.pop_back();
|
mRenderPassStack.pop_back();
|
||||||
|
|
||||||
auto task = renderPass.endRenderPass<GlDrawBlitTask>(
|
auto task = renderPass.endRenderPass<GlDrawBlitTask>(
|
||||||
mPrograms[RT_Image].get(), currentPass()->getFboId());
|
mPrograms[RT_Image].get(), currentPass()->getFboId());
|
||||||
|
|
||||||
prepareCmpTask(task);
|
prepareCmpTask(task, 1.f);
|
||||||
|
|
||||||
// matrix buffer
|
// matrix buffer
|
||||||
{
|
{
|
||||||
|
@ -722,8 +788,9 @@ void GlRenderer::endRenderPass(Compositor* cmp)
|
||||||
// texture id
|
// texture id
|
||||||
{
|
{
|
||||||
uint32_t loc = task->getProgram()->getUniformLocation("uTexture");
|
uint32_t loc = task->getProgram()->getUniformLocation("uTexture");
|
||||||
task->addBindResource(GlBindingResource{0, renderPass.getFboId(), loc});
|
task->addBindResource(GlBindingResource{0, renderPass.getTextureId(), loc});
|
||||||
}
|
}
|
||||||
|
|
||||||
currentPass()->addRenderTask(std::move(task));
|
currentPass()->addRenderTask(std::move(task));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -38,6 +38,14 @@ public:
|
||||||
RT_LinGradient,
|
RT_LinGradient,
|
||||||
RT_RadGradient,
|
RT_RadGradient,
|
||||||
RT_Image,
|
RT_Image,
|
||||||
|
RT_MaskAlpha,
|
||||||
|
RT_MaskAlphaInv,
|
||||||
|
RT_MaskLuma,
|
||||||
|
RT_MaskLumaInv,
|
||||||
|
RT_MaskAdd,
|
||||||
|
RT_MaskSub,
|
||||||
|
RT_MaskIntersect,
|
||||||
|
RT_MaskDifference,
|
||||||
|
|
||||||
RT_None,
|
RT_None,
|
||||||
};
|
};
|
||||||
|
@ -81,7 +89,7 @@ private:
|
||||||
|
|
||||||
GlRenderPass* currentPass();
|
GlRenderPass* currentPass();
|
||||||
|
|
||||||
void prepareCmpTask(GlRenderTask* task);
|
void prepareCmpTask(GlRenderTask* task, float opacity);
|
||||||
void endRenderPass(Compositor* cmp);
|
void endRenderPass(Compositor* cmp);
|
||||||
|
|
||||||
GLint mTargetFboId = 0;
|
GLint mTargetFboId = 0;
|
||||||
|
|
|
@ -252,3 +252,175 @@ const char* IMAGE_FRAG_SHADER = TVG_COMPOSE_SHADER(
|
||||||
FragColor = vec4(result.rgb, result.a * opacity * aOpacity); \n
|
FragColor = vec4(result.rgb, result.a * opacity * aOpacity); \n
|
||||||
} \n
|
} \n
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const char* MASK_VERT_SHADER = TVG_COMPOSE_SHADER(
|
||||||
|
layout(location = 0) in vec3 aLocation; \n
|
||||||
|
layout(location = 1) in vec2 aUV; \n
|
||||||
|
\n
|
||||||
|
out float vOpacity; \n
|
||||||
|
out vec2 vUV; \n
|
||||||
|
\n
|
||||||
|
void main() { \n
|
||||||
|
vUV = aUV; \n
|
||||||
|
vOpacity = aLocation.z; \n
|
||||||
|
\n
|
||||||
|
gl_Position = vec4(aLocation.xy, 0.0, 1.0); \n
|
||||||
|
} \n
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
const char* MASK_ALPHA_FRAG_SHADER = TVG_COMPOSE_SHADER(
|
||||||
|
uniform sampler2D uSrcTexture; \n
|
||||||
|
uniform sampler2D uMaskTexture; \n
|
||||||
|
\n
|
||||||
|
in float vOpacity; \n
|
||||||
|
in vec2 vUV; \n
|
||||||
|
\n
|
||||||
|
out vec4 FragColor; \n
|
||||||
|
\n
|
||||||
|
void main() { \n
|
||||||
|
vec4 srcColor = texture(uSrcTexture, vUV); \n
|
||||||
|
vec4 maskColor = texture(uMaskTexture, vUV); \n
|
||||||
|
\n
|
||||||
|
FragColor = vec4(srcColor.rgb, \n
|
||||||
|
srcColor.a * maskColor.a * vOpacity); \n
|
||||||
|
} \n
|
||||||
|
);
|
||||||
|
|
||||||
|
const char* MASK_INV_ALPHA_FRAG_SHADER = TVG_COMPOSE_SHADER(
|
||||||
|
uniform sampler2D uSrcTexture; \n
|
||||||
|
uniform sampler2D uMaskTexture; \n
|
||||||
|
\n
|
||||||
|
in float vOpacity; \n
|
||||||
|
in vec2 vUV; \n
|
||||||
|
\n
|
||||||
|
out vec4 FragColor; \n
|
||||||
|
\n
|
||||||
|
void main() { \n
|
||||||
|
vec4 srcColor = texture(uSrcTexture, vUV); \n
|
||||||
|
vec4 maskColor = texture(uMaskTexture, vUV); \n
|
||||||
|
\n
|
||||||
|
FragColor = vec4(srcColor.rgb, \n
|
||||||
|
srcColor.a * (1.0 - maskColor.a) * vOpacity); \n
|
||||||
|
} \n
|
||||||
|
);
|
||||||
|
|
||||||
|
const char* MASK_LUMA_FRAG_SHADER = TVG_COMPOSE_SHADER(
|
||||||
|
uniform sampler2D uSrcTexture; \n
|
||||||
|
uniform sampler2D uMaskTexture; \n
|
||||||
|
\n
|
||||||
|
in float vOpacity; \n
|
||||||
|
in vec2 vUV; \n
|
||||||
|
\n
|
||||||
|
out vec4 FragColor; \n
|
||||||
|
\n
|
||||||
|
void main() { \n
|
||||||
|
vec4 srcColor = texture(uSrcTexture, vUV); \n
|
||||||
|
vec4 maskColor = texture(uMaskTexture, vUV); \n
|
||||||
|
\n
|
||||||
|
FragColor = srcColor * vOpacity * (0.299 * maskColor.r + 0.587 * maskColor.g + 0.114 * maskColor.b); \n
|
||||||
|
} \n
|
||||||
|
);
|
||||||
|
|
||||||
|
const char* MASK_INV_LUMA_FRAG_SHADER = TVG_COMPOSE_SHADER(
|
||||||
|
uniform sampler2D uSrcTexture; \n
|
||||||
|
uniform sampler2D uMaskTexture; \n
|
||||||
|
\n
|
||||||
|
in float vOpacity; \n
|
||||||
|
in vec2 vUV; \n
|
||||||
|
\n
|
||||||
|
out vec4 FragColor; \n
|
||||||
|
\n
|
||||||
|
void main() { \n
|
||||||
|
vec4 srcColor = texture(uSrcTexture, vUV); \n
|
||||||
|
vec4 maskColor = texture(uMaskTexture, vUV); \n
|
||||||
|
\n
|
||||||
|
float luma = (0.299 * maskColor.r + 0.587 * maskColor.g + 0.114 * maskColor.b); \n
|
||||||
|
FragColor = srcColor * vOpacity * (1.0 - luma); \n
|
||||||
|
} \n
|
||||||
|
);
|
||||||
|
|
||||||
|
const char* MASK_ADD_FRAG_SHADER = TVG_COMPOSE_SHADER(
|
||||||
|
uniform sampler2D uSrcTexture; \n
|
||||||
|
uniform sampler2D uMaskTexture; \n
|
||||||
|
\n
|
||||||
|
in float vOpacity; \n
|
||||||
|
in vec2 vUV; \n
|
||||||
|
\n
|
||||||
|
out vec4 FragColor; \n
|
||||||
|
\n
|
||||||
|
void main() { \n
|
||||||
|
vec4 srcColor = texture(uSrcTexture, vUV); \n
|
||||||
|
vec4 maskColor = texture(uMaskTexture, vUV); \n
|
||||||
|
\n
|
||||||
|
vec4 color = srcColor + maskColor * (1.0 - srcColor.a); \n
|
||||||
|
\n
|
||||||
|
FragColor = min(color, vec4(1.0, 1.0, 1.0, 1.0 * vOpacity)) ; \n
|
||||||
|
} \n
|
||||||
|
);
|
||||||
|
|
||||||
|
const char* MASK_SUB_FRAG_SHADER = TVG_COMPOSE_SHADER(
|
||||||
|
uniform sampler2D uSrcTexture; \n
|
||||||
|
uniform sampler2D uMaskTexture; \n
|
||||||
|
\n
|
||||||
|
in float vOpacity; \n
|
||||||
|
in vec2 vUV; \n
|
||||||
|
\n
|
||||||
|
out vec4 FragColor; \n
|
||||||
|
\n
|
||||||
|
void main() { \n
|
||||||
|
vec4 srcColor = texture(uSrcTexture, vUV); \n
|
||||||
|
vec4 maskColor = texture(uMaskTexture, vUV); \n
|
||||||
|
float a = srcColor.a - maskColor.a; \n
|
||||||
|
\n
|
||||||
|
if (a <= 0.0) { \n
|
||||||
|
FragColor = vec4(0.0, 0.0, 0.0, 0.0); \n
|
||||||
|
} else { \n
|
||||||
|
FragColor = vec4(srcColor.rgb, srcColor.a * vOpacity * a); \n
|
||||||
|
} \n
|
||||||
|
} \n
|
||||||
|
);
|
||||||
|
|
||||||
|
const char* MASK_INTERSECT_FRAG_SHADER = TVG_COMPOSE_SHADER(
|
||||||
|
uniform sampler2D uSrcTexture; \n
|
||||||
|
uniform sampler2D uMaskTexture; \n
|
||||||
|
\n
|
||||||
|
in float vOpacity; \n
|
||||||
|
in vec2 vUV; \n
|
||||||
|
\n
|
||||||
|
out vec4 FragColor; \n
|
||||||
|
\n
|
||||||
|
void main() { \n
|
||||||
|
vec4 srcColor = texture(uSrcTexture, vUV); \n
|
||||||
|
vec4 maskColor = texture(uMaskTexture, vUV); \n
|
||||||
|
\n
|
||||||
|
float intAlpha = srcColor.a * maskColor.a; \n
|
||||||
|
\n
|
||||||
|
FragColor = vec4(maskColor.rgb, maskColor.a * vOpacity * intAlpha); \n
|
||||||
|
} \n
|
||||||
|
);
|
||||||
|
|
||||||
|
const char* MASK_DIFF_FRAG_SHADER = TVG_COMPOSE_SHADER(
|
||||||
|
uniform sampler2D uSrcTexture; \n
|
||||||
|
uniform sampler2D uMaskTexture; \n
|
||||||
|
\n
|
||||||
|
in float vOpacity; \n
|
||||||
|
in vec2 vUV; \n
|
||||||
|
\n
|
||||||
|
out vec4 FragColor; \n
|
||||||
|
\n
|
||||||
|
void main() { \n
|
||||||
|
vec4 srcColor = texture(uSrcTexture, vUV); \n
|
||||||
|
vec4 maskColor = texture(uMaskTexture, vUV); \n
|
||||||
|
\n
|
||||||
|
float da = srcColor.a - maskColor.a; \n
|
||||||
|
\n
|
||||||
|
if (da == 0.0) { \n
|
||||||
|
FragColor = vec4(0.0, 0.0, 0.0, 0.0); \n
|
||||||
|
} else if (da > 0.0) { \n
|
||||||
|
FragColor = vec4(srcColor.rgb, srcColor.a * da * vOpacity); \n
|
||||||
|
} else { \n
|
||||||
|
FragColor = vec4(maskColor.rgb, maskColor.a * (-da) * vOpacity);\n
|
||||||
|
} \n
|
||||||
|
} \n
|
||||||
|
);
|
|
@ -30,5 +30,14 @@ extern const char* LINEAR_GRADIENT_FRAG_SHADER;
|
||||||
extern const char* RADIAL_GRADIENT_FRAG_SHADER;
|
extern const char* RADIAL_GRADIENT_FRAG_SHADER;
|
||||||
extern const char* IMAGE_VERT_SHADER;
|
extern const char* IMAGE_VERT_SHADER;
|
||||||
extern const char* IMAGE_FRAG_SHADER;
|
extern const char* IMAGE_FRAG_SHADER;
|
||||||
|
extern const char* MASK_VERT_SHADER;
|
||||||
|
extern const char* MASK_ALPHA_FRAG_SHADER;
|
||||||
|
extern const char* MASK_INV_ALPHA_FRAG_SHADER;
|
||||||
|
extern const char* MASK_LUMA_FRAG_SHADER;
|
||||||
|
extern const char* MASK_INV_LUMA_FRAG_SHADER;
|
||||||
|
extern const char* MASK_ADD_FRAG_SHADER;
|
||||||
|
extern const char* MASK_SUB_FRAG_SHADER;
|
||||||
|
extern const char* MASK_INTERSECT_FRAG_SHADER;
|
||||||
|
extern const char* MASK_DIFF_FRAG_SHADER;
|
||||||
|
|
||||||
#endif /* _TVG_GL_SHADERSRC_H_ */
|
#endif /* _TVG_GL_SHADERSRC_H_ */
|
||||||
|
|
Loading…
Add table
Reference in a new issue