The Blinn-Phong Normalization Zoo

It is good to see how phys­i­cal­ly based shad­ing is final­ly 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­cial­ly sur­prised to learn about Call of Duty: Black Ops join­ing the club [1]. Even a slick 60Hz-shoot­er with no cycles to spare can afford to do PBS today!

This leads me to the top­ic 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 recent­ly with the cur­rent batch of pub­li­ca­tions from peo­ple adopt­ing phys­i­cal­ly 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, giv­en here in this post. I would also like to elab­o­rate a lit­tle on the mod­el that I wrote about in ShaderX7 [2]. Be aware this post is a large brain dump.

Blinn-Phong Normalization: A paradigm 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 shad­er authors, but also for tex­ture artist edu­ca­tion.
Nor­mal­iza­tion means, in sim­ple terms, that the shad­ing mod­el scales the inten­si­ty of the spec­u­lar high­light in pro­por­tion to its angu­lar size, such that the total reflect­ed ener­gy 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 real­ly 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 con­stant Spec­u­lar lev­el 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­nect­ed to specular/reflective inten­si­ty, while the glossi­ness was only an after­thought, often not tex­tured at all. With a nor­mal­ized shad­ing mod­el, all the detail goes into the glossi­ness tex­ture, while it is the spec­u­lar inten­si­ty that becomes bor­ing. So, is every­thing dif­fer­ent now? In short, yes. And to dri­ve the point home, I’ll give a visu­al exam­ple.

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

Con­sid­er the scene in the image above. The scene shows an an asphalt sur­face in back­light with dra­mat­i­cal­ly dif­fer­ent reflectances for wet and dry parts. Isn’t this para­dox? The refrac­tive index of water is actu­al­ly low­er than that of the asphalt min­er­als, so every­thing else being equal, the water-cov­ered sur­face should have less reflec­tion. But things are not equal, because the water-cov­ered parts have a much smoother sur­face. A smoother sur­face focus­es the reflect­ed sun­light into a nar­row­er 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 pho­to.

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 tex­tures

The dif­fuse tex­ture is a straight­for­ward ide­al­iza­tion of the sub­sur­face col­or, devoid of any light­ing and reflec­tions. Since this can­not be observed direct­ly, it must be inferred, but it should be much more sat­u­rat­ed than the real-world appear­ance. I may be use­ful to have pho­tos tak­en with a polar­iz­ing fil­ter as a ref­er­ence.

The spec­u­lar tex­ture defines the reflec­tiv­i­ty for the case when light, view­er and nor­mal are aligned. This is the min­i­mum val­ue, and the shad­ing mod­el will increase the reflec­tiv­i­ty for any oth­er con­fig­u­ra­tion. There is not much artis­tic free­dom here, since this val­ue is con­nect­ed to refrac­tive index of the mate­r­i­al. It is usu­al­ly in the range of 2% to 5% for every­thing which is not a met­al 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 tak­en 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 sin­gle-dig­it 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 mod­el is nor­mal­ized, both the size and the inten­si­ty of the spec­u­lar high­light is con­trolled with this val­ue alone.

Tex­ture Phys­i­cal inter­pre­ta­tion
Dif­fuse Col­or due to aver­age sub­sur­face absorp­tion
Spec­u­lar Fres­nel reflectance at nor­mal inci­dence
Gloss Blinn-Phong expo­nent, a mea­sure of sur­face smooth­ness

There is more to phys­i­cal­ly-based shad­ing then just a nor­mal­ized Blinn-Phong spec­u­lar term. To get a dra­mat­ic and con­vinc­ing con­tre-jour effect, it is impor­tant to mod­el the behav­ior at graz­ing angles. This was one of the visu­al goals for the Vel­vet Assas­sin engine. See it real­ized, for exam­ple, in this cene, and also pay atten­tion to the wet pud­dles on the floor, which is an effect of vary­ing glossi­ness. Anoth­er play of vary­ing glossi­ness are the wet streaks on the fuel tank here, or the dusty vs non-dusty parts on the car’s wind­screen here. What’s more, it becomes pos­si­ble to paint both metal­lic and non-metal­lic parts onto the same tex­ture, which helps to min­i­mize batch count and num­ber of shad­er vari­ants. (EDIT 2018: The old youtube links were dead, so I replaced them with equiv­a­lent scenes from oth­er videos.) As it turned out dur­ing the devel­op­ment, the Fres­nel fac­tor alone does not have enough ‘omph’. It need­ed the com­bi­na­tion of a Fres­nel fac­tor and the micro-facet geo­met­ric vis­i­bil­i­ty fac­tor to get the right effect at graz­ing angles. More on this below.

In the ear­li­er engine for Spell­Force 2, there was only one mate­r­i­al with a per-pix­el vary­ing glossi­ness like that, the ice/crystal mate­r­i­al. It is pos­si­ble to get a hint of how it looked like here and here (note how not only the spec­u­lar high­light , but also the mipmap lev­el of the translu­cent back buffer is var­ied depend­ing on glossi­ness).  Since this game was based on shad­er mod­el 2, I need­ed to sac­ri­fice shad­ow map taps to get the Blinn-Phong nor­mal­iza­tion in (with­out Fres­nel). For all oth­er mate­ri­als, the glossi­ness was fixed and the nor­mal­iza­tion fac­tor was a pre­com­put­ed 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 met­al, which is anoth­er 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­tive­ly crude, “phys­i­cal­ly inspired” shad­ing mod­els proved to be real­ly pop­u­lar with the team.

Normalization vs Energy Conservation

When I speak about nor­mal­iza­tion I under­stand a dif­fer­ent thing than ener­gy con­ser­va­tion. In ener­gy con­ser­va­tion, one looks at the total hemi­spher­i­cal reflectance for a giv­en BRDF, and guar­an­tees that it is strict­ly bound­ed by uni­ty for all incom­ing light direc­tions. Nor­mal­iza­tion, on the oth­er 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­nient­ly 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 ,\mathrm{d} \omega_o = \text{const} .\]

It is pos­si­ble (and may be even use­ful) to nor­mal­ize BRDFs that are not ener­gy con­serv­ing [8], like the orig­i­nal Phong and Blinn-Phong (the ones with­out the addi­tion­al cosine term). It is also entire­ly 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 func­tion.

The Normalization 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­bol­ic alge­bra tool. Unfor­tu­nate­ly 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 Math­e­mat­i­ca.

Mod­el 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]
Mod­el 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­si­ty func­tion (RDF). This is the prob­a­bil­i­ty den­si­ty that a pho­ton from the incom­ing direc­tion is reflect­ed 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 pre­vi­ous­ly.

The low­er part of the table shows the nor­mal­ized nor­mal dis­tri­b­u­tion func­tion (NDF) for a micro-facet mod­el. This is the prob­a­bil­i­ty den­si­ty that the nor­mal of a micro-facet is ori­ent­ed 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 slight­ly dif­fer­ent, it nor­mal­izes the pro­ject­ed area of the micro-facets to the area of the ground plane (adding yet anoth­er cosine term).

Two Pi Or Not Two Pi

This is a good oppor­tu­ni­ty 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­i­ly con­tain \pi, as the result of an inte­gra­tion over parts of a sphere. In the shad­er code how­ev­er, pi does usu­al­ly 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­sid­er 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 sol­id angle sub­tend­ed 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­mu­la for the irra­di­ance of a point light, neat­ly can­cel­ing with the \pi from the RDF/NDF. This exer­cise can be done with all oth­er types of illu­mi­na­tion, it should always remove the fac­tor \pi. (See the com­ment sec­tion for an in-depth expla­na­tion.)

Minimalist Cook-Torrance (ShaderX7 style)

I wrote ear­li­er in this post how it was impor­tant to cap­ture the effects at graz­ing angles. The orig­i­nal Cook-Tor­rance mod­el [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 great­ly sim­pli­fy \mathrm{D}. A clever sim­pli­fi­ca­tion for \mathrm{G} was giv­en by Kele­men and Szir­may-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­i­ty fac­tor (\mathrm{V}). The Schlick approx­i­ma­tion is good to sim­pli­fy \mathrm{F}, but still with all the lerp’ing and one-minus’ing that is going on, it gen­er­ates many shad­er instruc­tions.

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­cant­ly reduced instruc­tion count, which I would call ‘min­i­mal­ist Cook-Tor­rance’. I looked at graphs and found, that in order to cap­ture the essence, it suf­fices to divide by a high­er pow­er of \mathbf{L} \cdot \mathbf{H}, and get rid of \mathrm{F} alto­geth­er. This is where the odd pow­er 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­mu­la 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­mu­la 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-Tor­rance there is, but an effec­tive one no less. There will be no Fres­nel col­or shift and no explic­it inter­po­la­tion to white (sat­u­ra­tion is sup­posed to take care of that), so the mod­el is lin­ear in k_s, which is a com­pu­ta­tion­al advan­tage of its own. The mod­el 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­ev­er, the esti­ma­tion is just right.

The graphs above show the min­i­mal­ist mod­el 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 Szir­may-Kalos (blue graph), for spec­u­lar reflectances of 0.02 (top), 0.05 (mid­dle) and 0.8 (bot­tom), respec­tive­ly. The graphs do not align per­fect­ly, but the ‘omph’ is there. So, what about the instruc­tion count?

Min­i­mal­ist F-Schlick with Kele­men/Szir­may-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 pow­er.
Cal­cu­late 1 - k_s.

If you already have (\mathbf{L} \cdot \mathbf{H})^2, the sim­pli­fied mod­el just needs one addi­tion­al mul­ti­pli­ca­tion. The com­bi­na­tion of F-Schlick and Kele­men/Szir­may-Kalos needs 5 or 6 more instruc­tions in a depen­den­cy 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­der­er with up to 8 lights per pass), then I’d rec­om­mend the min­i­mal­ist ver­sion.

[1] Dim­i­tar Lazarov, “Phys­i­cal­ly-based light­ing in Call of Duty: Black Ops” SIGGRAPH 2011
[2] Chris­t­ian Schüler, “An Effi­cient and Phys­i­cal­ly Plau­si­ble Real-Time Shad­ing Mod­el.” ShaderX 7, Chap­ter 2.5, pp. 175–187
[3] Fabi­an Giesen, “Phong Nor­mal­iza­tion Fac­tor deriva­tion”
[4] Kele­men and Szir­may-Kalos, “A Micro­facet Based Cou­pled Spec­u­lar-Mat­te BRDF Mod­el with Impor­tance Sam­pling”, Euro­graph­ics 2001
[5] Lafor­tune and Willems, “Using the mod­i­fied Phong reflectance mod­el for phys­i­cal­ly based ren­der­ing”, Tech­ni­cal Report
[6] Yoshi­haru Gotan­da, “Prac­ti­cal Imple­men­ta­tion of Phys­i­cal­ly-Based Shad­ing Mod­els at tri-Ace”, SIGGRAPH 2010
[7] Robert Cook and Ken­neth Tor­rance, “A reflectance mod­el for com­put­er graph­ics”
[8] Robert Lewis, “Mak­ing Shaders More Phys­i­cal­ly Plau­si­ble”, Com­put­er Graph­ics Forum, vol. 13, no. 2 (June, 1994)
[9] Aki­enne-Möller, Haines and Hoff­mann, “Real-Time Ren­der­ing” book
[10] Pharr, Humphreys, “Phys­i­cal­ly-Based Ren­der­ing” book
[11] Nathaniel Hoff­mann, “Craft­ing Phys­i­cal­ly Moti­vat­ed 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 equa­tion.

    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 direct­ly 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.

    • Hal­lo 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­cif­ic 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­si­ty! In the lim­it of a point light, you would have zero r_0 and infi­nite L, but the prod­uct, the inten­si­ty, and there­fore the irra­di­ance received, stays finite. It is true that in the end, a point light is eval­u­at­ed as a direc­tion­al delta func­tion, but you must not for­get \pi, as it will stay there when you do the lim­it.

  2. It makes a lot more sense now, but I am still slight­ly con­fused about the pi. Let me see if I under­stood this cor­rect­ly. Assum­ing the light source is a small dis­tant sphere as stat­ed orig­i­nal­ly and inside the upper hemi­spher­i­cal range of the receiv­er, the light source is actu­al­ly 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 receiv­er, the pi comes from inte­grat­ing the light source’s hemi­sphere? Or is the pi actu­al­ly com­ing from inte­grat­ing the receiver’s hemi­sphere?

    Thanks again for reply­ing.

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

          \[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­nient­ly 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} lat­er 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­mu­la stat­ed in the arti­cle,

          \[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 shad­er. The radi­ance L' of the shad­ed sur­face (aka. pix­el col­or) is the BRDF times \mathbf{N} \cdot \mathbf{L} times irra­di­ance E. Assum­ing, with­out loss of gen­er­al­i­ty, 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 pix­el col­or. The \pi from the BRDF can­cels with the \pi from the irra­di­ance, so the radi­ance-to-radi­ance rela­tion­ship does not involve \pi:

          \[L' &= k_d \, ( \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^2, and we can recre­ate the usu­al for­mu­la for a dif­fuse light

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

  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­rect­ly: \sin \beta \simeq \beta \simeq \frac{r_0}{r} for large r?

    Thanks for your patience. Much appre­ci­at­ed.

    • 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 observ­er 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­ti­fy my com­ments.

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

  6. I recent­ly start­ed 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-alias­ing in tex­ture author­ing, etc. The issue is that you end up with an unre­al­is­tic “semi-rough” val­ue in the tran­si­tion region, which picks up a broad­er and brighter spec­u­lar high­light than the smooth and rough neigh­bor­ing sur­faces, respec­tive­ly. (BTW, I tried both “real” Cook-Tor­rance and your “min­i­mal­ist” approx­i­ma­tion and got sim­i­lar arti­facts).

    There’s a sim­i­lar issue tran­si­tion­ing between met­al and dielec­tric (ex: rust on met­al), where you get dark fring­ing if you try to reduce the dif­fuse con­tri­bu­tion on the met­al 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-met­al” in between the met­al and the rust.

    The root issue is that fil­ter­ing intro­duces unre­al­is­tic in-between BRDF attrib­ut­es.

    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­rate­ly, and blend the results, but that is pro­hib­i­tive in terms of resources and like­ly 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 appeal­ing.

    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 relat­ed arti­facts?

    • Hal­lo 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 accept­ed it as is and the artists try to work around the issue. Oth­er 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 tex­ture.

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

    • 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 accept­ed 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­i­ty that a pho­ton from the giv­en 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 anoth­er fac­tor that can­cels this out?

    • The RDF (and the NDF) itself is not a prob­a­bil­i­ty but a dis­tri­b­u­tion, aka prob­a­bil­i­ty den­si­ty. To get a prob­a­bil­i­ty 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 plu­g­ins?

    • Hal­lo Jens,
      besides what I wrote in the arti­cle, there is no mag­ic here. I also don’t know of any resource that would specif­i­cal­ly teach about this top­ic. 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. Anoth­er 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­ear­ly* sub­tract that from the pho­to to get the dif­fuse map. Lin­ear­ly means here, that the sub­trac­tion is done in lin­ear light­ing space, not in RGB space. Hope this helps!

  11. Sor­ry for res­ur­rect­ing an old dis­cus­sion, but I am recent­ly 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 sub­sti­tu­tion.

    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­si­ty appears as the prod­uct of L and r_0^2 in the lim­it of a point light. Remem­ber that when the light source is shrunk to a point, we need to make it infi­nite­ly bright. So r_0 goes to zero, and L goes to infin­i­ty, but their prod­uct approach­es the finite val­ue I. It would hap­pen in real life if a dis­tant star is small­er than the res­o­lu­tion of the cam­era. Then we can only mea­sure I but not L, since the sol­id angle of a cam­era pix­el is known but not the actu­al 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 val­ue as r_{0} \to 0, but how does it become the radi­ant inten­si­ty? Can you help me fig­ure this out? Thanks!

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

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

  14. I edit­ed 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­mu­la into the D, F, V fac­tors.

  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 use­ful.

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

    From this equa­tion:

        \[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 oth­er 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 deriva­tion?

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

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

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

    If you can com­ment on this, it would be pret­ty much appre­ci­at­ed 🙂

    • Hi Iryoku,
      the rea­son is because the \pi is also in the for­mu­la 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­rect­ed a slight­ly mis­lead­ing word­ing, in my com­ment post from 2011-09, so now it should be clear.

      The for­mu­la 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 |

  19. Pingback: Physically Based Shading in Games | A Graphics guy's note

Leave a Reply

Your email address will not be published.