wg_engine: fix fill rule usage

Fix wronk application of fill rule in a cases of terminated path (.close()/.moveTo())
This commit is contained in:
Sergii Liebodkin 2024-06-15 19:01:16 +03:00 committed by Hermet Park
parent 419fa93989
commit f333241f0a
2 changed files with 11 additions and 36 deletions

View file

@ -85,16 +85,13 @@ void WgRenderStorage::renderShape(WgContext& context, WgRenderDataShape* renderD
assert(renderData); assert(renderData);
assert(mRenderPassEncoder); assert(mRenderPassEncoder);
// draw strokes // draw strokes
if (renderData->strokeFirst) if (renderData->strokeFirst) {
drawStroke(context, renderData, blendType); drawStroke(context, renderData, blendType);
// draw shape drawShape(context, renderData, blendType);
if(renderData->fillRule == FillRule::Winding) } else {
drawShapeWinding(context, renderData, blendType); drawShape(context, renderData, blendType);
else if(renderData->fillRule == FillRule::EvenOdd)
drawShapeEvenOdd(context, renderData, blendType);
// draw strokes
if (!renderData->strokeFirst)
drawStroke(context, renderData, blendType); drawStroke(context, renderData, blendType);
}
} }
@ -109,40 +106,19 @@ void WgRenderStorage::renderPicture(WgContext& context, WgRenderDataPicture* ren
} }
void WgRenderStorage::drawShapeWinding(WgContext& context, WgRenderDataShape* renderData, WgPipelineBlendType blendType) void WgRenderStorage::drawShape(WgContext& context, WgRenderDataShape* renderData, WgPipelineBlendType blendType)
{ {
assert(renderData); assert(renderData);
assert(mRenderPassEncoder); assert(mRenderPassEncoder);
assert(renderData->meshGroupShapes.meshes.count == renderData->meshGroupShapesBBox.meshes.count); assert(renderData->meshGroupShapes.meshes.count == renderData->meshGroupShapesBBox.meshes.count);
// draw shape geometry // draw shape geometry
uint8_t blend = (uint8_t)blendType;
wgpuRenderPassEncoderSetStencilReference(mRenderPassEncoder, 0); wgpuRenderPassEncoderSetStencilReference(mRenderPassEncoder, 0);
for (uint32_t i = 0; i < renderData->meshGroupShapes.meshes.count; i++) { // setup fill rule
// draw to stencil (first pass) if (renderData->fillRule == FillRule::Winding)
mPipelines->fillShapeWinding.use(mRenderPassEncoder, mBindGroupCanvas, renderData->bindGroupPaint); mPipelines->fillShapeWinding.use(mRenderPassEncoder, mBindGroupCanvas, renderData->bindGroupPaint);
renderData->meshGroupShapes.meshes[i]->drawFan(context, mRenderPassEncoder); else
// fill shape (second pass) mPipelines->fillShapeEvenOdd.use(mRenderPassEncoder, mBindGroupCanvas, renderData->bindGroupPaint);
WgRenderSettings& settings = renderData->renderSettingsShape;
if (settings.fillType == WgRenderSettingsType::Solid)
mPipelines->solid[blend].use(mRenderPassEncoder, mBindGroupCanvas, renderData->bindGroupPaint, settings.bindGroupSolid);
else if (settings.fillType == WgRenderSettingsType::Linear)
mPipelines->linear[blend].use(mRenderPassEncoder, mBindGroupCanvas, renderData->bindGroupPaint, settings.bindGroupLinear);
else if (settings.fillType == WgRenderSettingsType::Radial)
mPipelines->radial[blend].use(mRenderPassEncoder, mBindGroupCanvas, renderData->bindGroupPaint, settings.bindGroupRadial);
renderData->meshGroupShapesBBox.meshes[i]->drawFan(context, mRenderPassEncoder);
}
}
void WgRenderStorage::drawShapeEvenOdd(WgContext& context, WgRenderDataShape* renderData, WgPipelineBlendType blendType)
{
assert(renderData);
assert(mRenderPassEncoder);
assert(renderData->meshGroupShapes.meshes.count == renderData->meshGroupShapesBBox.meshes.count);
// draw shape geometry
wgpuRenderPassEncoderSetStencilReference(mRenderPassEncoder, 0);
// draw to stencil (first pass) // draw to stencil (first pass)
mPipelines->fillShapeEvenOdd.use(mRenderPassEncoder, mBindGroupCanvas, renderData->bindGroupPaint);
for (uint32_t i = 0; i < renderData->meshGroupShapes.meshes.count; i++) for (uint32_t i = 0; i < renderData->meshGroupShapes.meshes.count; i++)
renderData->meshGroupShapes.meshes[i]->drawFan(context, mRenderPassEncoder); renderData->meshGroupShapes.meshes[i]->drawFan(context, mRenderPassEncoder);
// fill shape geometry (second pass) // fill shape geometry (second pass)

View file

@ -65,8 +65,7 @@ public:
WgBindGroupOpacity* opacity); WgBindGroupOpacity* opacity);
void antialias(WGPUCommandEncoder commandEncoder, WgRenderStorage* targetSrc); void antialias(WGPUCommandEncoder commandEncoder, WgRenderStorage* targetSrc);
private: private:
void drawShapeWinding(WgContext& context, WgRenderDataShape* renderData, WgPipelineBlendType blendType); void drawShape(WgContext& context, WgRenderDataShape* renderData, WgPipelineBlendType blendType);
void drawShapeEvenOdd(WgContext& context, WgRenderDataShape* renderData, WgPipelineBlendType blendType);
void drawStroke(WgContext& context, WgRenderDataShape* renderData, WgPipelineBlendType blendType); void drawStroke(WgContext& context, WgRenderDataShape* renderData, WgPipelineBlendType blendType);
void dispatchWorkgroups(WGPUComputePassEncoder computePassEncoder); void dispatchWorkgroups(WGPUComputePassEncoder computePassEncoder);