Skip to content

World-space hatching lab: four strategies compared on an architectural test scene - #9

Closed
cbgbt wants to merge 1 commit into
developfrom
hatch-lab
Closed

World-space hatching lab: four strategies compared on an architectural test scene#9
cbgbt wants to merge 1 commit into
developfrom
hatch-lab

Conversation

@cbgbt

@cbgbt cbgbt commented Aug 3, 2026

Copy link
Copy Markdown
Owner

What this is

An experimentation harness for the "beautiful architectural renderings" direction: one test scene (gabled house with door/window openings, chimney, sphere-canopy tree, ground plane, single point light) rendered through four hatching strategies so they can be compared visually. Run with:

cargo run --release -p hatch-lab

Outputs land in hatch-lab/renders/*.svg (gitignored, like all render outputs in this repo).

Core seams added to raydeon

Two minimal public APIs that world-space hatching needs, both extracted from existing internals rather than new logic:

  • Scene::illumination_for_hit — computes total light arriving at a caller-constructed HitShape, so hatch generators can sample illumination at surface points they already know.
  • SceneCamera::clip_and_project — the existing chop → occlusion-clip → join → project pipeline, now callable with arbitrary caller-generated world-space segments. render() is reimplemented on top of it.

Strategies

Strategy Idea
a screen_space Existing screen-space hatching (baseline), seeded
b world_uniform 45° hatch lines generated on each face in world space; stochastic keep driven by sampled illumination
c crosshatch_tonal Discrete tone bands accumulate cross directions at tightening spacing (engraving look)
d light_flow Hatch direction = light direction projected onto each face; sphere rings wrap the light axis

Hatch lines are generated in face-plane coordinates, clipped to the convex outline minus door/window holes, lifted ~0.006 world units off the surface (so their visibility rays don't re-intersect their own face), then illumination-filtered per ~0.16-unit sample using the same slice/join machinery as the main renderer.

Notable findings while building this

  • Hatch lines lying exactly on a face self-occlude — the midpoint visibility ray hits its own surface at distance ~0 and gets clipped. The existing shapes dodge this by expanding outlines outside their face; surface detail needs a normal lift. A first-class world-space hatching API in raydeon should handle this internally.
  • join_slices drops the shape reference when rebuilding segments, so render output can't currently be traced back to materials — this blocks per-pen/per-layer SVG output and is worth fixing in the planned cleanup.
  • World-space strategies are markedly cheaper than the screen-space pass here (~10–40ms vs ~120ms) because they only sample where surfaces exist, and the screen-space hatch filter is currently single-threaded due to the shared RNG.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WT2VUpRTEKguqL42ehtXdn

Adds two small seams to raydeon's renderer so callers can generate their
own surface detail:

- Scene::illumination_for_hit computes lighting at a caller-constructed
  surface hit, letting hatch generators sample light at points they
  already know lie on a face.
- SceneCamera::clip_and_project exposes the existing chop/occlude/join
  projection pipeline for caller-provided world-space segments.

The new hatch-lab crate renders one architectural test scene (gabled
house with door/window openings, chimney, sphere-canopy tree, ground
plane, single point light) through four hatching strategies for visual
comparison:

- a_screen_space: the existing screen-space hatching, seeded
- b_world_uniform: 45-degree world-space hatching per face, stochastic
  keep probability driven by sampled illumination
- c_crosshatch_tonal: discrete tone bands accumulate cross-hatch
  directions at tightening spacing, engraving-style
- d_light_flow: hatch direction follows the light direction projected
  onto each face; sphere rings wrap the axis pointing at the light

Hatch lines are generated in face-plane coordinates, clipped to convex
outlines minus door/window holes, lifted slightly off the surface so
their visibility rays do not re-intersect their own face, then filtered
sample-by-sample against scene illumination.

Also removes two unused bon::builder imports flagged by clippy.

Claude-Session: https://claude.ai/code/session_01WT2VUpRTEKguqL42ehtXdn
@cbgbt

cbgbt commented Aug 3, 2026

Copy link
Copy Markdown
Owner Author

Closing per Sean's preference to work from branches without PRs — the branch stays pushed.

@cbgbt cbgbt closed this Aug 3, 2026
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