Preserve realtime volumetrics research

This commit is contained in:
Meta Vens 2026-05-08 20:51:14 +01:00
commit 8d501fd6f1
7 changed files with 238 additions and 1 deletions

2
.gitignore vendored
View file

@ -5,3 +5,5 @@ artifacts/
*.suo
.vs/
.idea/
research/volumetrics/sources/
research/volumetrics/extracted-text/

View file

@ -0,0 +1,26 @@
# Realtime Volumetrics Research
This folder preserves the renderer research notes for future Aquarium volumetric
work. Local source artifacts live in `sources/` and extracted working text lives
in `extracted-text/`; both are gitignored because the cache contains large slide
decks and copyrighted papers. The durable repo surface is the manifest and the
distilled notes.
## Files
- `source-manifest.md`: source list, URLs, local cache names, and download notes.
- `synthesis.md`: distilled lessons for Aquarium's renderer architecture.
## Current Direction
Aquarium should treat volumetrics as a renderer-owned field system, not a fog
color slapped onto the final image. The useful production pattern is a
frustum-aligned or Grid-aligned volume that stores physical-ish density,
extinction, scattering, lighting, and transmittance, then composites solids,
transparent surfaces, particles, diegetic UI, and field effects against the same
transport result.
Start small: one low-resolution field volume, one Self light source, Beer
transmittance, single scattering, stable reprojection/jitter, and explicit debug
modes. Add richer atmosphere, clouds, and streaming only after the simple field
earns its keep.

View file

@ -0,0 +1,36 @@
# Volumetrics Source Manifest
Local binary/text sources are cached under `research/volumetrics/sources/` and
working text extracts under `research/volumetrics/extracted-text/`. These folders
are gitignored; rerun the listed URLs if the cache is missing.
## Cached Sources
| Topic | Local file | URL | Notes |
| --- | --- | --- | --- |
| Bruneton atmosphere implementation | `bruneton-2017-implementation.html` | https://ebruneton.github.io/precomputed_atmospheric_scattering/ | 2017 documented implementation of Bruneton/Neyret precomputed atmospheric scattering. |
| Bruneton atmosphere shader docs | `bruneton-functions.glsl.html` | https://ebruneton.github.io/precomputed_atmospheric_scattering/atmosphere/functions.glsl.html | Core transmittance, single scattering, multiple scattering, irradiance, and lookup functions. |
| Wronski volumetric fog | `wronski-volumetric-fog-siggraph2014-advances.pdf` | https://www.realtimerendering.com/advances/s2014/wronski/bwronski_volumetric_fog_siggraph2014.pdf | SIGGRAPH 2014 Assassin's Creed IV volumetric fog deck with presenter notes. |
| Frostbite unified volumetrics | `hillaire-frostbite-pb-unified-volumetrics-siggraph2015.pptx` | https://advances.realtimerendering.com/s2015/Frostbite%20PB%20and%20unified%20volumetrics.pptx | Hillaire/Frostbite SIGGRAPH 2015 deck; large binary, local only. |
| Frostbite sky/atmosphere/clouds | `hillaire-frostbite-sky-atmosphere-clouds-siggraph2016.pdf` | https://media.contentapi.ea.com/content/dam/eacom/frostbite/files/s2016-pbs-frostbite-sky-clouds-new.pdf | SIGGRAPH 2016 physically based sky, atmosphere, and cloud rendering notes. |
| Dreams Learning from Failure | `dreams-learning-from-failure-siggraph2015-compressed.pdf` | https://advances.realtimerendering.com/s2015/AlexEvans_SIGGRAPH-2015-sml.pdf | Compressed SIGGRAPH 2015 Media Molecule deck with transcript-like presenter notes. |
| Dreams Media Molecule post | `dreams-learning-from-failure-mediamolecule.html` | https://www.mediamolecule.com/blog/article/siggraph_2015 | Official post for Alex Evans's SIGGRAPH talk. |
| Dreams Umbra video page | `dreams-learning-from-failure-video-page.html` | https://www.mediamolecule.com/blog/article/alex_at_umbra_ignite_2015_learning_from_failure_video | Official video-page wrapper. I did not find a separate clean transcript. |
| GigaVoxels paper | `gigavoxels-ray-guided-streaming.pdf` | https://maverick.inria.fr/Publications/2009/CNLE09/CNLE09.pdf | I3D 2009 paper on ray-guided streaming and brick/mipmap volume rendering. |
| GigaVoxels publication page | `gigavoxels-publication-page.html` | https://www.icare3d.org/research-cat/publications/gigavoxels-ray-guided-streaming-for-efficient-and-detailed-voxel-rendering.html | Abstract, authors, and publication metadata. |
| Horizon volumetric clouds | `schneider-horizon-volumetric-cloudscapes-siggraph2015.pdf` | https://advances.realtimerendering.com/s2015/The%20Real-time%20Volumetric%20Cloudscapes%20of%20Horizon%20-%20Zero%20Dawn%20-%20ARTR.pdf | Guerrilla SIGGRAPH 2015 deck on cloud modeling, lighting, and optimization. |
| Stable volume sampling | `bowles-fast-stable-volume-rendering-siggraph2015.pptx` | https://advances.realtimerendering.com/s2015/siggraph15_volsampling.pptx | Studio Gobo talk on stable undersampled volume rendering. |
| NVIDIA volumetric light scattering | `nvidia-fast-flexible-volumetric-light-scattering-gdc2016.pdf` | https://developer.nvidia.com/sites/default/files/akamai/gameworks/downloads/papers/NVVL/Fast_Flexible_Physically-Based_Volumetric_Light_Scattering.pdf | GDC 2016/GameWorks-style physically based volumetric light scattering. |
| Unreal volumetric fog docs | `unreal-volumetric-fog-docs.html` | https://dev.epicgames.com/documentation/en-us/unreal-engine/volumetric-fog-in-unreal-engine?application_version=5.6 | Current engine docs on frustum volume texture, temporal reprojection, and tradeoffs. |
| Frostbite 2016 source page | `frostbite-sky-atmosphere-cloud-rendering.html` | https://www.frostbite.com/frostbite/news/physically-based-sky-atmosphere-and-cloud-rendering | Official page with presentation/course-note links. |
## Not Fully Cached
- Bruneton & Neyret 2008 original paper: direct PDF downloads from KlayGE and
CiteSeer failed from this environment. Stable references:
- https://www.klayge.org/material/4_0/Atmospheric/Precomputed%20Atmospheric%20Scattering.pdf
- https://citeseerx.ist.psu.edu/document?doi=5cd50191a346535eef7e12c024592c3afdd29ad4&repid=rep1&type=pdf
- DOI: https://doi.org/10.1111/j.1467-8659.2008.01245.x
- A separate Dreams talk transcript was not found. The compressed SIGGRAPH PDF
contains substantial presenter-note text and is the preserved transcript-like
source for this pass.

View file

@ -0,0 +1,166 @@
# Realtime Volumetrics Synthesis
## Why This Exists
Aquarium needs volumetrics eventually: Grid fog, Self glow, light shafts, weather
fields, transport light, particles, and diegetic UI should live in one coherent
lighting story. The literature is blunt about the failure mode: separate fog,
particles, god rays, sky, and clouds become unrelated hacks unless they share a
field representation and light transport model.
## Durable Lessons
### Wronski: Frustum Volume First
Wronski's Assassin's Creed IV solution is the cleanest first production target
for Aquarium. Build a low-resolution frustum-aligned 3D texture, inject density
and lit scattering into it, integrate transmittance and in-scattering along view
depth, then apply the result with a single lookup during scene composition.
The important part is not the exact AC4 numbers. It is the pass shape:
1. Define a volume aligned to the camera frustum.
2. Inject participating-media density/extinction.
3. Light the volume from relevant scene lights and shadows.
4. Accumulate scattering/transmittance through depth.
5. Composite solids, transparent layers, particles, and UI against the same
volume result.
For Aquarium, this means the first serious fog pass should be an explicit render
stage, not code inside `shade()`. The field should start with Self as emitter and
one density source from the Grid/weather domain.
### Hillaire/Frostbite: Unify the Medium
Frostbite's move is to make all participating media speak the same units:
extinction, scattering, emission, albedo, phase, and transmittance. Particles,
fog volumes, clouds, and atmosphere are not separate final-image tricks; they
write into or interact with a shared volume representation.
The Frostbite deck also connects volumetrics to tiled/clustered lighting. Its
"froxel" idea is directly relevant to Aquarium's existing primitive froxel table:
align volume cells with screen/light tiles when possible, reuse culling, and keep
lighting work bounded by the cells and lights that can actually matter.
Aquarium lesson: extend the current froxel concept deliberately. Body broad
phase is not the same thing as a lighting volume, but the renderer already has a
mental slot for conservative 3D bins. Use that grammar instead of inventing a
separate fog bureaucracy.
### Bruneton: Precompute Physics, Test the Math
Bruneton's atmosphere work is the heavy end of the spectrum: transmittance,
single scattering, multiple scattering, and irradiance are precomputed into LUTs
so runtime rendering becomes lookup-driven. The 2017 implementation is more
useful than the raw 2008 paper for engineering because it documents the texture
mappings, removes Earth-only ad hoc constants, supports configurable spectra and
density profiles, and tests dimensional consistency by compiling GLSL-like code
through C++ types.
Aquarium should not start here. A full planetary sky model is premature while the
Grid field is still young. But Bruneton is the north star for any future
planetary atmosphere or large-scale sky: precompute smooth high-dimensional
transport, make texture-coordinate mappings explicit and planet-parameterized,
and test physical units instead of "looks close" math.
### Unreal: Reprojection Helps, But Trails Are Real
Unreal's volumetric fog docs preserve the production compromise: low-resolution
frustum volume textures are made acceptable with heavy temporal reprojection and
sub-voxel jitter. The cost is history artifacts for fast-changing lights.
Aquarium lesson: add temporal smoothing only with debug visibility and light
history policy. Self is stable enough for reprojection. Fast diegetic flashes,
cursor beams, or short-lived UI lights may need reduced volumetric contribution
or separate non-history paths.
### Bowles/Gobo: Make Samples Stable in World/Volume Space
The Studio Gobo volume sampling talk attacks the same problem from the sample
distribution side. Undersampling in depth aliases under camera motion. Holding
samples stationary in the volume and using a `1/z`-style distribution keeps more
quality near the viewer while preserving draw distance.
Aquarium lesson: when the Grid field starts marching, avoid camera-locked random
noise that swims. Either anchor sample positions in world/Grid/volume space or
make the temporal reprojection own the instability explicitly.
### Horizon Clouds: Author Shape Separately From Lighting
Horizon's cloud work separates weather/shape authoring from lighting. Cloud
density is built from layered procedural fields and weather maps, then lit with
cheap approximations to Beer transmittance, anisotropic phase behavior, and
multiple-scattering feel.
Aquarium lesson: weather texture and visual density are not lighting. Keep
authoring fields, simulation fields, and lighting fields separate until they
deserve to merge. The current Grid weather color should not become the fog
density API by accident.
### GigaVoxels: Stream What Rays Ask For
GigaVoxels is less about fog and more about large sparse volumetric worlds. Its
central idea is ray-guided streaming: render traversal discovers missing data,
requests production/loading, and uses temporal coherence plus brick/mipmap
structures to stay interactive with huge virtual resolution.
Aquarium lesson: if the world becomes brushy, cloudy, or memory-rich enough to
need sparse volume storage, do not build a giant monolithic 3D texture. Use
bricks, mip/filter levels, and demand-driven production. This also supports the
Epiphany doctrine: persistent state should store meaningful field chunks, not one
hero JSON blob pretending to be a database.
### Dreams: Failures Are Evidence, Not Souvenirs
Alex Evans's Dreams talk is relevant because Aquarium is also tempted by
unconventional rendering. Dreams tried multiple renderers before settling on a
pipeline motivated by both aesthetic and technical constraints: CSG/SDF scene
description, compute-heavy evaluation, multi-resolution point clouds, splats,
and a painterly target that made some "incorrect" choices useful.
The preserved lesson is process discipline. Explore, measure, and throw away
systems that do not serve the final image. Aquarium should carry forward
explicit maps of each rendering experiment: input, output, artifact, cost, and
why it stayed or died. Dead branches belong in evidence notes, not live renderer
architecture.
## Suggested Aquarium Volumetric Roadmap
1. Add renderer debug modes before fog work: Grid hit, depth, terrain normal,
body bins, light contribution, and line/fog masks.
2. Add an explicit low-resolution volume pass:
- frustum-aligned 3D texture
- logarithmic or perspective depth slicing
- channels for extinction and in-scattered radiance
- one Self light source
- one Grid/weather density function
3. Integrate front-to-back transmittance and in-scattering into an accumulated
volume texture.
4. Composite terrain, bodies, particles, and overlay/diegetic surfaces against
the volume consistently.
5. Add temporal reprojection and jitter only after static debug views prove the
transport terms are sane.
6. Add local density injectors: body wakes, object auras, weather bands, and
diegetic UI light, all writing physical-ish volume parameters.
7. Consider Bruneton-style LUTs only when Aquarium needs a sky/atmosphere model
with view-from-ground-to-space behavior.
8. Consider GigaVoxels-style sparse bricks only if volume data grows beyond one
bounded field texture.
## Non-Goals For The First Pass
- Do not implement full multiple scattering immediately.
- Do not hide bad lighting with bloom or blue fog.
- Do not make particles, Grid weather, and fog use separate light models.
- Do not use a giant persistent monolithic volume cache.
- Do not ship temporal reprojection without history rejection/debug controls.
## Aquarium Invariants To Add
- Volumetric lighting is a renderer-owned field, not a material afterthought.
- Density, extinction, scattering, emission, and transmittance should be explicit
terms even when the first implementation is approximate.
- Self is the first volumetric light source.
- Grid/weather domains may inject density but do not own the lighting equation.
- Any shader/CPU contract for volumetric fields must be watched as a reload
boundary, just like `AquariumFrame`.

View file

@ -5,3 +5,4 @@
{"topic":"dev_reload_visible_headless_split","summary":"Fixed dev-reload so headless smoke runs use separate PID state and logs from the visible dev window, preventing headless verification from stopping the active window. Added -Reopen to relaunch the last visible slot without rebuilding.","files":["scripts/dev-reload.ps1","README.md","state/evidence.jsonl"],"verification":[".\\scripts\\dev-reload.ps1 -Reopen",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4","visible Aquarium PID remained running after headless smoke"],"ts":"2026-05-08"}
{"topic":"grid_far_distance","summary":"Replaced the shader fixed raymarch far distance with a per-frame value equal to camera distance from the Grid origin plus Grid radius, matching the circular Grid fade boundary.","files":["src/Aquarium.Engine/Render/D3D11Renderer.cs","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","docs/hlsl-renderer.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"topic":"watcher_renderer_contract_reload","summary":"dev-watch now fingerprints the AquariumFrame cbuffer in Aquarium.hlsl as host contract input. Ordinary shader edits can still hot reload, but cbuffer layout changes trigger a host reload so C# frame constants and shader reads stay in sync.","files":["scripts/dev-watch.ps1","docs/hlsl-renderer.md","state/evidence.jsonl"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -RetainSlots 4",".\\scripts\\dev-watch.ps1 -NoInitialLaunch -Once"],"ts":"2026-05-08"}
{"topic":"volumetrics_research_sweep","summary":"Preserved a realtime volumetrics research map covering Bruneton atmospheric scattering, Wronski AC4 volumetric fog, Hillaire/Frostbite froxel volumetrics and sky/clouds, Dreams Learning from Failure, GigaVoxels, Horizon clouds, Gobo stable volume sampling, NVIDIA GDC volumetric scattering, and Unreal volumetric fog docs. Distilled the Aquarium path: explicit renderer-owned low-resolution volume pass first, Bruneton LUT atmosphere later, sparse brick streaming only if scale demands it.","files":["research/volumetrics/README.md","research/volumetrics/source-manifest.md","research/volumetrics/synthesis.md","state/map.yaml","state/memory.json",".gitignore"],"verification":["downloaded local source cache under research/volumetrics/sources","extracted working text under research/volumetrics/extracted-text","source cache and extracts gitignored due binary size and copyright"],"ts":"2026-05-08"}

View file

@ -28,6 +28,7 @@ current_model:
runtime_surface: docs/cult-runtime-surface.md
native_spine: docs/vortice-spine.md
input: docs/input.md
volumetrics_research: research/volumetrics/synthesis.md
invariants:
- The camera target is the Grid center on the global XY plane.
@ -51,6 +52,7 @@ renderer_state:
next:
- Add explicit renderer debug modes for hits, normals, depth, bins, and lighting.
- Restore HDR scene target, gentle pre-tonemap bloom, and ACES as explicit passes.
- Add volumetrics as an explicit renderer-owned field pass, starting from Wronski/Hillaire-style frustum volume lighting with Self as the first emitter.
- Move Grid gradients into the Grid target for cheaper terrain normals.
- Rebuild lighting as an Aquarium-owned field before adding richer fog.
- Add diegetic labels and object-local menus after the renderer and text contracts are stable.
@ -59,5 +61,6 @@ next_actions:
- Keep main as the live development branch.
- Verify publish output after every packaging-affecting change.
- Add renderer debug controls through the DirectWrite overlay path.
- Use research/volumetrics/synthesis.md before designing fog, atmospheric scattering, clouds, or sparse volume storage.
- Promote runtime knobs into typed CultCache documents.
- Port only proven synth concepts into C# when audio returns; keep external prototypes as references, not engine baggage.

View file

@ -35,7 +35,10 @@
"Lighting must be diegetic by default. Self is the initial emitter; later light should come from Aquarium-owned fields and transport, not ambient convenience fill.",
"If surfaces read brighter than Self, the light story is broken. Diagnose source terms, texture contents, bloom order, and tonemapping before polishing.",
"HDR bloom belongs before tonemapping and should be gentle in intensity but broad enough to spread true emissive energy.",
"Future volumetric lighting should be a field sampled consistently by terrain, planets, fog, particles, and diegetic UI. Do not fake only the planet term if the scene is supposed to bounce light."
"Future volumetric lighting should be a field sampled consistently by terrain, planets, fog, particles, and diegetic UI. Do not fake only the planet term if the scene is supposed to bounce light.",
"Volumetric design must start from research/volumetrics/synthesis.md. The first pass should follow Wronski/Hillaire production shape: explicit low-resolution frustum volume, injected density/extinction/scattering, Self as first emitter, front-to-back transmittance/in-scattering integration, then consistent composition.",
"Bruneton-style atmospheric scattering is the later sky/planet solution, not the first Grid fog pass. Use LUTs, explicit texture mappings, and unit-tested physical terms when Aquarium reaches ground-to-space atmosphere.",
"GigaVoxels-style ray-guided sparse bricks are only for large sparse field/world storage. Do not turn early fog into a monolithic persistent volume cache."
],
"text_and_ui": [
"Overlay text uses DirectWrite/Direct2D after scene rendering. It is crisp final-pixel UI for debug surfaces, terminals, inspectors, and splash/status text.",