Sampling Visible Normals for GGX BRDF

Posted by Shih-Chin on Sun, Aug 23, 2015

The standard approach proposed by Walter et al. [1] for importance sampling of GGX BRDF is to use the PDF proportional to distribution of microfacet normal D(ω)D(\omega). However, D(ω)D(\omega) is not view-dependent, thus it would waste lots of samples when the incoming direction is near grazing angles. In addition, the small value of D(ω)mnD(\omega)\vert m\cdot n\vert at grazing angle would make the sample value as high as hundreds to millions in some situations and cause fireflies in render results.

In order to tackle these problems, Heitz and d’Eon [3] proposed a new method by sampling from the distribution of visible normals. Due to the consideration of view direction, their approach can significantly reduce the amount of wasted samples and make the sample weight in proper range to avoid the fireflies.

Revisit the Distribution of Normals D(ω)D(\omega)

Microsurface configuration. Image from Heitz [2]

Suppose the area of macro surface is 1m21m^2 and its normal is ωg\omega_g. The normal of each microfacet point pmp_m on the micro-surface M\mathcal{M} is ωm(pm)\omega_m(p_m) and the distribution of normals is:

D(ω)=Mδω(ωm(pm))dpmD(\omega) = \int_\mathcal{M}{\delta_\omega (\omega_m(p_m)) dp_m}

The unit stated in Heitz [2] is m2sr\frac{m^2}{sr} instead of 1sr\frac{1}{sr}, it’s different from the one stated in Walter et al. [1]

D(ω)D(\omega) describes the area of points MM\mathcal{M}^{\prime} \subset \mathcal{M} whose normals lie in the given solid angle ω\omega. Additionaly, it relates the integral from microsurface space to the space the normals which is the unit sphere ω\omega:

microsurface area=Mdpm=ΩD(ωm)dωmmicrosurface\ area = \int_\mathcal{M}{dp_m} = \int_\Omega{D(\omega_m)d\omega_m}

and the projected area along the geometry normal ωg\omega_g is:

Ω(ωmωg)D(ωm)dωm=M(ωm(pm)ωg)dpm=1\int_\Omega{(\omega_m\cdot\omega_g) D(\omega_m )d\omega_m} = \int_\mathcal{M}{(\omega_m (p_m)\cdot\omega_g )dp_m}=1

The Distribution of Visible Normals Dωo(ω)D_{\omega_o}(\omega)

Distribution of visible normals. Image from Heitz [2]

When we consider the projected area along the outgoing direction ωo\omega_o, we have to add a masking function G1(ωo,ωm)\color{#009933}{G_1(\omega_o, \omega_m)} to exclude the occlusion part (i.e. the black parts in the figure above):

ωG1(ωo,ωm)ωo,ωmD(ωm)dωm=cosθo\int_\omega{\textcolor{#009933}{G_1(\omega_o, \omega_m)}\langle\omega_o, \omega_m\rangle D(\omega_m)d\omega_m}=\textcolor{#0099FF}{\cos{\theta_o}}

With these information, the outgoing radiance from the microsurface can be formulated as:

L(ωo,M)=Mprojected area(pm)L(ωo,pm)dpmMprojected area(pm)dpm=1cosθoΩG1(ωo,ωm)ωo,ωmD(ωm)L(ωo,ωm)dωm=ΩDωo(ωm)L(ωo,ωm)dωm\begin{aligned} L(\omega_o,\mathcal{M}) &= \frac{\int_\mathcal{M}{projected\ area(p_m)L(\omega_o,p_m)dp_m}}{\textcolor{#0099FF}{\int_\mathcal{M}{projected\ area(p_m)dp_m}}} \\ &= \frac{1}{\textcolor{#0099FF}{\cos{\theta_o}}} \int_\Omega{G_1(\omega_o,\omega_m)\langle\omega_o,\omega_m\rangle D(\omega_m)L(\omega_o, \omega_m)d\omega_m} \\ &= \int_\Omega{\textcolor{#FF3399}{D_{\omega_o}(\omega_m)}L(\omega_o, \omega_m)d\omega_m} \end{aligned}

where the distribution of visible normals is Dωo(ωm)=1cosθoG1(ωo,ωm)ωo,ωmD(ωm)\textcolor{#FF3399}{D_{\omega_o}(\omega_m)} = \frac{1}{\cos{\theta_o}}G_1(\omega_o,\omega_m)\langle\omega_o, \omega_m\rangle D(\omega_m).

Importance Sampling of Dωo(ω)D_{\omega_o}(\omega)

For the anisotropic case, the D(ωm)D(\omega_m) should be replaced with D(ωm,αx,αy)D(\omega_m,\alpha_x,\alpha_y) and the distribution of visible normals becomes:

Dωo(ωm,αx,αy)=1cosθoG1(ωo,ωm)ωo,ωmD(ωm,αx,αy)D_{\omega_o}(\omega_m,\alpha_x,\alpha_y) = \frac{1}{\cos{\theta_o}} G_1(\omega_o,\omega_m)\langle \omega_o, \omega_m \rangle D(\omega_m,\alpha_x,\alpha_y)

Since it’s not easy to perform importance sampling with Dωo(ωm,αx,αy)D_{\omega_o}(\omega_m,\alpha_x,\alpha_y) directly, Heitz and d’Eon [3] proposed a novel technique based on Heitz’s discovery [2] of stretch invariance property in slope space to accomplish the task.

Normal Vector in Slope Space

Suppose the microsurface is a heightfield, given a normal ωm(xm,ym,zm)\omega_m(x_m, y_m,z_m), its coordinate in slope space can be defined as:

m~(ωm)=(xm~,ym~)=(xmzm,ymzm)\tilde{m}(\omega_m) = (x_{\tilde{m}}, y_{\tilde{m}}) = \left(-\frac{x_m}{z_m}, -\frac{y_m}{z_m}\right)

and the distribution of slopes P22(m~)P^{22}(\tilde{m}) is necessarily normalized (all the possibilities must sum to 1):

P22(m~)dxm~dym~=1\int_{-\infty}^{\infty} \int_{-\infty}^{\infty} P^{22}(\tilde{m}) \,dx_{\tilde{m}}\,dy_{\tilde{m}} = 1

Recall that ω(ωmωg)D(ωm)dωm=1\int_\omega{(\omega_m\cdot\omega_g)D(\omega_m)d\omega_m} = 1, we get the following relationship:

(ωmωg)D(ωm)dωm=P22(m~)dm~(ωmωg)D(ωm)=m~ωmP22(m~)\begin{aligned} (\omega_m⋅\omega_g)D(\omega_m)d\omega_m &=P^{22}(\tilde{m})d\tilde{m} \\ (\omega_m⋅\omega_g)D(\omega_m) &= \left\|\frac{\partial \tilde{m}}{\partial \omega_m}\right\| P^{22}(\tilde{m}) \\ \end{aligned}

Likewise, the relationship involved with masking is (cf. Heitz [2] p.82):

Dωi(ωm)=m~ωmPωi22(m~)D_{\omega_i}(\omega_m)=\left\|\frac{\partial \tilde{m}}{\partial \omega_m}\right\| P_{\omega_i}^{22}(\tilde{m})

where Pωi22(m~)P_{\omega_i}^{22}(\tilde{m}) is the distribution of visible slopes, and it shows that if we sample the slopes from Pωi22(m~)P_{\omega_i}^{22}(\tilde{m}) and transform them to normal ωm\omega_m, the resulting PDF is Dωi(ωm)D_{\omega_i}(\omega_m).

Stretch Invariance

Suppose the distribution of slopes P22P^{22} depends on the roughness αx,αy\alpha_x,\alpha_y, Heitz calls P22P^{22} is stretch invariant if changing its roughness would only stretch the distribution but keep its shape identical:

Illustration of stretch invariance. Image from Heitz [2]

In 1D case, stretch x-axis by a factor of 2 would compress the distribution by 2 and also notice that the height of distribution has been scaled by 2. Suppose the distribution is D(x,α)D(x, \alpha), the stretch invariance can be described as D(x,α)=1λD(xλ,αλ)D(x, \alpha) = \frac{1}{\lambda}D(\frac{x}{\lambda},\frac{\alpha}{\lambda}).

Extend this relationship to 2D, we get:

P22(xm~,ym~,αx,αy)=1λxλyP22(xm~λx,ym~λy,αxλx,αyλy)P^{22}(x_{\tilde{m}},y_{\tilde{m}},\alpha_x,\alpha_y)=\frac{1}{\lambda_x \lambda_y} P^{22}\left(\frac{x_{\tilde{m}}}{\lambda_x},\frac{y_{\tilde{m}}}{\lambda_y},\frac{\alpha_x}{\lambda_x},\frac{\alpha_y}{\lambda_y}\right)

In Heitz and d’Eon [3], they showed that the distribution of visible slopes also has the following relationship:

Pωi22(xm~,ym~,αx,αy)=1λxλyPSλxλy(ωi)22(xm~λx,ym~λy,αxλx,αyλy)P_{\omega_i}^{22}(x_{\tilde{m}},y_{\tilde{m}},\alpha_x,\alpha_y)=\frac{1}{\lambda_x \lambda_y} P_{S^{\lambda_x \lambda_y} (\omega_i)}^{22}\left(\frac{x_{\tilde{m}}}{\lambda_x},\frac{y_{\tilde{m}}}{\lambda_y},\frac{\alpha_x}{\lambda_x},\frac{\alpha_y}{\lambda_y}\right)

With stretch invariance property, any anisotropic distribution can be stretched into an isotropic one whose masking probability GG is the same. Then the samples can be generated with the help of the stretched isotropic distribution in following steps:

  1. Apply stretch invariant property to make Pωi22P_{\omega_i}^{22} isotropic
  2. Sample the slope coordinate xm~x_{\tilde{m}} according to the marginal PDF Pωi2(xm~,1,1)P_{\omega_i}^{2-}(x_{\tilde{m}},\textcolor{#FF3399}{1,1})
  3. Sample ym~y_{\tilde{m}} with given xm~x_{\tilde{m}} and conditional PDF Pωi22(ym~xm~,1,1)P_{\omega_i}^{2|2}(y_{\tilde{m}}|x_{\tilde{m}},\textcolor{#FF3399}{1,1})
  4. Rotate along the z axis by ϕ\phi in canonical frame
  5. Inversely stretch the slope coordinate (xm,ym)(x_m, y_m)
  6. Compute normal from slope coordinate ωm=(xm,ym,1)xm2+ym2+1\omega_m = \frac{(-x_m, -y_m, 1)}{\sqrt{x_m^2 + y_m^2 + 1}}

The implementation details can be found in the supplemental document of the Heitz and d’Eon [3].

Experimental Results

Sampling Comparison

Comparison

Comparison

When cosθo=1.5(θo85.94)\cos{\theta_o}=1.5 (\theta_o\approx 85.94^\circ), the new method saves 310 wasted samples! The remaining 61 back-facing samples are about 13°1\sim3\degree below the macrosurface. However, the mysterious situation happens at cosθo=π/4\cos{\theta_o}=\pi/4. In current implementation, there still are 52 invalid samples whose maximum θi\theta_i is about 3π/43\pi/4!! From the debugging traces, I found all those invalid samples come with a random number rx that is near to 0 or 1. To my best guess, this weird result may be caused by numerical errors and needs further investigation.

As usual, the implementation can be found on my github.

References

  1. Walter, Bruce, et al. “Microfacet models for refraction through rough surfaces.” EGSR'07.
  2. Heitz, Eric. “Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs.” JCGT'14. [slides]
  3. Heitz, Eric, and Eugene d’Eon. “Importance Sampling Microfacet‐Based BSDFs using the Distribution of Visible Normals.” EGSR'14. [source code][slides]