gl_engine: support advance compose method

This commit is contained in:
RuiwenTang 2023-11-21 18:43:47 +08:00 committed by Hermet Park
parent 221005bb25
commit 269537a411
5 changed files with 322 additions and 64 deletions

View file

@ -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));

View file

@ -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));
}

View file

@ -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;

View file

@ -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
);

View file

@ -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_ */