mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-10 06:34:01 +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 getTextureId() { return mFbo->getColorTexture(); }
|
||||
|
||||
template <class T>
|
||||
T* endRenderPass(GlProgram* program, GLuint targetFbo) {
|
||||
return new T(program, targetFbo, mFbo->getFboId(), std::move(mTasks));
|
||||
|
|
|
@ -116,7 +116,7 @@ bool GlRenderer::sync()
|
|||
|
||||
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;
|
||||
|
||||
// TODO handle other composite method with recursive begin composite
|
||||
|
||||
cmp->method = method;
|
||||
cmp->opacity = opacity;
|
||||
|
||||
if (cmp->method == CompositeMethod::None) {
|
||||
if (mPoolIndex >= mComposePool.size()) {
|
||||
mComposePool.emplace_back(make_unique<GlRenderTarget>(surface.w, surface.h));
|
||||
mComposePool.back()->init(mTargetFboId);
|
||||
}
|
||||
mRenderPassStack.emplace_back(GlRenderPass(mComposePool[mPoolIndex++].get()));
|
||||
if (mPoolIndex >= mComposePool.size()) {
|
||||
mComposePool.emplace_back(make_unique<GlRenderTarget>(surface.w, surface.h));
|
||||
mComposePool.back()->init(mTargetFboId);
|
||||
}
|
||||
mRenderPassStack.emplace_back(GlRenderPass(mComposePool[mPoolIndex++].get()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -469,6 +465,16 @@ void GlRenderer::initShaders()
|
|||
|
||||
// image Renderer
|
||||
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();
|
||||
}
|
||||
|
||||
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
|
||||
Array<float> vertices;
|
||||
|
@ -626,25 +632,25 @@ void GlRenderer::prepareCmpTask(GlRenderTask* task)
|
|||
// left top point
|
||||
vertices.push(left);
|
||||
vertices.push(top);
|
||||
vertices.push(1.f);
|
||||
vertices.push(opacity);
|
||||
vertices.push(0.f);
|
||||
vertices.push(1.f);
|
||||
// left bottom point
|
||||
vertices.push(left);
|
||||
vertices.push(bottom);
|
||||
vertices.push(1.f);
|
||||
vertices.push(opacity);
|
||||
vertices.push(0.f);
|
||||
vertices.push(0.f);
|
||||
// right top point
|
||||
vertices.push(right);
|
||||
vertices.push(top);
|
||||
vertices.push(1.f);
|
||||
vertices.push(opacity);
|
||||
vertices.push(1.f);
|
||||
vertices.push(1.f);
|
||||
// right bottom point
|
||||
vertices.push(right);
|
||||
vertices.push(bottom);
|
||||
vertices.push(1.f);
|
||||
vertices.push(opacity);
|
||||
vertices.push(1.f);
|
||||
vertices.push(0.f);
|
||||
|
||||
|
@ -676,54 +682,115 @@ void GlRenderer::prepareCmpTask(GlRenderTask* task)
|
|||
void GlRenderer::endRenderPass(Compositor* cmp)
|
||||
{
|
||||
if (cmp->method != CompositeMethod::None) {
|
||||
//TODO support advance composite method with recursive compositor
|
||||
return;
|
||||
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;
|
||||
}
|
||||
|
||||
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());
|
||||
mRenderPassStack.pop_back();
|
||||
|
||||
auto task = renderPass.endRenderPass<GlDrawBlitTask>(
|
||||
mPrograms[RT_Image].get(), currentPass()->getFboId());
|
||||
|
||||
prepareCmpTask(task, 1.f);
|
||||
|
||||
// matrix buffer
|
||||
{
|
||||
float matrix[16];
|
||||
memset(matrix, 0, 16 * sizeof(float));
|
||||
matrix[0] = 1.f;
|
||||
matrix[5] = 1.f;
|
||||
matrix[10] = 1.f;
|
||||
matrix[15] = 1.f;
|
||||
uint32_t loc = task->getProgram()->getUniformBlockIndex("Matrix");
|
||||
|
||||
task->addBindResource(GlBindingResource{
|
||||
0,
|
||||
loc,
|
||||
mGpuBuffer->getBufferId(),
|
||||
mGpuBuffer->push(matrix, 16 * sizeof(float), true),
|
||||
16 * sizeof(float),
|
||||
});
|
||||
}
|
||||
// image info
|
||||
{
|
||||
uint32_t info[4] = {ABGR8888, 0, cmp->opacity, 0};
|
||||
uint32_t loc = task->getProgram()->getUniformBlockIndex("ColorInfo");
|
||||
|
||||
task->addBindResource(GlBindingResource{
|
||||
1,
|
||||
loc,
|
||||
mGpuBuffer->getBufferId(),
|
||||
mGpuBuffer->push(info, 4 * sizeof(uint32_t), true),
|
||||
4 * sizeof(uint32_t),
|
||||
});
|
||||
}
|
||||
// texture id
|
||||
{
|
||||
uint32_t loc = task->getProgram()->getUniformLocation("uTexture");
|
||||
task->addBindResource(GlBindingResource{0, renderPass.getTextureId(), loc});
|
||||
}
|
||||
|
||||
currentPass()->addRenderTask(std::move(task));
|
||||
}
|
||||
|
||||
auto renderPass = std::move(mRenderPassStack.back());
|
||||
mRenderPassStack.pop_back();
|
||||
|
||||
auto task = renderPass.endRenderPass<GlDrawBlitTask>(
|
||||
mPrograms[RT_Image].get(), currentPass()->getFboId());
|
||||
|
||||
prepareCmpTask(task);
|
||||
|
||||
// matrix buffer
|
||||
{
|
||||
float matrix[16];
|
||||
memset(matrix, 0, 16 * sizeof(float));
|
||||
matrix[0] = 1.f;
|
||||
matrix[5] = 1.f;
|
||||
matrix[10] = 1.f;
|
||||
matrix[15] = 1.f;
|
||||
uint32_t loc = task->getProgram()->getUniformBlockIndex("Matrix");
|
||||
|
||||
task->addBindResource(GlBindingResource{
|
||||
0,
|
||||
loc,
|
||||
mGpuBuffer->getBufferId(),
|
||||
mGpuBuffer->push(matrix, 16 * sizeof(float), true),
|
||||
16 * sizeof(float),
|
||||
});
|
||||
}
|
||||
// image info
|
||||
{
|
||||
uint32_t info[4] = {ABGR8888, 0, cmp->opacity, 0};
|
||||
uint32_t loc = task->getProgram()->getUniformBlockIndex("ColorInfo");
|
||||
|
||||
task->addBindResource(GlBindingResource{
|
||||
1,
|
||||
loc,
|
||||
mGpuBuffer->getBufferId(),
|
||||
mGpuBuffer->push(info, 4 * sizeof(uint32_t), true),
|
||||
4 * sizeof(uint32_t),
|
||||
});
|
||||
}
|
||||
// texture id
|
||||
{
|
||||
uint32_t loc = task->getProgram()->getUniformLocation("uTexture");
|
||||
task->addBindResource(GlBindingResource{0, renderPass.getFboId(), loc});
|
||||
}
|
||||
|
||||
currentPass()->addRenderTask(std::move(task));
|
||||
}
|
||||
|
|
|
@ -38,6 +38,14 @@ public:
|
|||
RT_LinGradient,
|
||||
RT_RadGradient,
|
||||
RT_Image,
|
||||
RT_MaskAlpha,
|
||||
RT_MaskAlphaInv,
|
||||
RT_MaskLuma,
|
||||
RT_MaskLumaInv,
|
||||
RT_MaskAdd,
|
||||
RT_MaskSub,
|
||||
RT_MaskIntersect,
|
||||
RT_MaskDifference,
|
||||
|
||||
RT_None,
|
||||
};
|
||||
|
@ -81,7 +89,7 @@ private:
|
|||
|
||||
GlRenderPass* currentPass();
|
||||
|
||||
void prepareCmpTask(GlRenderTask* task);
|
||||
void prepareCmpTask(GlRenderTask* task, float opacity);
|
||||
void endRenderPass(Compositor* cmp);
|
||||
|
||||
GLint mTargetFboId = 0;
|
||||
|
|
|
@ -252,3 +252,175 @@ const char* IMAGE_FRAG_SHADER = TVG_COMPOSE_SHADER(
|
|||
FragColor = vec4(result.rgb, result.a * opacity * aOpacity); \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* IMAGE_VERT_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_ */
|
||||
|
|
Loading…
Add table
Reference in a new issue