docs: Triplanar mapping and split-view component - #2625
Conversation
|
pkg.pr.new packages benchmark commit |
📊 Bundle Size Comparison
👀 Notable resultsStatic test results:No major changes. Dynamic test results:No major changes. 📋 All resultsClick to reveal the results table (355 entries).
If you wish to run a comparison for other, slower bundlers, run the 'Tree-shake test' from the GitHub Actions menu. |
Resolution Time Benchmark---
config:
themeVariables:
xyChart:
plotColorPalette: "#E63946, #3B82F6, #059669"
---
xychart
title "Random Branching (🔴 PR | 🔵 main | 🟢 release)"
x-axis "max depth" [1, 2, 3, 4, 5, 6, 7, 8]
y-axis "time (ms)"
line [0.95, 1.96, 4.25, 6.82, 7.23, 12.07, 22.38, 25.02]
line [0.95, 1.92, 4.30, 6.73, 8.15, 10.59, 21.88, 27.08]
line [0.96, 1.86, 3.88, 6.67, 7.46, 11.00, 22.48, 23.85]
---
config:
themeVariables:
xyChart:
plotColorPalette: "#E63946, #3B82F6, #059669"
---
xychart
title "Linear Recursion (🔴 PR | 🔵 main | 🟢 release)"
x-axis "max depth" [1, 2, 3, 4, 5, 6, 7, 8]
y-axis "time (ms)"
line [0.29, 0.60, 0.78, 0.91, 1.19, 1.21, 1.54, 1.67]
line [0.27, 0.54, 0.69, 0.88, 1.16, 1.18, 1.43, 1.60]
line [0.30, 0.57, 0.74, 0.88, 1.19, 1.20, 1.50, 1.55]
---
config:
themeVariables:
xyChart:
plotColorPalette: "#E63946, #3B82F6, #059669"
---
xychart
title "Full Tree (🔴 PR | 🔵 main | 🟢 release)"
x-axis "max depth" [1, 2, 3, 4, 5, 6, 7, 8]
y-axis "time (ms)"
line [0.96, 2.18, 4.68, 7.22, 13.18, 26.50, 56.93, 117.94]
line [0.82, 2.16, 3.81, 6.32, 12.31, 25.83, 57.04, 115.90]
line [1.05, 2.23, 3.48, 6.51, 12.39, 26.36, 57.46, 115.84]
|
|
@pullfrog review please |
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — adds a triplanar mapping docs example with a split-view comparison component for visualizing triplanar projection vs mesh UVs side by side.
- Add
triplanar-mappingexample — full rendering example with triplanar texture projection, PBR-like lighting, debug views, and a material picker, following the same patterns as the existingpomexample. - Add
load-model.ts— OBJ loader with tangent computation for normal mapping, using@loaders.gl/objand TypeGPU'scommon.writeSoA. - Add
split-comparison.ts— reusable split-view slider component with pointer drag, keyboard navigation, and ARIA attributes for comparing two rendering modes. - Add example metadata and assets — Suzanne OBJ model, thumbnail, and meta.json.
DeepSeek Pro (free via Pullfrog for OSS) | 𝕏
There was a problem hiding this comment.
Important
The split-view comparison — the headline feature of this example — compares clip-space coordinates against a pixel-based threshold, so the "Mesh UVs" pane never actually renders once the handle moves. Please fix before merging.
Reviewed changes
index.ts— new WebGPU example implementing triplanar sampling over 3 axis-aligned UV projections with sharpness-weighted blending, a mesh-UV reference path, a compact Blinn-Phong-styleshade(), 7 debug view modes, and material/paramsuniform plumbing (shares the existing/TypeGPU/assets/pomPBR asset pack).schemas.ts—ModelVertexstruct +modelVertexLayout,VertexOutput,TriplanarParamsuniform, and theVIEW_MODES/MATERIAL_IDS/DEFAULT_MATERIAL/INITIAL_PARAMSconstants.load-model.ts— OBJ loading via@loaders.glwith CPU-synthesized tangents/bitangents and a SoA vertex buffer.split-comparison.ts— a reusable split-pane overlay (drag handle with pointer capture, ARIA slider, clamped labels) appended to the canvas host.suzanne.obj,meta.json,thumbnail.png,index.html— example assets and metadata; thumbnail is 1232×1330 (passes the ≥513px loader check), anddata-fit-to-containermatches neighboring examples.
The example closely follows the established rendering/pom conventions, and all touched TypeGPU APIs (d.InferInput, tgpu.vertexLayout, schemaForCount, common.writeSoA, viewFormats) match existing usage. One substantive issue found, inline.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
| let roughness = triRoughness; | ||
| let metallic = triMetallic; | ||
|
|
||
| const showMeshUvs = input.canvasPosition.x > params.splitX; |
There was a problem hiding this comment.
Coordinate-space mismatch breaks the split. canvasPosition is the homogenous clip-space output of projection * view * worldPosition under a perspective projection, so its .x sits in a small clip range (roughly ±tens), whereas params.splitX is written in device pixels (splitX: canvas.width * ratio, typically hundreds). Because createSplitComparison calls sync() → onChange on construction and every resize, showMeshUvs becomes effectively always false, so the "Mesh UVs" pane never renders — the core comparison the example exists to demonstrate is dead.
Technical details
# Split comparison mixes clip-space and pixel coordinates
## Affected sites
- apps/typegpu-docs/src/examples/rendering/triplanar-mapping/index.ts:327 — `showMeshUvs` compares clip-space `canvasPosition.x` against pixel-valued `params.splitX`
- apps/typegpu-docs/src/examples/rendering/triplanar-mapping/index.ts:148 — `splitX` set from `canvas.width * ratio` (device px)
- apps/typegpu-docs/src/examples/rendering/triplanar-mapping/schemas.ts:25 — `splitX: d.f32`
## Required outcome
- The shader must compare against a coordinate space consistent with `params.splitX`. Either convert clip-space to NDC/window space in the shader, or store the threshold in NDC (e.g. `splitRatio * 2 - 1`) and compare `canvasPosition.x / canvasPosition.w` against it.
## Suggested approach (optional)
- Change `params.splitX` to a unitless ratio (it is already initialized to `0.5`), update `onChange` to patch the ratio rather than `canvas.width * ratio`, and compare `ndcX = input.canvasPosition.x / input.canvasPosition.w` against `ratio * 2 - 1`. This also keeps the threshold resolution-independent across the ResizeObserver-driven resizes.| const showMeshUvs = input.canvasPosition.x > params.splitX; | |
| const ndcX = input.canvasPosition.x / input.canvasPosition.w; | |
| const showMeshUvs = ndcX > params.splitRatio * 2 - 1; |

No description provided.