capsuleOcclusion.renderFeature
The render feature behind `OcclusionProxy` and `@builtin::systems.proxyOcclusion.proxyOcclusion`. One compute pass runs after lighting, at order 50.
capsuleOcclusion
The render feature behind OcclusionProxy and
@builtin::systems.proxyOcclusion.proxyOcclusion. One compute pass runs after
lighting, at order 50.
For each pixel it reconstructs the world position and normal from
@scene.depth and @scene.normal, then integrates the solid angle each proxy
capsule subtends over the hemisphere above that point.
The sphere term
The occlusion of a sphere is computed exactly rather than with the usual
cos(theta) * r^2 / d^2 approximation. That approximation collapses as the
shaded point approaches or enters the sphere — which is precisely where a
grounding contact lives, so the cheap form fails exactly where the feature is
supposed to work.
A capsule is a swept sphere, so its occlusion is the sphere term evaluated at whichever point of the sweep is nearest the surface.
Proxies occlude independently, so what survives them all is the product of what survives each. Summing would let three weak proxies black out a surface none of them covers.
Not double-darkening
There is no shadow buffer to read, so how lit a pixel already is is estimated
from its lit colour against its own albedo (@scene.color over
@scene.material's base colour). A surface sitting in shadow-map shadow reads near zero there,
and scaling the occlusion by it is what stops a proxy darkening what is already
dark.
Camera
The camera comes from @frame.camera and the target is screen-sized, so
occlusion is correct in offscreen captures and render-to-texture cameras, not
only the live viewport.
Parameters and shapes arrive through the proxy_occlusion_params and
proxy_occlusion_shapes buffers, packed by
@builtin::systems.proxyOcclusion.proxyOcclusion.
Scoped to this part · feeds back into the world's score.