gl/wg engines: zero size blur dropshadow support
Implements support for zero size blur in drop shadow effects for both GL and WebGPU engines.
When the blur sigma parameter is zero, the implementation now skips the blur processing entirely and uses the original image as the shadow source, improving performance and avoiding unnecessary computations
EffectDropShadow example changed to reproduce zero sigma shadow

https://github.com/thorvg/thorvg/issues/3602
This commit is contained in:
Sergii Liebodkin 2025-07-23 19:37:12 +03:00
parent 7fc8e616da
commit 01eced39b0
5 changed files with 23 additions and 19 deletions

View file

@ -103,7 +103,7 @@ struct UserExample : tvgexam::Example
scene2->push(tvg::SceneEffect::DropShadow, 65, 143, 222, (int)(255.0f * progress), 135.0, 10.0, 3.0, 100);
scene3->push(tvg::SceneEffect::ClearAll);
scene3->push(tvg::SceneEffect::DropShadow, 0, 0, 0, 125, (double)(360.0f * progress), 20.0, 3.0, 100);
scene3->push(tvg::SceneEffect::DropShadow, 0, 0, 0, 125, (double)(360.0f * progress), 20.0, 0.0, 100);
canvas->update();

View file

@ -141,7 +141,7 @@ void GlEffect::update(RenderEffectDropShadow* effect, const Matrix& transform)
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);
effect->valid = (dropShadow->extend >= 0);
}

View file

@ -544,20 +544,23 @@ void GlEffectDropShadowTask::run()
GL_CHECK(glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST));
GL_CHECK(glDisable(GL_BLEND));
// horizontal blur
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, mDstCopyFbo0->getResolveFboId()));
horzTask->setViewport(vp);
horzTask->addBindResource({ 0, dstCopyTexId1, horzSrcTextureLoc });
horzTask->run();
// vertical blur
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, mDstCopyFbo1->getResolveFboId()));
vertTask->setViewport(vp);
vertTask->addBindResource({ 0, dstCopyTexId0, vertSrcTextureLoc });
vertTask->run();
// copy original image to intermediate buffer
GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, mDstFbo->getFboId()));
GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDstCopyFbo0->getResolveFboId()));
GL_CHECK(glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST));
// when sigma is 0, no blur is applied, and the original image is used directly as the shadow.
if (!tvg::zero(effect->sigma)) {
// horizontal blur
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, mDstCopyFbo0->getResolveFboId()));
horzTask->setViewport(vp);
horzTask->addBindResource({ 0, dstCopyTexId1, horzSrcTextureLoc });
horzTask->run();
// vertical blur
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, mDstCopyFbo1->getResolveFboId()));
vertTask->setViewport(vp);
vertTask->addBindResource({ 0, dstCopyTexId0, vertSrcTextureLoc });
vertTask->run();
// copy original image to intermediate buffer
GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, mDstFbo->getFboId()));
GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDstCopyFbo0->getResolveFboId()));
GL_CHECK(glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST));
}
// run drop shadow effect
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, mDstFbo->getFboId()));
GlRenderTask::run();

View file

@ -875,8 +875,9 @@ bool WgCompositor::dropShadow(WgContext& context, WgRenderTarget* dst, const Ren
auto aabb = compose->aabb;
auto viewport = compose->rdViewport;
{ // apply blur
copyTexture(&targetTemp1, dst, aabb);
copyTexture(&targetTemp1, dst, aabb);
// when sigma is 0, no blur is applied, and the original image is used directly as the shadow.
if (!tvg::zero(params->sigma)) {
WgRenderTarget* sbuff = &targetTemp1;
WgRenderTarget* dbuff = &targetTemp0;
WGPUComputePassDescriptor computePassDesc{ .label = "Compute pass drop shadow blur" };

View file

@ -247,7 +247,7 @@ bool WgShaderTypeEffectParams::update(RenderEffectDropShadow* dropShadow, const
params[9] = offset.y;
extend = params[2] * 2; // kernel
dropShadow->valid = (extend > 0);
dropShadow->valid = (extend >= 0);
return dropShadow->valid;
}