The code is avail­able through the Area Lights ex­am­ple page in the doc­u­men­ta­tion and the ex­am­ple has al­so a live web ver­sion linked be­low. This blog post ex­plains the ba­sics of shad­ing with lin­ear­ly trans­formed cosines (LTCs) and how Mag­num was used for the im­ple­men­ta­tion.

Check out the pa­per on Er­ic Heitz’s Re­search Page for a more de­tailed and com­plete ex­pla­na­tion. It is very well writ­ten and has a ton of sup­ple­men­tal ma­te­ri­al such as a We­bGL im­ple­men­ta­tion to play around with.

To un­der­stand lin­ear­ly trans­formed cosines I will start off by ex­plain­ing some ba­sics. If you al­ready know what BRDFs are, you may want to skip the next para­graph or two.

Bi­na­ry Re­flectance Dis­tri­bu­tion Func­tions When shad­ing a point on a sur­face, phys­i­cal­ly, you need to take all in­com­ing rays from ev­ery di­rec­tion in­to ac­count. Some light rays af­fect the fi­nal col­or of the shad­ed point more than oth­ers — de­pend­ing on their di­rec­tion, the view di­rec­tion and the prop­er­ties of the ma­te­ri­al. A per­fect mir­ror, for ex­am­ple, may take on­ly the ex­act re­flec­tion of the view vec­tor in­to ac­count, as can be seen in fig­ure (a), where­as a more dif­fuse ma­te­ri­al will be af­fect­ed by all or most in­com­ing rays sim­i­lar­ly or equal­ly, as vi­su­al­ized in fig­ure (b). These fig­ures show spher­i­cal dis­tri­bu­tions: imag­ine you want to shade a point on a sur­face (the point where the view vec­tor is re­flect­ed). Imag­ine a ray of light hit­ting this point, it will pierce through the col­ored sphere at some lo­ca­tion. The col­or at that lo­ca­tion on the sphere in­di­cates how much this ray will af­fect the col­or of the sur­face point: the more red, the high­er the ef­fect. (a) Vi­su­al­iza­tion of what the BRDF of a near­ly per­fect mir­ror may look like. (b) Vi­su­al­iza­tion of what the BRDF of a more dif­fuse ma­te­ri­al may look like. The func­tion that de­scribes how much ef­fect an in­com­ing light ray has for giv­en view­ing and in­com­ing light an­gles, is called BRDF . This func­tion is very spe­cif­ic to ev­ery ma­te­ri­al. As this is very im­prac­ti­cal for re­al-time ren­der­ing and art pipe­lines, it is com­mon to in­stead use a so called para­met­ric BRDF; a func­tion which is able to ap­prox­i­mate many dif­fer­ent BRDFs of dif­fer­ent ma­te­ri­als us­ing in­tu­itive pa­ram­e­ters, e.g. rough­ness or met­al­ness. There are many para­met­ric BRDFs out there: the GGX mi­cro­facet BRDF, the Schlick BRDF and the Cook-Tor­rance BRDF. I recom­ment play­ing around with them in Dis­ney’s BRDF Ex­plor­er.

Shad­ing area lights With point lights, shad­ing is re­al­ly sim­ple as you on­ly have a sin­gle in­com­ing ray — as­sum­ing you do not want to take in­di­rect rays in­to ac­count. You can get the ap­pro­pri­ate fac­tor (of how much of that ray will be re­flect­ed in view di­rec­tion) from the BRDF us­ing the view an­gle and light an­gle, mul­ti­ply that with the light in­ten­si­ty and that is al­ready it. With area lights, it is a lot more com­pli­cat­ed, as you have an in­fi­nite amount of in­com­ing rays. The fi­nal in­ten­si­ty of the shad­ed point is the in­te­gral over the BRDF in the do­main of the poly­gon of the light (which, pro­ject­ed on­to the spher­i­cal dis­tri­bu­tion, is a spher­i­cal poly­gon). This is a prob­lem, be­cause we do not have an an­a­lyt­i­cal so­lu­tion to in­te­grat­ing over ar­bi­trary spher­i­cal dis­tri­bu­tions. In­stead, such a so­lu­tion is known on­ly for very spe­cif­ic dis­tri­bu­tions, the uni­form sphere or the co­sine dis­tri­bu­tion for ex­am­ple. So, how can we still do it with­out rad­i­cal­ly ap­prox­i­mat­ing the area light?