Lighting part 2: Reflections (+video)

When the light hits a surface, it bounces. This is a basic fact for all lighting computations. You must also remember that almost everything both receives and emits light. For example if you have colour-painted walls try taking a blank sheet of paper and putting it near a wall. You will notice that paper has caught your wall’s colour (it’s called colour bleeding). By the way, did you know that a sheet of paper in sunlight gives off more photons than a light bulb? (via @ID_AA_Carmack)

Posted by on

When the light hits a surface, it bounces. This is a basic fact for all lighting computations. You must also remember that almost everything both receives and emits light. For example if you have colour-painted walls try taking a blank sheet of paper and putting it near a wall. You will notice that paper has caught your wall's colour (it's called colour bleeding). By the way, did you know that a sheet of paper in sunlight gives off more photons than a light bulb? (via @ID_AA_Carmack)

And some surfaces are glossy enough to reflect even more light than others. Yet exact nature of those reflections depend on micro-surface properties. Well-polished mirror will give you an exact specular (without distortions) reflection, but some kinds of wood will give you more blurry (diffuse) reflections. And there are other materials that need reflections to look well, for example different kinds of metal.

In 3D graphics we have 2 basic options for reflections and both of them have their pros and cons. First, we have planar reflections:

We can also perturb normals a little bit to highlight crevices in tiles:

Some time ago, planar reflections (without perturbations though) were rather cheap and many games used them for mirrors or floors. However in the realms of more and more complex shaders and Deferred Lighting, planar reflections became very expensive to render. If you want to reflect exact scene you're looking at normally you need to do lighting, shadows, ambient occlusion and everything else twice -- thus doubling amount of rendering work. And in graphically demanding games that is just impossible.

The second option is using cubemaps for environmental mapping. The idea is to take a cubemap from inside a scene and use it for reflections for all objects. This have several advantages over planar reflections: they may be cached -- this of course won't let you have dynamic reflections but drastically reduces CPU/GPU workload. Cubemaps can also be used for all kinds of objects and surfaces, while planar reflection requires additional rendering for every single flat surface we want to be reflective. So cubemapping is the only option for complex, curved objects.

Basic specular cubemapping may look like this:

And we can make if more diffuse (blurry):

But cube reflections are not perfect. They are very crude approximation and this can be visible if you have several objects of the same kind next to each other:

Due to the way that env-mapping works, reflections of each of those cars will look exactly the same:

For some objects/scenes this may be undesirable. However there is a solution for some specific cases. If you restrict reflections to box-shaped room, you may use some clever math to make reflections more accurate:

This looks much better and more exact. However, reflections in current rendering engines are quite complicated and not as powerful as you might wish they would have been. Raytracing (which is now possible in real-time) fixes this, allowing unlimited reflections and refractions. However raytracing doesn't itself solve global illumination and -- in my opinion -- its cool reflections are not worth huge performance penalty (unless on massively parallel systems).

And by the way: I've also added first Youtube video. So if you can stand my terrible English, you can watch it here:

If you're interested in our game and technology, don't forget to subscribe to our news feeds: