God rays / volumetric sun shafts (like Black Dragon) #208
Labels
No labels
amd
avatars
bug
builder
cannot-reproduce
crash
epic
feature
from-viewer
gl-removal
known-limitation
monitoring
parity
perf
platform
priority
critical
priority
high
priority
low
priority
medium
provenance
rendering
rt
status
in-progress
status
testing
status
up-next
triage
ui
upstream
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
sky_line/Slipstream#208
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Light shafts from the sun and moon through gaps in geometry (trees, windows, clouds), as Black Dragon offers, integrated into the Vulkan post / lighting chain with a Lightbox-style control set.
A full spec (BD's approach, the options for our pipeline, the recommended design, cost and settings) will be added as a comment.
Related: #118 (Photo later: motion blur, volumetric sun shafts, temporal AA), #119 (photography suite), #185 (RT sun shadows).
Spec: God rays / volumetric sun shafts (#208)
Related: #118, #119, #185 (RT sun). Based on the Vulkan renderer (
llcleanrenderervk.cpprecordWorld,clean_draw_common.glsl,clean_frame_info.glsl,clean_taa.comp),research/black_dragon_features.md, and BD's shader source (github.com/NiranV/Black-Dragon-Viewer,class3/deferred/volumetricLightF.glsl).1. What Black Dragon does
Where it runs:
LLPipeline::renderVolumetric, one full-resolution fragment pass. It runs after tonemap and glow generation and beforecombineGlow, so it adds light to display-space LDR colour, which is not HDR-correct.How it works:
godray_ressamples from the eye toward the fragment, capped at 512 m.rand(tc)offset. There is no temporal filtering.nonpcfShadowAtPos. The cascade is chosen by view z, ignoring the shadow far clip.haze_density/(blue_density+haze_density),sunlight_color, the multiplier, andmax(falloff/depth,1). There is also an odddepth *= pow(depth,100)on raw depth.GODRAYS_FADEdefine fades the effect by sun direction.Settings:
RenderVolumetricLighting(on/off),…Resolution(steps; the research notes say 32),…Multiplier,…FalloffMultiplier,…Directional. The Multiplier/Falloff defaults are unconfirmed. The machinima panel'sRenderGodrays*bindings are stale. Release 5.4.4 restored the feature after PBR broke it, "with better alpha handling, sorted behind DoF".Known limitations:
2. Options for us
recordFlareStatealready computes the sun's UV and visibilitysunShadow); noise without accumulation. In RT sun mode (RenderVKSunShadows 2) the cascades aren't rendered, so the map is stale.compshader usesGL_EXT_ray_querytodayVerdict: build (b). It fixes BD's flaws: HDR compositing, a real phase function, temporal accumulation, reduced resolution. (a) fails the window-into-a-dark-room and sun-off-screen cases. In RT sun mode, (b) gets a cheap dedicated cascade set; (d) is a later "ultra" tier.
3. Recommended design
Pass placement in recordWorld:
clean_godrays.comp: right after the depth pre-pass and SSAO (g_ssao/g_occl). Opaque depth is final there, and the march doesn't depend on pass 1. Output: an RGBA16F in-scatter target atrw/scale × rh/scale(render extent, not display).recordRefractCopy.clean_taa.compmarks a pixel reactive where the final colour differs fromuRef, the refraction copy. Shafts added after the copy would be flagged reactive and get less history weight exactly where the dither needs accumulating.clean_hiz.compstores max depth and only runs with occlusion culling on, so don't depend on it.Inputs (already in the frame UBO
ssr.*/ push constants):uDepth(NEAREST).uShadowMap,shadow_mat[4],shadow_clip.atmosLightDir(). This is already whichever body is active, so moon shafts come for free.atmos[8]/ moonatmos[9]*0.7, selected byatmos[9].w.haze_density,blue_density,density_mul.taa_jitter/taa_params, IGN (projIGN).Scattering:
L += T * sigma_s * phaseHG(dot(V,L), g) * shadow(P) * sunColour * dt, with transmittanceTfrom the same density.sigma_s= haze density × user intensity, so shafts follow the environment's haze.min(depth, shadow_clip.w, MaxDist). Taps beyond the far split count as lit, likesunShadow's fade.Noise and TAA:
taa_prev_vp(M3).mOffscreen, one frame, no history): 4× steps at full resolution.Sun position:
GODRAYS_FADEcrudely approximates.shadow_params.w == 0or the light colour's luminance is ≈ 0.Water:
water[3].w) for pixels below it.water[5].w): water fog colour and density (water[4]) as the medium, with light attenuated by depth below the surface. This is its own milestone; M1 turns the effect off underwater.Other cases:
record*paths.4. Settings and UI
RenderVKGodRaysRenderVKGodRaysIntensityRenderVKGodRaysAnisotropyRenderVKGodRaysMaxDistRenderVKGodRaysStepsRenderVKGodRaysScaleRenderVKGodRaysUnderwaterpanel_lightbox_scene.xml, next to the shadow and SSAO controls; the tier combo also in the Graphics prefs.RenderVolumetricLighting*settings in the viewer importer: on → tier 2, Resolution → Steps, Multiplier → Intensity.5. Cost targets
Estimates, to be confirmed with the timers. Mid = RTX 3060 (our mid-range datapoint), high = 4080-class.
GPU timers: sub-marks
c_godraysafter the march andg_godrays_compafter the composite. (Sub-marks, because the 8 main pass indices are a fixed pool.)6. Milestones
regen_world_spv.py.7. Test plan
mOffscreen, large sizes): no visible noise.c_godraysper tier at 1440p against the targets.Sources: BD repo, BD 2.4.1.9 volumetrics write-up, BD releases.
Verified done: VK god rays: cascade and ray-traced march, depth-aware composite, temporal accumulation, RT budget, Lightbox controls. Commits:
0512e01500,b64f029ac4,c2f39a2dd6,e9dfb6cf31,731887e445,186b633052,9579c41ddb. Shipped in v1.0.0-beta.1.