Graphics Reference
In-Depth Information
The next step is to calculate the view ray vector during our lighting pass. We'll do this
by first determining the vector from the camera to the vertex position in the vertex shader.
Then in the pixel shader, we'll normalize this vector to get the final view ray vector. This
vector is then multiplied with the distance value sampled from the g-buffer and added to
the camera position to reconstruct the original surface position. Note that the vertex posi-
tion, camera position, and resulting camera ray can be in any coordinate space, as long as
the same space is used for all three of them. This allows reconstructing either a view space
or a world space position. The code in Listing 11.10 uses world space for simplicity of
presentation.
//
--
Light
vertex
shader
--
#if,
VOLUMES
II
Calculate
the
world
space
position
for
a
light
volume
float3
positionWS
=
mul(input.PositionOS, WorldMatrix);
#elif
QUADS
//
Calculate
the
world
space
position
for
a
full-screen
quad
(assume
input
//
vertex
coordinates
are
in
[-1,1]
post-projection
space)
float3
positionWS
=
mul
(
input.PositionOS, InvViewProjMatrix);
#endif
//
Calculate
the
view
ray
output.
ViewRay
=
positionWS
-
CameraPositionWS;
// --
Light Pixel
shader
--
//
Normalize the
view
ray,
and apply
the
distance
to
reconstruct position
float3
viewRay
=
normalize(input.
ViewRay);
float
viewDistance
=
DistanceTexture.Sample(PointSampler, texCoord);
float3
positionWS
=
CameraPositionWS
+
viewRay
*
viewDistance;
Listing 11.10.
Light shader code for view ray calculation and position reconstruction.
This provides us with a flexible and fairly efficient method for reconstructing position
from only a single high-precision value stored in the g-buffer. However, we can still make
further optimizations if we restrict ourselves to view space, since
in
view space the view
frustum is aligned with the Z-axis.
When reconstructing a view space position, we can extrapolate the view ray until it
intersects with the far clipping plane. Computing this intersection point is trivial, since it's
the point where the Z component is equal to the far clip distance. When rasterizing a quad
for a directional light, it's even simpler, since the frustum corner position can be linearly
interpolated. With the Z component of the view ray set to a known value, it is no longer
necessary to normalize the view ray vector in the pixel shader. Instead, we can multiply it
by a value that scales along the camera's z-axis to get the final reconstructed position. In the
case where Z is the far clip distance, we want to scale by a ratio of the original surface depth
relative to the far clip plane. In other words, the surface's view space Z divided by the far
Search WWH ::
Custom Search