Light Propagation Volumes
Light Propagation Volumes is a technique for approximating the first bounce of diffuse global illumination. I present a finite element approximation, using Spherical Harmonics(SH) and Radiance Volumes(RV). This solution is fully dynamic and the additional steps can be easily implemented into pre-existing complex rendering pipelines.

## Spherical Harmonics

SH can be used for approximating a signal integrated over a sphere. This is very useful when trying to simulate scattering phenomena. Various previous uses in computer graphics include precomputed radiance transfer and radiance probes.

Real-valued SH are defined as: \begin{equation} Y_{l}^{m}(\theta, \phi) = \Phi^{m}(\phi) N_{l}^{|m|} P_{l}^{|m|}(cos \theta) \end{equation} Where: \begin{equation} \Phi^{m}(\phi)=\begin{cases} \sqrt{2}cos(mx), & \text{m $>$ 0}.\\ 1, & \text{m = 0}. \\ \sqrt{2}sin(|m|x) & \text{m $<$ 0} \end{cases} \end{equation} \begin{equation} N_{l}^{|m|} = \sqrt{\frac{2l + 1}{4\pi} \frac{(l-m)!}{(l + m)!}} \end{equation} And $$P_{l}^{|m|}$$ are the associated Legendre polynomials: \begin{align*} P_{0}^{0} & = 1\\ P_{1}^{0} & = x\\ P_{1}^{1} & = -\sqrt{1 - x^2}\\ P_{0}^{2} & = \frac{1}{2}(3x^2-1)\\ P_{1}^{2} & = -3x\sqrt{1 - x^2}\\ P_{2}^{2} & = 3(1 - x^2)\\ ... \end{align*} I will assume points on a unit sphere are defined in cartesian coordinates as: \begin{align*} x & = sin(\theta) cos(\phi)\\ y & = sin(\theta) sin(\phi)\\ z & = cos(theta)\\ \end{align*} solving these equations for the first two bands gives: \begin{align*} Y_{0}^{0}(\theta, \phi) & = \sqrt{\frac{1}{4\pi}} \\ Y_{-1}^{1}(\theta, \phi) & = -\sqrt{\frac{3}{4\pi}} y \\ Y_{0}^{1}(\theta, \phi) & = \sqrt{\frac{3}{4\pi}} z \\ Y_{1}^{1}(\theta, \phi) & = -\sqrt{\frac{3}{4\pi}} x \\ \end{align*}

Our constants now represent radiance, which is not what we want, Spherical harmonics are surprisingly bad at approximating radiance, they are however extremely good at approximating irradiance. Thus, we want our constants to represent Irradiance. We can convert them by multiplying with normalization constant $$Â_{l}$$, which is defined as: \begin{align*} \hat{A}_{0} & = \pi \\ \hat{A}_{1} & = 2\pi / 3 \\ \end{align*} I precompute these values and use them to represent a normal by a vector of SH coefficients. I renormalize them right away to form a hemispherical lobe. Finally, we must not forget to scale the resulting vector with the weight of the surfel.

## Propagation

Now we have a 3D texture filled with SH coefficients. The next step is propagation. Propagation is a sequential iterative process where each iteration represents one discrete step of light propagation in the radiance volume. The propagation can be visualized as every grid cell sending its directional energy to neighbors through the face that they share. However, in practice, this will be a race condition prone approach. Multiple threads will be reading and writing from/to the same cell in an unspecified order. This will cause race conditions and, therefore, flickering. I suggest a gathering approach, where threads sample the data from neighboring cells. We must not forget that we are propagating light through a cubical grid. If we do not project our propagated light correctly there will be artifacts in the form of unlit spots. this is done by re-projecting our cosine lobes in the direction of the four side faces and just using the current lobe for the front facing cube. All the resulting SH coefficients are added together and stored in their cell. Note that in the discussed implementation I have separate injection textures and accumulation buffers. My Geforce GTX660m only allows 32bit typed loads from RWTextures, I worked around this issue by using a RWStructuredBuffer<float4> to store the accumulated SH coefficients.

## Sampling

Lastly, we have to sample our accumulation buffers, luckily this is a fairly straightforward process. We take the world space normal of the fragment we are shading and project it into SH basis. Then we use the world space position of the fragment to do linear sampling on our accumulation buffers. Finally, we do dot products and a multiplication with PI to find the final flux.

## Result Figure1: San Miguel with Light Propagation