Crafter.Graphics/examples
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Jorijn van der Graaf c97a3048fb
fix(webgpu): drop the removed UICustomBinding::_pad from the CustomShader example
Examples
- CustomShader did not build for wasm32-wasip1: its DOM branch still set
  UICustomBinding::_pad, which 097cc37 (#27) turned into format. The
  invalid designator left the bindings array of incomplete type, so the
  Load call after it found no overload either. The designator is dropped
  rather than renamed, as HDRBloom does: format is 0 for anything but a
  StorageTexture binding, and a buffer binding has no texel format to
  give. The native branch was never affected.
- Every other example with a DOM path (HelloUI, HelloDom, HDRBloom,
  RayQueryPick, RTMultiShadow, RTStress, RTVolume, VulkanTriangle,
  Sponza) builds for wasm at this commit. Nothing builds them
  otherwise, which is how this one fell behind.

Closes #158.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 08:07:00 +01:00
..
CustomShader fix(webgpu): drop the removed UICustomBinding::_pad from the CustomShader example 2026-10-31 08:07:00 +01:00
Decompression SPDX license update 2026-07-22 18:09:06 +02:00
HDRBloom SPDX license update 2026-07-22 18:09:06 +02:00
HelloDom SPDX license update 2026-07-22 18:09:06 +02:00
HelloUI SPDX license update 2026-07-22 18:09:06 +02:00
HelloWindow SPDX license update 2026-07-22 18:09:06 +02:00
InputSystem SPDX license update 2026-07-22 18:09:06 +02:00
RayQueryPick SPDX license update 2026-07-22 18:09:06 +02:00
RTMultiShadow SPDX license update 2026-07-22 18:09:06 +02:00
RTStress SPDX license update 2026-07-22 18:09:06 +02:00
RTVolume feat(device): applications ask for the device features their shaders use 2026-10-31 06:40:02 +01:00
Sponza feat(device): applications ask for the device features their shaders use 2026-10-31 06:40:02 +01:00
SponzaBench feat(device): applications ask for the device features their shaders use 2026-10-31 06:40:02 +01:00
VulkanTriangle feat(device): applications ask for the device features their shaders use 2026-10-31 06:40:02 +01:00
LICENSE SPDX license update 2026-07-22 18:09:06 +02:00
README.md test(webgpu-rt): RTMultiShadow example exercising N shadow rays/pixel/bounce (#30) 2026-06-09 22:45:33 +00:00

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:

cd examples/<name>
crafter-build -r

Index

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

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

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

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

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

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

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

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.