forked from 1b-agent/opencadstudio-upstream
Paper content viewports with a circle / spline / ellipse clip boundary drew their model content to the full bounding rectangle instead of the shape. Each paper content viewport is its own render into its own screen rectangle, so clipping is done per viewport: the boundary polygon is projected into that viewport's render-target NDC (paper shape mapped through the same visible-sub-rect crop as the content, so it stays fixed to the viewport frame) and stamped into the stencil buffer with an even-odd Invert, which marks the interior of any shape, convex or not, without triangulation. Every content pass then draws only where the stencil is set, so hatch, wire, mesh, 3DFACE, text, image, wipeout and selection are all clipped uniformly. Because Invert turns the cleared 0x00 into 0xFF, clipped content draws with stencil reference 0xFF (unclipped content keeps reference 0). The shared depth buffer moves to Depth24PlusStencil8 across every pipeline. Rectangular viewports keep clipping via their own render rectangle and XCLIP keeps its existing CPU wire clip; neither needs the stencil path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
26 lines
1.0 KiB
WebGPU Shading Language
26 lines
1.0 KiB
WebGPU Shading Language
// Viewport / XCLIP stencil-mask shader.
|
|
//
|
|
// Draws a clip-boundary polygon (as a triangle fan) into the stencil buffer so
|
|
// a paper content viewport can clip its render to an arbitrary shape. It writes
|
|
// no colour and no depth — only stencil (the pipeline uses `Invert`, so an
|
|
// even-odd fill marks the polygon interior regardless of convexity).
|
|
//
|
|
// The boundary arrives already projected into the content viewport's normalized
|
|
// device coordinates (paper-space shape mapped through the same visible-sub-rect
|
|
// crop as the content), so the vertex stage is a pure pass-through — the mask
|
|
// is fixed to the viewport frame and never moves with the model camera.
|
|
|
|
struct VIn {
|
|
@location(0) ndc: vec2<f32>,
|
|
}
|
|
|
|
@vertex fn vs_main(in: VIn) -> @builtin(position) vec4<f32> {
|
|
return vec4<f32>(in.ndc, 0.0, 1.0);
|
|
}
|
|
|
|
// Colour is write-masked off in the pipeline; this only satisfies the
|
|
// fragment-output requirement.
|
|
@fragment fn fs_main() -> @location(0) vec4<f32> {
|
|
return vec4<f32>(0.0, 0.0, 0.0, 0.0);
|
|
}
|