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); 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::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(); canvas->update();

View file

@ -141,7 +141,7 @@ void GlEffect::update(RenderEffectDropShadow* effect, const Matrix& transform)
dropShadow->offset[1] = offset.y; dropShadow->offset[1] = offset.y;
dropShadow->extend = 2 * std::max(sigma * scale + std::abs(offset.x), sigma * scale + std::abs(offset.y)); dropShadow->extend = 2 * std::max(sigma * scale + std::abs(offset.x), sigma * scale + std::abs(offset.y));
effect->rd = dropShadow; 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(glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST));
GL_CHECK(glDisable(GL_BLEND)); GL_CHECK(glDisable(GL_BLEND));
// horizontal blur // when sigma is 0, no blur is applied, and the original image is used directly as the shadow.
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, mDstCopyFbo0->getResolveFboId())); if (!tvg::zero(effect->sigma)) {
horzTask->setViewport(vp); // horizontal blur
horzTask->addBindResource({ 0, dstCopyTexId1, horzSrcTextureLoc }); GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, mDstCopyFbo0->getResolveFboId()));
horzTask->run(); horzTask->setViewport(vp);
// vertical blur horzTask->addBindResource({ 0, dstCopyTexId1, horzSrcTextureLoc });
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, mDstCopyFbo1->getResolveFboId())); horzTask->run();
vertTask->setViewport(vp); // vertical blur
vertTask->addBindResource({ 0, dstCopyTexId0, vertSrcTextureLoc }); GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, mDstCopyFbo1->getResolveFboId()));
vertTask->run(); vertTask->setViewport(vp);
// copy original image to intermediate buffer vertTask->addBindResource({ 0, dstCopyTexId0, vertSrcTextureLoc });
GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, mDstFbo->getFboId())); vertTask->run();
GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDstCopyFbo0->getResolveFboId())); // copy original image to intermediate buffer
GL_CHECK(glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST)); 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 // run drop shadow effect
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, mDstFbo->getFboId())); GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, mDstFbo->getFboId()));
GlRenderTask::run(); GlRenderTask::run();

View file

@ -875,8 +875,9 @@ bool WgCompositor::dropShadow(WgContext& context, WgRenderTarget* dst, const Ren
auto aabb = compose->aabb; auto aabb = compose->aabb;
auto viewport = compose->rdViewport; 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* sbuff = &targetTemp1;
WgRenderTarget* dbuff = &targetTemp0; WgRenderTarget* dbuff = &targetTemp0;
WGPUComputePassDescriptor computePassDesc{ .label = "Compute pass drop shadow blur" }; WGPUComputePassDescriptor computePassDesc{ .label = "Compute pass drop shadow blur" };

View file

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