Five pillars, four colored point lights; closest-hit emits one shadow ray per light from the same invocation (raysPerPixel = 4, maxDepth = 2), so up to four rays per pixel rtAccumulate in a single SHADE pass — the contention case #30 exists for. Each pillar casts four separable colored shadows; an accumulator race or capacity drop shows as flickering dark noise or a missing shadow color. Two frames a second apart diff at 2 px / 1.85 M (last-ulp CAS ordering), confirming no lost updates. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
120 lines
5.7 KiB
Markdown
120 lines
5.7 KiB
Markdown
# Examples
|
|
|
|
Each example is a self-contained `crafter-build` project that depends on
|
|
the parent `Crafter.Graphics` via `LocalProject`. To build and run any
|
|
of them:
|
|
|
|
```bash
|
|
cd examples/<name>
|
|
crafter-build -r
|
|
```
|
|
|
|
## Index
|
|
|
|
### [HelloWindow](HelloWindow/)
|
|
Minimum viable program: open a window, run the event loop. No Vulkan
|
|
rendering. Useful as a smoke test for `Device::Initialize` + `Window` +
|
|
the platform backend.
|
|
|
|
### [VulkanTriangle](VulkanTriangle/)
|
|
Ray-traced single triangle through `vkCmdTraceRaysKHR`. Shows the full
|
|
ray-tracing setup: `DescriptorHeapVulkan` with image and buffer slots,
|
|
`PipelineRTVulkan` from raygen / miss / closesthit SPIR-V, BLAS via
|
|
`Mesh::Build`, TLAS via `RenderingElement3D::BuildTLAS`, direct
|
|
`vkWriteResourceDescriptorsEXT` for swapchain views, `RTPass` on
|
|
`window.passes`. Smallest test of the bindless ray-tracing path.
|
|
|
|
### [HelloUI](HelloUI/)
|
|
Compute-shader UI demo using all three UI tiers:
|
|
|
|
- **Tier 3** components: `DrawButton`, `DrawSlider`, `DrawProgressBar`,
|
|
composed via `Rect::SubRect` for resize-safe layout.
|
|
- **Tier 2** standard shaders: `DispatchQuads` for the background and
|
|
components, `DispatchCircles` for a cursor-tracking dot,
|
|
`DispatchText` for the button label (with the FontAtlas wired up to
|
|
`UIRenderer`).
|
|
- **Tier 1** is available too — any custom `ComputeShader` registered
|
|
on the same heap can be dispatched alongside the standard ones.
|
|
|
|
Hit-testing and animation are user code (see the `EventListener`
|
|
subscriptions on `window.onMouseMove` / `onMouseLeftClick`); the
|
|
library does not track widgets or focus.
|
|
|
|
Drop a TTF in this directory as `font.ttf` before running (the example
|
|
loads it via `Font("font.ttf")`).
|
|
|
|
### [InputSystem](InputSystem/)
|
|
Guided tour of `Crafter::Input`: name actions ("Jump", "Move", "Fire",
|
|
"Look", "Zoom"), bind them to keys / mouse / gamepad (with composite
|
|
bindings for WASD-as-Vector2 and analog sticks), and consume them as
|
|
events. Demonstrates:
|
|
|
|
- The compile-time `Key(CrafterKeys::Space)` helper that folds to a
|
|
per-platform raw scancode — bindings stay cross-platform-readable
|
|
in source while runtime data stores raw codes only.
|
|
- All four action types (Button, Axis1D, Vector2) with multiple
|
|
bindings per action (any-of semantics).
|
|
- `Map::StartRebind` — press R, then press any input to remap "Jump"
|
|
at runtime. Captured input is filtered out for that frame.
|
|
- `BindingToString` / `BindingFromString` round-trip — print the
|
|
default bindings as the on-disk format.
|
|
- Gamepad hot-plug events: plug a controller in mid-run and the
|
|
bindings start firing immediately.
|
|
|
|
Console-driven (no UI rendering needed); focus the window and watch
|
|
stdout.
|
|
|
|
### [CustomShader](CustomShader/)
|
|
Tier 1 demo: a user-authored compute shader (`inverse-circle.comp.glsl`)
|
|
running alongside the shipped `drawQuads`. The custom shader inverts RGB
|
|
under each item-circle — exactly the kind of effect attempt #2's closed
|
|
shader couldn't express. Shows:
|
|
|
|
- Defining your own item POD struct in C++ + matching `std430` struct
|
|
in GLSL.
|
|
- `#include "../../shaders/ui-shared.glsl"` for the bindless heap
|
|
declarations + `UIDispatchHeader` push-constant contract.
|
|
- `ComputeShader::Load` for the `.spv`, `UIRenderer::RegisterBuffer`
|
|
for your SSBO, `FillHeader` to populate the standard prefix, and
|
|
`UIRenderer::Dispatch` to launch — the same pattern the standard
|
|
shaders use under the hood.
|
|
- The inter-dispatch SHADER_WRITE → SHADER_READ|WRITE barrier is
|
|
inserted automatically, so the custom shader sees the colored stripes
|
|
drawn by the prior `DispatchQuads` and reads/writes the swapchain
|
|
image safely.
|
|
|
|
### [RayQueryPick](RayQueryPick/)
|
|
Regression test for the WebGPU software ray-query shim. Builds a
|
|
512-instance TLAS and shoots one ray through a `rayQuery=true`
|
|
`PlainComputeShader`, reading the committed hit back to the host and
|
|
checking it against the analytically-known answer. Guards against the
|
|
hardcoded-leaf-start TLAS-traversal bug (issue #25) that made every
|
|
rayQuery pick miss for realistic instance counts. WebGPU/DOM only.
|
|
|
|
### [HDRBloom](HDRBloom/)
|
|
Cross-backend-shaped HDR bloom on the WebGPU backend (issue #27). The RT
|
|
pipeline's RESOLVE writes linear radiance into a user `rgba16float`
|
|
texture (`StorageImage2D`, `PipelineRTWebGPU::Init(..., RGBA16Float)`),
|
|
two `PlainComputeShader` passes threshold + blur it through float storage
|
|
targets (`UICustomBindingKind::StorageTexture`), and a UI custom shader
|
|
composites scene + bloom with a Reinhard tonemap onto the canvas.
|
|
Exercises the three primitives an HDR post-process chain needs: float
|
|
textures, write-only storage-texture bindings, and pre-tonemap radiance
|
|
out of the wavefront. The threshold/blur passes run from `onBeforeUpdate`
|
|
so each gets its own queue submit — the storage-write → sampled-read
|
|
barrier WebGPU only provides between submits (or between passes), never
|
|
within a single compute pass. WebGPU/DOM only; the same chain is wireable
|
|
on Vulkan today via an offscreen HDR heap image + a composite `RenderPass`
|
|
(the present path records passes generically and barriers between them).
|
|
|
|
### [RTMultiShadow](RTMultiShadow/)
|
|
Multi-light shadowing through the wavefront RT pipeline (issue #30). Five
|
|
pillars on a checkered ground, four colored point lights; the closest-hit
|
|
emits one shadow ray **per light** from the same invocation, so up to four
|
|
rays per pixel resolve in a single SHADE pass. Exercises both halves of
|
|
the >1-ray-per-pixel-per-bounce widening: the atomic `rtAccumulate`
|
|
(per-channel f32 CAS — concurrent same-pixel adds don't race) and
|
|
`RTPass::raysPerPixel` (scales the ray/hit/payload buffers so the
|
|
per-light emits aren't capacity-dropped). Any regression shows up as
|
|
flickering dark noise or a missing shadow color in the overlap regions.
|
|
WebGPU/DOM only.
|