ARF addresses this issue by approximating arbitrary BRDF for surfaces lit by global lighting, represented by easily rotatable zonal harmonic coefficients.
First we generate lighting information at each surface element or vertex and then store these as spherical harmonic floats. This can be done by rendering the scene normally on the GPU from the position of each surface element oriented about the normal to capture lighting about the hemisphere and then processing the frame buffer on the CPU. ARF currently uses a paraboloid projection for the hemisphere instead of a cubemap projection when rendering the scene because it's significantly faster, but at the cost of interpolation artifacts around less tesselated geometry. ARF will probably also support cubemap projection for higher quality results in the future.
Secondly we also generate a BRDF response table for every light orientation in the hemisphere about a surface and compress that into spherical harmonics and repeat this also for every viewpoint. We compress these spherical harmonics further into approximate zonal harmonic representations for faster rotations at the expense of some accuracy and store the results in one 64x64 4-byte texture and another 64x64 2-byte texture. Each zonal harmonic coefficient is range-compressed to fit into 8-bits rather than a 32-bit float. Every entry in the texture(s) now contain the zonal harmonic representation of the BRDF for every viewpoint about the hemisphere.
At runtime, we index the two lookup textures in the GPU with the view direction and reconstruct the zonal harmonic coefficients representing the BRDF for that particular view and rotate that to the tangent frame for the surface. We then simply evaluate the lighting equation with the BRDF and incident lighting coefficients.
Some shortcomings with this implementation is that only lower-frequency lighting and BRDF can be practically approximated with spherical harmonics, and the additional compression into zonal harmonics for the BRDF also means that certain complex BRDF cannot be fully represented.
However, the simplicity of it's implementation, acceptable visual results in the general case and very fast performance (especially if lighting is stored and compressed per vertex) means that overall this lighting technique can still be quite practical even on lower end systems. On an ATI 5850 GPU and Core i5 CPU the example scene above renders in ~2 ms with cascade shadow directional lighting in a deferred pass. Without the cascade shadows, it takes only less than 1 ms on the same setup.





















