gl/wg engines: zero size blur dropshadow support
Some checks failed
Android / build_x86_64 (push) Has been cancelled
Android / build_aarch64 (push) Has been cancelled
iOS / build_x86_64 (push) Has been cancelled
iOS / build_arm64 (push) Has been cancelled
macOS / build (push) Has been cancelled
macOS / compact_test (push) Has been cancelled
macOS / unit_test (push) Has been cancelled
Ubuntu / build (push) Has been cancelled
Ubuntu / compact_test (push) Has been cancelled
Ubuntu / unit_test (push) Has been cancelled
Windows / build (push) Has been cancelled
Windows / compact_test (push) Has been cancelled
Windows / unit_test (push) Has been cancelled

- 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 committed by Hermet Park
parent dfa3efdb4e
commit 86e4310a14
6 changed files with 27 additions and 23 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

@ -538,10 +538,10 @@ bool WgRenderer::region(RenderEffect* effect)
} else if (effect->type == SceneEffect::DropShadow) { } else if (effect->type == SceneEffect::DropShadow) {
auto dropShadow = (RenderEffectDropShadow*)effect; auto dropShadow = (RenderEffectDropShadow*)effect;
auto renderData = (WgRenderDataEffectParams*)dropShadow->rd; auto renderData = (WgRenderDataEffectParams*)dropShadow->rd;
dropShadow->extend.min.x = -(renderData->extend + std::abs(renderData->offset.x)); dropShadow->extend.min.x = -std::ceil(renderData->extend + std::abs(renderData->offset.x));
dropShadow->extend.max.x = +(renderData->extend + std::abs(renderData->offset.x)); dropShadow->extend.min.y = -std::ceil(renderData->extend + std::abs(renderData->offset.y));
dropShadow->extend.min.y = -(renderData->extend + std::abs(renderData->offset.y)); dropShadow->extend.max.x = +std::floor(renderData->extend + std::abs(renderData->offset.x));
dropShadow->extend.max.y = +(renderData->extend + std::abs(renderData->offset.y)); dropShadow->extend.max.y = +std::floor(renderData->extend + std::abs(renderData->offset.y));
return true; return true;
} }
return false; return false;

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