Skip to content

feat: add more advanced rendering effects#386

Merged
sebcrozet merged 11 commits into
masterfrom
advanced-effects
May 31, 2026
Merged

feat: add more advanced rendering effects#386
sebcrozet merged 11 commits into
masterfrom
advanced-effects

Conversation

@sebcrozet

Copy link
Copy Markdown
Member

This adds multiple improved rendering effects:

  • Order Independent Transparencny (OIT)
  • Cascading Shadow maps
  • Tonemapping
  • Bloom
image image image

This also introduces a path-tracer with hardware acceleration on platforms where wgpu supports path tracing. The raytracer is also compatible with offscreen rendering. It is also compatible on the web, but without access to hardware-accelerated ray queries.

image image image

sebcrozet and others added 11 commits May 31, 2026 19:39
A progressive Monte-Carlo path tracer that renders the existing scene graph,
selectable per frame instead of the rasterizer:

- Two backends sharing one WGSL kernel: a software compute BVH traversal and a
  hardware ray-query path (`hw_raytracer` feature), chosen at runtime.
- Two-level (instanced) BVH so instanced scene nodes are traced once per mesh.
- Unified PBR/BSDF surface model (diffuse, metal, glass), per-object materials
  and textures, area-light next-event estimation with MIS, thin-lens depth of
  field, and image-based lighting from an equirectangular HDRI.
- Edge-aware à-trous denoiser with first-hit albedo/normal guides.
- Alpha (coverage) transparency; the background color is shown on camera/specular
  ray misses but does not light the scene; ambient acts as a uniform fill light.
- Progressive accumulation; the radiance and denoiser guides share one buffer so
  the compute stage stays within WebGPU's 8-storage-buffers-per-stage limit.
- BSDF setters on SceneNode3d and `render_raytraced`/offscreen entry points, with
  examples (basic, BSDF gallery, denoise comparison, offscreen, transparency).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ransparency)

The rasterizer now renders into a linear Rgba16Float HDR film and resolves it to
the (non-sRGB) surface with a configurable tonemap operator, instead of writing
LDR directly:

- Tonemap operators: None, ACES, Reinhard, AgX, Khronos PBR Neutral (default),
  and Tony McMapface (baked CC0 3D LUT). Operator + exposure are configurable and
  shared with the path tracer's resolve pass.
- Physically-weighted bloom (threshold + progressive down/upsample) on the HDR
  film before tonemapping.
- Weighted-blended order-independent transparency: a transparent pass accumulates
  into additive color/reveal targets that are composited over the opaque film
  (RenderPhase opaque/transparent).
- All rasterizer materials target the shared HDR render format.
- Examples: hdr_bloom, tonemapping comparison UI, transparency.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Shadow mapping for the rasterizer's directional, spot, and point lights, applied
in the PBR lighting shader:

- All shadow maps pack into one Depth32Float 2D-array atlas; per-light view-proj
  matrices and metadata drive sampling, so the material binds a single depth
  texture + comparison sampler regardless of light count.
- Directional lights use cascaded shadow maps: the camera frustum is split
  logarithmically (cascade 0 spans [near, first_cascade_far_bound], the rest grow
  geometrically), each cascade fit to its slice with a rotation-invariant, texel-
  snapped bounding box. The split range is derived from the camera (not the scene)
  so distant/fallen geometry can't make shadows flicker or degrade, and cascades
  are selected by view depth and cross-faded across boundaries.
- Spot lights use a perspective map; point lights an unrolled cube map.
- Castaño 2013 optimized PCF (tent-weighted 9-tap) for smooth, crisp edges;
  configurable atlas resolution, cascade count, shadow distance, and bias.
- Object materials kept within WebGPU's 4-bind-group limit (albedo + PBR maps
  merged into one group, shadows in another).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Auxiliary render outputs produced by re-rendering the scene with dedicated
materials (no path tracer needed):

- Linear view-space depth, world/view-space normals, and per-object segmentation
  ids (with a colorized variant for human-readable PNGs).
- Per-object segmentation id on Object3d; `snap_depth`/`snap_normals`/
  `snap_segmentation*` entry points on the window, plus an AOV example.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds native (and, for windowed examples, web/wasm) .run configurations for the
examples that lacked one: aov (headless, native only), dda_raycast2d, hdr_bloom,
raytracing_bsdf, raytracing_denoise, raytracing_transparency, shadows,
tonemapping (with the egui feature), and transparency.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The script now lists all 49 examples (added hdr_bloom, tonemapping, shadows,
transparency, aov, and the raytracing* examples).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The HDR pipeline made the scene render into a linear HDR film (and added a
second, multi-target order-independent-transparency pass), which broke custom
Material3d implementations written against the old single-surface-format pass:

- The custom_material example built its pipeline for the surface format
  (Bgra8Unorm) instead of the HDR render format (Rgba16Float) -> incompatible
  color attachment.
- Every material was also invoked in the transparent (OIT) pass, whose two render
  targets don't match a single-target opaque pipeline -> a second validation error.

Fix both: the example now targets Context::render_format(); and Material3d gains a
renders_in_transparent_phase() method (default false) so a material is skipped in
the OIT pass unless it builds OIT-compatible pipelines. The built-in ObjectMaterial
opts in (true); custom materials stay opaque-only by default and no longer crash.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- rustfmt: reflow an import in object3d.rs.
- rustdoc (-D warnings): de-link intra-doc references to private items
  (super::gpu_scene, ShadowUniforms, scene_render_view) that rustdoc rejected.
- unused imports in the raytracing_bsdf / raytracing_denoise examples (caught by
  cargo test with -D warnings).
- typos: fix `halfs` -> `halves` and `tlo`/`thi` -> `t_lo`/`t_hi`, and add a
  .typos.toml allowing the rendering term "MIS" (Multiple Importance Sampling).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@sebcrozet sebcrozet merged commit 41a9a0f into master May 31, 2026
5 checks passed
@sebcrozet sebcrozet deleted the advanced-effects branch May 31, 2026 22:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant