mirror of
https://github.com/thorvg/thorvg.git
synced 2025-07-25 15:48:58 +00:00
wg_engine: Introduce the stroke clipper
Issue: https://github.com/thorvg/thorvg/issues/3063
This commit is contained in:
parent
173822b1d9
commit
889710ecee
3 changed files with 26 additions and 16 deletions
|
@ -660,6 +660,26 @@ void WgCompositor::blendScene(WgContext& context, WgRenderStorage* scene, WgComp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WgCompositor::markupClipPath(WgContext& context, WgRenderDataShape* renderData)
|
||||||
|
{
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||||
|
// markup stencil
|
||||||
|
if (renderData->meshGroupStrokes.meshes.count > 0) {
|
||||||
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
||||||
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.direct);
|
||||||
|
ARRAY_FOREACH(p, renderData->meshGroupStrokes.meshes)
|
||||||
|
(*p)->draw(context, renderPassEncoder);
|
||||||
|
} else {
|
||||||
|
WGPURenderPipeline stencilPipeline = (renderData->fillRule == FillRule::NonZero) ? pipelines.nonzero : pipelines.evenodd;
|
||||||
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, stencilPipeline);
|
||||||
|
ARRAY_FOREACH(p, renderData->meshGroupShapes.meshes)
|
||||||
|
(*p)->drawFan(context, renderPassEncoder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgCompositor::renderClipPath(WgContext& context, WgRenderDataPaint* paint)
|
void WgCompositor::renderClipPath(WgContext& context, WgRenderDataPaint* paint)
|
||||||
{
|
{
|
||||||
assert(paint);
|
assert(paint);
|
||||||
|
@ -669,17 +689,11 @@ void WgCompositor::renderClipPath(WgContext& context, WgRenderDataPaint* paint)
|
||||||
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, 0, 0, width, height);
|
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, 0, 0, width, height);
|
||||||
// get render data
|
// get render data
|
||||||
WgRenderDataShape* renderData0 = (WgRenderDataShape*)paint->clips[0];
|
WgRenderDataShape* renderData0 = (WgRenderDataShape*)paint->clips[0];
|
||||||
// set transformations
|
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
|
||||||
// markup stencil
|
// markup stencil
|
||||||
WGPURenderPipeline stencilPipeline = (renderData0->fillRule == FillRule::NonZero) ? pipelines.nonzero : pipelines.evenodd;
|
markupClipPath(context, renderData0);
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData0->bindGroupPaint, 0, nullptr);
|
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, stencilPipeline);
|
|
||||||
ARRAY_FOREACH(p, renderData0->meshGroupShapes.meshes)
|
|
||||||
(*p)->drawFan(context, renderPassEncoder);
|
|
||||||
// copy stencil to depth
|
// copy stencil to depth
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData0->bindGroupPaint, 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData0->bindGroupPaint, 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[128], 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[128], 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.copy_stencil_to_depth);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.copy_stencil_to_depth);
|
||||||
|
@ -689,12 +703,7 @@ void WgCompositor::renderClipPath(WgContext& context, WgRenderDataPaint* paint)
|
||||||
// get render data
|
// get render data
|
||||||
WgRenderDataShape* renderData = (WgRenderDataShape*)(*p);
|
WgRenderDataShape* renderData = (WgRenderDataShape*)(*p);
|
||||||
// markup stencil
|
// markup stencil
|
||||||
WGPURenderPipeline stencilPipeline = (renderData->fillRule == FillRule::NonZero) ? pipelines.nonzero : pipelines.evenodd;
|
markupClipPath(context, renderData);
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, stencilPipeline);
|
|
||||||
ARRAY_FOREACH(p, renderData->meshGroupShapes.meshes)
|
|
||||||
(*p)->drawFan(context, renderPassEncoder);
|
|
||||||
// copy stencil to depth (clear stencil)
|
// copy stencil to depth (clear stencil)
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||||
|
|
|
@ -68,7 +68,6 @@ private:
|
||||||
void copyTexture(const WgRenderStorage* dst, const WgRenderStorage* src);
|
void copyTexture(const WgRenderStorage* dst, const WgRenderStorage* src);
|
||||||
void copyTexture(const WgRenderStorage* dst, const WgRenderStorage* src, const RenderRegion& region);
|
void copyTexture(const WgRenderStorage* dst, const WgRenderStorage* src, const RenderRegion& region);
|
||||||
|
|
||||||
|
|
||||||
// shapes
|
// shapes
|
||||||
void drawShape(WgContext& context, WgRenderDataShape* renderData);
|
void drawShape(WgContext& context, WgRenderDataShape* renderData);
|
||||||
void blendShape(WgContext& context, WgRenderDataShape* renderData, BlendMethod blendMethod);
|
void blendShape(WgContext& context, WgRenderDataShape* renderData, BlendMethod blendMethod);
|
||||||
|
@ -88,6 +87,8 @@ private:
|
||||||
void drawScene(WgContext& context, WgRenderStorage* scene, WgCompose* compose);
|
void drawScene(WgContext& context, WgRenderStorage* scene, WgCompose* compose);
|
||||||
void blendScene(WgContext& context, WgRenderStorage* src, WgCompose* compose);
|
void blendScene(WgContext& context, WgRenderStorage* src, WgCompose* compose);
|
||||||
|
|
||||||
|
// the renderer prioritizes clipping with the stroke over the shape's fill
|
||||||
|
void markupClipPath(WgContext& context, WgRenderDataShape* renderData);
|
||||||
void renderClipPath(WgContext& context, WgRenderDataPaint* paint);
|
void renderClipPath(WgContext& context, WgRenderDataPaint* paint);
|
||||||
void clearClipPath(WgContext& context, WgRenderDataPaint* paint);
|
void clearClipPath(WgContext& context, WgRenderDataPaint* paint);
|
||||||
|
|
||||||
|
|
|
@ -376,7 +376,7 @@ void WgRenderDataShape::updateMeshes(WgContext& context, const RenderShape &rsha
|
||||||
|
|
||||||
pbuff->decodePath(rshape, true, [&](const WgVertexBuffer& path_buff) {
|
pbuff->decodePath(rshape, true, [&](const WgVertexBuffer& path_buff) {
|
||||||
appendShape(context, path_buff);
|
appendShape(context, path_buff);
|
||||||
if (rshape.stroke) proceedStrokes(context, rshape.stroke, path_buff, pool);
|
if ((rshape.stroke) && (rshape.stroke->width > 0)) proceedStrokes(context, rshape.stroke, path_buff, pool);
|
||||||
}, rshape.trimpath());
|
}, rshape.trimpath());
|
||||||
|
|
||||||
// update shapes bbox (with empty path handling)
|
// update shapes bbox (with empty path handling)
|
||||||
|
|
Loading…
Add table
Reference in a new issue