The Blinn-​Phong Normalization Zoo

It is good to see how phys­i­cally based shad­ing is finally gain­ing momen­tum in real time graph­ics and games. This is some­thing I have been advo­cat­ing for a long time. Devel­op­ers are spread­ing the word. I was espe­cially sur­prised to learn about Call of Duty: Black Ops join­ing the club [1]. Even a slick 60Hz-​shooter with no cycles to spare can afford to do PBS today!

This leads me to the topic of this post, the nor­mal­iza­tion of the Blinn-​Phong spec­u­lar high­light. Why am I writ­ing about it? It came to my mind recently with the cur­rent batch of pub­li­ca­tions from peo­ple adopt­ing phys­i­cally based shad­ing mod­els. This got me check­ing the maths again and I com­piled a list with nor­mal­iza­tion fac­tors for dif­fer­ent shad­ing mod­els, given here in this post. I would also like to elab­o­rate a lit­tle on the model that I wrote about in ShaderX7 [2]. Be aware this post is a large brain dump.

Blinn-​Phong Nor­mal­iza­tion: A par­a­digm shift for texturing

Let me first devote some lines to empha­size how this nor­mal­iza­tion busi­ness is not only a mat­ter for engine devel­op­ers or shader authors, but also for tex­ture artist edu­ca­tion.
Nor­mal­iza­tion means, in sim­ple terms, that the shad­ing model scales the inten­sity of the spec­u­lar high­light in pro­por­tion to its angu­lar size, such that the total reflected energy remains con­stant with vary­ing sur­face smooth­ness, aka. glossi­ness. This may sound like a minor tech­ni­cal detail, but it really is a par­a­digm shift.

stan­dard blinn-​phong nor­mal­ized blinn-​phong
Spec­u­lar map has all the details Gloss map has all the details
Glossi­ness constant Spec­u­lar level con­stant (almost)

With stan­dard Blinn-​Phong shad­ing, artists were used to paint sur­face vari­a­tion into a tex­ture con­nected to specular/​reflective inten­sity, while the glossi­ness was only an after­thought, often not tex­tured at all. With a nor­mal­ized shad­ing model, all the detail goes into the glossi­ness tex­ture, while it is the spec­u­lar inten­sity that becomes bor­ing. So, is every­thing dif­fer­ent now? In short, yes. And to drive the point home, I’ll give a visual example.

Wet and dry parts on an asphalt sur­face, in backlight

Con­sider the scene in the image above. The scene shows an an asphalt sur­face in back­light with dra­mat­i­cally dif­fer­ent reflectances for wet and dry parts. Isn’t this para­dox? The refrac­tive index of water is actu­ally lower than that of the asphalt min­er­als, so every­thing else being equal, the water-​covered sur­face should have less reflec­tion. But things are not equal, because the water-​covered parts have a much smoother sur­face. A smoother sur­face focuses the reflected sun­light into a nar­rower range of out­go­ing direc­tions, mak­ing it more intense at the same time. This is the rea­son for the glar­ing parts of the photo.

With this said, I dab­bled a lit­tle bit with GIMP to try and fac­tor the above image into dif­fuse, spec­u­lar and glossi­ness tex­tures, much in the same way as I had advised artists to do when I was tech­ni­cal direc­tor at Replay Stu­dios. The result is shown below.

Fac­tored into dif­fuse, spec­u­lar and glossi­ness textures

The dif­fuse tex­ture is a straight­for­ward ide­al­iza­tion of the sub­sur­face color, devoid of any light­ing and reflec­tions. Since this can­not be observed directly, it must be inferred, but it should be much more sat­u­rated than the real-​world appear­ance. I may be use­ful to have pho­tos taken with a polar­iz­ing fil­ter as a reference.

The spec­u­lar tex­ture defines the reflec­tiv­ity for the case when light, viewer and nor­mal are aligned. This is the min­i­mum value, and the shad­ing model will increase the reflec­tiv­ity for any other con­fig­u­ra­tion. There is not much artis­tic free­dom here, since this value is con­nected to refrac­tive index of the mate­r­ial. It is usu­ally in the range of 2% to 5% for every­thing which is not a metal or a crys­tal. In the exam­ple above, there is almost no point in tex­tur­ing it.

Instead, all the sur­face vari­a­tion went into the glossi­ness map. This map is taken to be a log­a­rith­mic encod­ing of the Blinn-​Phong spec­u­lar expo­nent, which is a mea­sure of sur­face smooth­ness. Black rep­re­sents a single-​digit expo­nent, indi­cat­ing a very rough sur­face. White rep­re­sents an expo­nent in the thou­sands, indi­cat­ing a very smooth sur­face. Since the shad­ing model is nor­mal­ized, both the size and the inten­sity of the spec­u­lar high­light is con­trolled with this value alone.

Tex­ture Phys­i­cal interpretation
Dif­fuse Color due to aver­age sub­sur­face absorption
Spec­u­lar Fres­nel reflectance at nor­mal incidence
Gloss Blinn-​Phong expo­nent, a mea­sure of sur­face smoothness

There is more to physically-​based shad­ing then just a nor­mal­ized Blinn-​Phong spec­u­lar term. To get a dra­matic and con­vinc­ing contre-​jour effect, it is impor­tant to model the behav­ior at graz­ing angles. This was one of the visual goals for the Vel­vet Assas­sin engine. See it real­ized, for exam­ple, in these scenes, and also pay atten­tion to the wet pud­dles on the floor, which are mostly an effect of vary­ing glossi­ness. Another play with vary­ing glossi­ness can be seen the wet streaks on the fuel tank here. (I’m not affil­i­ated with the com­menter, btw, I just found these videos to be of accept­able qual­ity.) As it turned out dur­ing the devel­op­ment, the Fres­nel fac­tor alone does not have enough ‘omph’. It needed the com­bi­na­tion of a Fres­nel fac­tor and the micro-​facet geo­met­ric vis­i­bil­ity fac­tor to get the right effect at graz­ing angles. More on this below.

In the ear­lier engine for Spell­Force 2, there was only one mate­r­ial with a per-​pixel vary­ing glossi­ness like that, the ice/​crystal mate­r­ial. It is pos­si­ble to get a hint of how it looked like here. Since this game was based on shader model 2, I needed to sac­ri­fice shadow map taps to get the Blinn-​Phong nor­mal­iza­tion in (with­out Fres­nel). For all other mate­ri­als, the glossi­ness was fixed and the nor­mal­iza­tion fac­tor was a pre­com­puted con­stant. What the engine did have was dif­fuse and spec­u­lar hemi­sphere light­ing. This allowed the artists to leave the dif­fuse tex­ture black for parts of shiny metal, which is another impor­tant aspect of PBS. The soldier’s armor in this scene is a good exam­ple of reflect­ing sky-​and ground col­ors. After some time, even these rel­a­tively crude, “phys­i­cally inspired” shad­ing mod­els proved to be really pop­u­lar with the team.

Nor­mal­iza­tion vs Energy Conservation

When I speak about nor­mal­iza­tion I under­stand a dif­fer­ent thing than energy con­ser­va­tion. In energy con­ser­va­tion, one looks at the total hemi­spher­i­cal reflectance for a given BRDF, and guar­an­tees that it is strictly bounded by unity for all incom­ing light direc­tions. Nor­mal­iza­tion, on the other hand, is just as strong as we define it. We can demand, for instance, that some para­me­ter (the spec­u­lar expo­nent in this case) has no effect the total hemi­spher­i­cal reflectance for a sin­gle, con­ve­niently cho­sen incom­ing light direc­tion. Then we have nor­mal­ized it. In math­e­mat­i­cal terms,

\[\text{for a given $\omega_i$,} \quad \int \limits _{\Omega} f_r(\omega_i, \omega_o) \cos \theta_o \,d \omega_o = \text{const} .\]

It is pos­si­ble (and may be even use­ful) to nor­mal­ize BRDFs that are not energy con­serv­ing [8], like the orig­i­nal Phong and Blinn-​Phong (the ones with­out the addi­tional cosine term). It is also entirely pos­si­ble to nor­mal­ize some­thing else than hemi­spher­i­cal reflectance, for instance we can nor­mal­ize the micro-​facet dis­tri­b­u­tion function.

The Nor­mal­iza­tion Zoo

I ver­i­fied the fol­low­ing list of nor­mal­iza­tion fac­tors with the help of MuPAD, which is a great sym­bolic alge­bra tool. Unfor­tu­nately this is no longer avail­able as a sep­a­rate prod­uct, which is a real pity. I rate it sec­ond maybe only to Mathematica.

Model RDF/​Integrand Nor­mal­iza­tion Lit­er­a­ture
Phong (\mathbf{R} \cdot \mathbf{L})^n
\cos^n \theta \sin \theta
\frac{n+1}{2 \pi}
(\mathbf{R} \cdot \mathbf{L})^n(\mathbf{N} \cdot \mathbf{L})
\cos^n \theta \cos \theta \sin \theta
\frac{n+2}{2 \pi} [3,5,8]
Blinn-​Phong (\mathbf{N} \cdot \mathbf{H})^n
\cos^n \frac{\theta}{2} \sin \theta
\frac{n+2}{8 \pi} < \frac{n+2}{4 \pi \big( 2-\exp_2(-n/2) \big)} < \frac{n+4}{8 \pi} [6]
(\mathbf{N} \cdot \mathbf{H})^n(\mathbf{N} \cdot \mathbf{L})
\cos^n \frac{\theta}{2} \cos \theta \sin \theta
\frac{n+6}{8 \pi} < \frac{(n+2)(n+4)}{8 \pi \big( \exp_2(-n/2)+n \big)} < \frac{n+8}{8 \pi} [3,9]
Model NDF/​Integrand Nor­mal­iza­tion Lit­er­a­ture
(\mathbf{N} \cdot \mathbf{H})^n
\cos^n \alpha \sin \alpha
\frac{n+1}{2 \pi} [2,4,5]
(\mathbf{N} \cdot \mathbf{H})^n
\cos^n \alpha \cos \alpha \sin \alpha
\frac{n+2}{2 \pi} [10,11]

The upper part of the table shows the nor­mal­ized reflec­tion den­sity func­tion (RDF). This is the prob­a­bil­ity den­sity that a pho­ton from the incom­ing direc­tion is reflected to the out­go­ing direc­tion, and is the BRDF times \cos \theta. Here, \theta is the angle between \mathbf{N} and \mathbf{L}, which is, for the assumed view posi­tion, also the angle between \mathbf{V} and \mathbf{L}, resp. \mathbf{R} and \mathbf{L}. The lit­er­a­ture col­umn shows where I have seen these nor­mal­iza­tions men­tioned previously.

The lower part of the table shows the nor­mal­ized nor­mal dis­tri­b­u­tion func­tion (NDF) for a micro-​facet model. This is the prob­a­bil­ity den­sity that the nor­mal of a micro-​facet is ori­ented towards \mathbf{H}. It is the same expres­sion in spher­i­cal coor­di­nates than that for of the Phong RDF, just over a dif­fer­ent vari­able, \alpha, the angle between \mathbf{N} and \mathbf{H}. The height­field dis­tri­b­u­tion does it slightly dif­fer­ent, it nor­mal­izes the pro­jected area of the micro-​facets to the area of the ground plane (adding yet another cosine term).

Two Pi Or Not Two Pi

This is a good oppor­tu­nity to elab­o­rate on this \pi-busi­ness, because it can be con­fus­ing time and again. The RDFs and NDFs nec­es­sar­ily con­tain \pi, as the result of an inte­gra­tion over parts of a sphere. In the shader code how­ever, \pi does usu­ally not appear, because it can­cels out when mul­ti­ply­ing with irra­di­ance, which is itself an inte­gra­tion over parts of a sphere.

Con­sider a point light source mod­eled as a small and very far away sphere, at dis­tance r. Let this sphere have radius r_0 and a homo­ge­neous emis­sive sur­face of radi­ance L. From the point of view of the receiv­ing sur­face, the solid angle sub­tended by this sphere is a spher­i­cal cap, and so the irra­di­ance inte­grates to E=\pi L (\frac{r_0}{r})^2. So there you have \pi in the for­mula for the irra­di­ance of a point light, neatly can­cel­ing with the \pi from the RDF/​NDF. This exer­cise can be done with all other types of illu­mi­na­tion, it should always remove the fac­tor \pi. (See the com­ment sec­tion for an in-​depth explanation.)

Min­i­mal­ist Cook-​Torrance (ShaderX7 style)

I wrote ear­lier in this post how it was impor­tant to cap­ture the effects at graz­ing angles. The orig­i­nal Cook-​Torrance model [7] has expen­sive fac­tors for the dis­tri­b­u­tion of nor­mals (\mathrm{D}), the Fres­nel reflectance (\mathrm{F}) and geo­met­ric occlu­sion of micro-​facets (\mathrm{G}). The nor­mal­ized Blinn-​Phong dis­tri­b­u­tion can be used to greatly sim­plify \mathrm{D}. A clever sim­pli­fi­ca­tion for \mathrm{G} was given by Kele­men and Szirmay-​Kalos [4], by com­bin­ing \mathrm{G} with the fore­short­en­ing terms in the denom­i­na­tor; it should then be called the geo­met­ric vis­i­bil­ity fac­tor (\mathrm{V}). The Schlick approx­i­ma­tion is good to sim­plify \mathrm{F}, but still with all the lerp’ing and one-minus’ing that is going on, it gen­er­ates many shader instructions.

For Vel­vet Assas­sin, I devised a fur­ther approx­i­ma­tion by com­bin­ing the effect of \mathrm{F} and \mathrm{V} in a sin­gle expres­sion with a sig­nif­i­cantly reduced instruc­tion count, which I would call ‘min­i­mal­ist Cook-​Torrance’. I looked at graphs and found, that in order to cap­ture the essence, it suf­fices to divide by a higher power of \mathbf{L} \cdot \mathbf{H}, and get rid of \mathrm{F} alto­gether. This is where the odd power of 3 comes from. In BRDF form, this is

\[f_r = \frac{k_d}{\pi} + k_s \frac{(n+1) (\mathbf{N} \cdot \mathbf{H})^n}{8 \pi (\mathbf{L} \cdot \mathbf{H})^3},\]

where k_d is the dif­fuse reflectance, k_s is the spec­u­lar reflectance, and n is the spec­u­lar expo­nent. This is the for­mula that was pub­lished in the ShaderX7 arti­cle [2] and the one that shipped with Vel­vet Assas­sin (see here for the code). The for­mula can be decom­posed into a con­tri­bu­tion from \mathrm{D} (the nor­mal­ized Blinn-​Phong NDF, see table above) and a con­tri­bu­tion from a com­bined \mathrm{F} and \mathrm{V}:

\begin{align*} f_r &= \frac{k_d}{\pi} + k_s \mathrm{DFV} , & \mathrm{D} &= \frac{(n+1)}{2\pi} (\mathbf{N} \cdot \mathbf{H})^n , \\ & & \mathrm{FV} &= \frac{1}{4} (\mathbf{L} \cdot \mathbf{H})^{-3} . \end{align*}

It is pos­si­bly the crud­est approx­i­ma­tion to Cook-​Torrance there is, but an effec­tive one no less. There will be no Fres­nel color shift and no explicit inter­po­la­tion to white (sat­u­ra­tion is sup­posed to take care of that), so the model is lin­ear in k_s, which is a com­pu­ta­tional advan­tage of its own. The model will under­es­ti­mate the reflectance at graz­ing angles for low-​index mate­ri­als like water, and over­es­ti­mate the reflectance for high-​index mate­ri­als like met­als. For the typ­i­cal range of di-​electrics how­ever, the esti­ma­tion is just right.

The graphs above show the min­i­mal­ist model with the (\mathbf{L} \cdot \mathbf{H})^3 denom­i­na­tor (red graph) against the com­bined effect of Schlick and the (\mathbf{L} \cdot \mathbf{H})^2 denom­i­na­tor of Kele­men and Szirmay-​Kalos (blue graph), for spec­u­lar reflectances of 0.02 (top), 0.05 (mid­dle) and 0.8 (bot­tom), respec­tively. The graphs do not align per­fectly, but the ‘omph’ is there. So, what about the instruc­tion count?

Min­i­mal­ist F-​Schlick with Kelemen/​Szirmay-​Kalos
Mul­ti­ply denom­i­na­tor by \mathbf{L} \cdot \mathbf{H} for a third time. Done. Cal­cu­late 1 - \mathbf{L} \cdot \mathbf{H}
Raise that to the 4th or 5th power.
Cal­cu­late 1 - k_s.

If you already have (\mathbf{L} \cdot \mathbf{H})^2, the sim­pli­fied model just needs one addi­tional mul­ti­pli­ca­tion. The com­bi­na­tion of F-​Schlick and Kelemen/​Szirmay-​Kalos needs 5 or 6 more instruc­tions in a depen­dency chain from that point. It doesn’t help if a Fres­nel fac­tor from the envi­ron­ment map already exists, since that is based on \mathbf{N} \cdot \mathbf{V}. In terms of bang for the buck, if there are many lights in a loop (and I had a for­ward ren­derer with up to 8 lights per pass), then I’d rec­om­mend the min­i­mal­ist version.

[1] Dim­i­tar Lazarov, “Physically-​based light­ing in Call of Duty: Black Ops” SIGGRAPH 2011
[2] Chris­t­ian Schüler, “An Effi­cient and Phys­i­cally Plau­si­ble Real-​Time Shad­ing Model.” ShaderX 7, Chap­ter 2.5, pp. 175 – 187
[3] Fabian Giesen, “Phong Nor­mal­iza­tion Fac­tor deriva­tion”
[4] Kele­men and Szirmay-​Kalos, “A Micro­facet Based Cou­pled Specular-​Matte BRDF Model with Impor­tance Sam­pling”, Euro­graph­ics 2001
[5] Lafor­tune and Willems, “Using the mod­i­fied Phong reflectance model for phys­i­cally based ren­der­ing”, Tech­ni­cal Report
[6] Yoshi­haru Gotanda, “Prac­ti­cal Imple­men­ta­tion of Physically-​Based Shad­ing Mod­els at tri-​Ace”, SIGGRAPH 2010
[7] Robert Cook and Ken­neth Tor­rance, “A reflectance model for com­puter graph­ics”
[8] Robert Lewis, “Mak­ing Shaders More Phys­i­cally Plau­si­ble”, Com­puter Graph­ics Forum, vol. 13, no. 2 (June, 1994)
[9] Akienne-​Möller, Haines and Hoff­mann, “Real-​Time Ren­der­ing” book
[10] Pharr, Humphreys, “Physically-​Based Ren­der­ing” book
[11] Nathaniel Hoff­mann, “Craft­ing Phys­i­cally Moti­vated Shad­ing Mod­els for Game Devel­op­ment”, SIGGRAPH 2010

32 thoughts on “The Blinn-​Phong Normalization Zoo

  1. Can you help me under­stand the deriva­tion of irra­di­ance under the sec­tion “Two Pi Or Not Two Pi”? It seems like if we decrease r_0 towards 0, then the equa­tion for irra­di­ance E also goes to 0, and the fac­tor of \pi becomes sort of point­less. The irra­di­ance equa­tion would make sense to me if \frac{r_0}{r} does not approach 0, and pi’s can­cel out, but we still need to mul­ti­ply the reflectance with (\frac{r_0}{r})^2 when eval­u­at­ing the ren­der­ing equation.

    My under­stand­ing when eval­u­at­ing irra­di­ance from a sin­gle point light is that it’s 0 every­where else and 1 for the dw com­ing from the point light so the irra­di­ance inte­gral can be done by directly eval­u­at­ing the incom­ing radi­ance times the cosine fac­tor. There would be no pi’s to can­cel and we would still need to divide by pi for a sin­gle out­go­ing dw.

    Please cor­rect me if I missed some­thing, I want to under­stand this as it has always con­fused me. Thanks.

    • Hallo Gaame,
      no prob­lem. Think of the light source as being a dis­tant star. It has some radius r_0 and some sur­face tem­per­a­ture, giv­ing the sur­face a spe­cific radi­ance L. If you reduce the radius, and there­fore the sur­face area, the radi­ance of the sur­face must increase (the star must get hot­ter) for that the light source keeps its inten­sity! In the limit of a point light, you would have zero r_0 and infi­nite L, but the prod­uct, the inten­sity, and there­fore the irra­di­ance received, stays finite. It is true that in the end, a point light is eval­u­ated as a direc­tional delta func­tion, but you must not for­get \pi, as it will stay there when you do the limit.

  2. It makes a lot more sense now, but I am still slightly con­fused about the pi. Let me see if I under­stood this cor­rectly. Assum­ing the light source is a small dis­tant sphere as stated orig­i­nally and inside the upper hemi­spher­i­cal range of the receiver, the light source is actu­ally emit­ting the radi­ant flux from its part of the hemi­sphere fac­ing the receiv­ing point. So when cal­cu­lat­ing the radi­ant flux com­ing from the light source seen by the receiver, the pi comes from inte­grat­ing the light source’s hemi­sphere? Or is the pi actu­ally com­ing from inte­grat­ing the receiver’s hemisphere?

    Thanks again for replying.

    • Nei­ther of both, the exam­ple was derived from the solid angle of the light source as seen in the hemi­sphere of the irra­di­ant plane. It starts with the integral

      \[E = \int \limits _{ \phi = 0 }^{ 2 \pi } \int \limits _{ \theta = 0 } ^{ \beta } L \cos \theta \sin \theta \, d\theta \, d\phi,\]

      which is inte­grat­ing L over the cap of a sphere with half-​angle \beta, times the cosine fac­tor. For this prob­lem, the plane for the irra­di­ant flux is con­ve­niently set to be nor­mal to the light direc­tion, so the spher­i­cal cap is cen­tered around \theta = 0. (The \mathbf{N} \cdot \mathbf{L} later con­verts this to the irra­di­ance received by the sur­face itself). The solu­tion of the inte­gral is

      \[E = \pi L \sin^{2} \beta.\]

      By trigonom­e­try, \sin \beta = \frac{r_0} {r}, which arrives at the for­mula stated in the article,

      \[E = \pi L \left ( \frac{r_0}{r} \right )^2.\]

      I’m now turn­ing this reply more into a foot­note for the arti­cle. Let’s go all the way and reduce the expres­sion to the one that will appear in the shader. The radi­ance L' of the shaded sur­face (aka. pixel color) is the BRDF times \mathbf{N} \cdot \mathbf{L} times irra­di­ance E. Assum­ing, with­out loss of gen­er­al­ity, a con­stant Lam­bert­ian BRDF, f_r = \frac{k_d}{\pi}, we have

      \[L' &= \frac{k_d}{\pi} \, ( \mathbf{N} \cdot \mathbf{L} ) \, E\]

      for the pixel color. The \pi from the BRDF can­cels with the \pi from the irra­di­ance,
      so the radiance-​to-​radiance rela­tion­ship does not involve \pi:

      \[L' &= \frac{k_d}{\pi} \, ( \mathbf{N} \cdot \mathbf{L} ) \, L \left ( \frac{r_0}{r} \right )^2.\]

      When the light source is now shrunk to an ide­al­ized point, we can define a con­stant, call it I', that is the prod­uct of L and r_0, and we can recre­ate the usual for­mula for a dif­fuse light

      \[L' &= k_d \, ( \mathbf{N} \cdot \mathbf{L} ) \, \frac {I'}{r^2} .\]

      This con­stant, I' is again related to the actual radi­ant inten­sity I of the light source by a fac­tor of \pi.

  3. This makes per­fect sense now! Cal­cu­lat­ing irra­di­ance in the plane nor­mal to the light source makes a lot of sense, it is the piece that I was miss­ing. I want to make sure I got one last small detail cor­rectly: \sin \beta \simeq \beta \simeq \frac{r_0}{r} for large r?

    Thanks for your patience. Much appreciated.

    • There is not even a need for an approx­i­ma­tion, \sin \beta = \frac{r_0}{r} is always true. Just draw a right tri­an­gle ABC with A the light source cen­ter, B the observer and C a point tan­gent on the light source sur­face (it’s a sphere), with angle \beta in B!

      PS, I hope you don’t mind I pret­tied up your com­ment a lit­tle bit. LaTeX code for inline math via $…$ is enabled blog-​wide.

  4. I am feel­ing embar­rassed to even ask this, but isn’t \frac{r_0}{r} = \tan \beta and \frac{r_0}{r} = \sin \beta only for large r? Thanks!

    P.S. Feel free to pret­tify my comments.

  5. Pingback: Readings on physically based rendering | Light is beautiful

  6. I recently started toy­ing with PBS, and right away got annoyed by arti­facts in tran­si­tions between mate­ri­als. Here’s an exam­ple from your game:

    I cir­cled one of the instances of the arti­fact I’m talk­ing about: bright spec­u­lar fringes in tran­si­tions between rough and smooth mate­ri­als. It’s unavoid­able due to tex­ture fil­ter­ing, anti-​aliasing in tex­ture author­ing, etc. The issue is that you end up with an unre­al­is­tic “semi-​rough” value in the tran­si­tion region, which picks up a broader and brighter spec­u­lar high­light than the smooth and rough neigh­bor­ing sur­faces, respec­tively. (BTW, I tried both “real” Cook-​Torrance and your “min­i­mal­ist” approx­i­ma­tion and got sim­i­lar artifacts).

    There’s a sim­i­lar issue tran­si­tion­ing between metal and dielec­tric (ex: rust on metal), where you get dark fring­ing if you try to reduce the dif­fuse con­tri­bu­tion on the metal all the way to 0. Again, this is an unre­al­is­tic sit­u­a­tion, because in real life you don’t have a “semi-​metal” in between the metal and the rust.

    The root issue is that fil­ter­ing intro­duces unre­al­is­tic in-​between BRDF attributes.

    The more cor­rect solu­tion to both of these issues would be to eval­u­ate the BRDFs for the two mate­ri­als sep­a­rately, and blend the results, but that is pro­hib­i­tive in terms of resources and likely very incon­ve­nient for artists (man­age sep­a­rate tex­ture sets and blend maps). The art work­flow could maybe be worked around with exten­sive spe­cial­ized paint tools, and the extra resource require­ment might be accept­able on dx11 hard­ware, but nei­ther sounds appealing.

    So I’ll throw the ques­tion out there for peo­ple who have had pro­duc­tion expe­ri­ence with PBS. How did you get around tex­ture fil­ter­ing related artifacts?

    • Hallo Steve
      what you men­tion is indeed an issue, and I too do not have a solu­tion for it. For our game we just accepted it as is and the artists try to work around the issue. Other peo­ple have this issue too. In the sildes from Call Of Duty, you can see on the wet vs dry parts on the roads the exact same issue. As it cur­rently stands, the neg­a­tives are out­weighed by the fact that a large vari­ety of mate­ri­als is batch­able into a sin­gle texture.

  7. I see. Were you able to achieve a decent look for some­thing as sim­ple as rust on metal?

    • I think yes, at least I can’t remem­ber the artists com­plain. Any arti­facts that appearead at the tran­si­tions of glossi­ness (for instance, very pro­nounced at the bor­ders of wet pud­dles) seem to be accepted as a fact of life.

  8. Pingback: Velvet Assassin is on Mac | The Tenth Planet

  9. One thing is con­fus­ing me here - you describe the RDF as the prob­a­bil­ity that a pho­ton from the given direc­tion will reflect towards the cam­era, but the nor­mal­i­sa­tion fac­tor for high gloss val­ues seems to go above 1. Is there another fac­tor that can­cels this out?

    • The RDF (and the NDF) itself is not a prob­a­bil­ity but a dis­tri­b­u­tion, aka prob­a­bil­ity den­sity. To get a prob­a­bil­ity you need to inte­grate over a region. The nor­mal­iza­tion takes care that this inte­gral is at most 1.

  10. Do you have some ref­er­ences, guide­lines or tuto­ri­als about how you fac­tored the image into dif­fuse, spec­u­lar and glossi­ness tex­tures? Are you using any cus­tom tools or plugins?

    • Hallo Jens,
      besides what I wrote in the arti­cle, there is no magic here. I also don’t know of any resource that would specif­i­cally teach about this topic. One idea is to always take pho­tos when the sky is over­cast, so there is as lit­tle light­ing as pos­si­ble in the pho­tos to begin with. Another thing is that if you have fac­tored one image (for instance, you think you have a good spec­u­lar map) then you can try to *lin­early* sub­tract that from the photo to get the dif­fuse map. Lin­early means here, that the sub­trac­tion is done in lin­ear light­ing space, not in RGB space. Hope this helps!

  11. Sorry for res­ur­rect­ing an old dis­cus­sion, but I am recently com­ing back to the math and real­ized that there is one thing I am still miss­ing dur­ing the irra­di­ance E substitution.

    Based on your derived equa­tions, plug­ging E into L':

    L' = \frac{k_{d}}{\pi}(N \cdot L) \pi L \left(\frac{r_{0}}{r}\right)^{2}

    can­celling out \pi, we have

    L' = k_{d}(N \cdot L) L \left(\frac{r_{0}}{r}\right)^{2}

    The final equa­tion is

    L' = k_{d}(N \cdot L) \frac{I}{r^{2}}

    which means

    I = L r_{0}^{2}

    but how is this final equa­tion derived? I can under­stand that
    E = \frac{I}{r^{2}}, and L = \frac{I}{A}, but isn’t
    L r_{0}^{2} = \frac{dI}{dw} (by sub­sti­tut­ing dw = \frac{dA}{r^{2}})?
    Please help.

    • Hi Gaame,
      wel­come back, that’s a long time; I had to reread my own posts to get up to the con­text. So that’s cor­rect, the radi­ant inten­sity appears as the prod­uct of L and r_0^2 in the limit of a point light. Remem­ber that when the light source is shrunk to a point, we need to make it infi­nitely bright. So r_0 goes to zero, and L goes to infin­ity, but their prod­uct approaches the finite value I. It would hap­pen in real life if a dis­tant star is smaller than the res­o­lu­tion of the cam­era. Then we can only mea­sure I but not L, since the solid angle of a cam­era pixel is known but not the actual sur­face area of the light source.

  12. Hi Chris­t­ian,

    Thanks for the reply. I have been bang­ing my head try­ing to understand/​prove that Lr_{0}^{2} = I with­out much suc­cess. I can agree that Lr_{0}^{2} is a finite value as r_{0} \to 0, but how does it become the radi­ant inten­sity? Can you help me fig­ure this out? Thanks!

    • Sim­ple, just do a dimen­sional analy­sis. The units of radi­ant inten­sity is Watts per stera­dian (\mathrm{W sr^{-1}}); while the units of radi­ance is Watts per meter squared and stera­dian (\mathrm{W m^{-2} sr^{-1}}). Mul­ti­ply­ing L with r^2 (or divid­ing I by r^2) will do the conversion.

  13. Pingback: Readings on Physically Based Rendering | Interplay of Light

  14. I edited some word­ings in the arti­cle and also added a para­graph that explains the decom­po­si­tion of the Min­i­mal­ist Cook Tor­rance for­mula into the D, F, V factors.

  15. Pingback: Highlights from GDC 2014 presentations | The Tenth Planet

  16. Pingback: Elite Dangerous: Impressions of Deep Space Rendering | The Tenth Planet

  17. Hi Chris­t­ian, thanks for the great post and blog. I found it very useful.

    I’ve a doubt with regards to the pi removal, I’d appre­ci­ate if you could help me with it.

    From this equation:

    \[L' &= \frac{k_d}{\pi} \, ( \mathbf{N} \cdot \mathbf{L} ) \, E\]

    If I just plug the point light irra­di­ance equa­tion, as found in var­i­ous other sources:
    E = I /​r^2

    Then the pi doesn’t can­cel out. Why is that hap­pen­ing, and why it didn’t hap­pened in you orig­i­nal derivation?

    Fol­low­ing other ref­er­ences:
    Page 18

    It is sug­gested that this pi dis­ap­pears as a con­ve­nient way to describe point light sources in such a way that the color of light matches the color of a sur­face lit by it, when the nor­mal and the light direc­tion matches.

    From what I can under­stand, the pi nat­u­rally dis­ap­pears for area lights, as you showed in your deriva­tion, but it looks to me that for point lights you actu­ally need add a “times pi” cor­rec­tion (for more intu­itive edi­tion of light values).

    If you can com­ment on this, it would be pretty much appreciated :)

    • Hi Iryoku,
      the rea­son is because the \pi is also in the for­mula for the irra­di­ance, I.
      That’s why I have shown the exam­ple of the ‘disk shrink­ing to a point’.
      I have also cor­rected a slightly mis­lead­ing word­ing, in my com­ment post from 2011-​09, so now it should be clear.

      The for­mula for E for a disk shaped light source was derived as

      \[E = \pi L \left ( \frac{r_0}{r} \right )^2.\]

      In this frame­work, I = \pi L r_0^2, so there is your \pi.

  18. Pingback: Energy Conservation |

Leave a Reply

Your email address will not be published.