In this tutorial, you have learned the following:
How to build and light a scene containing multiple objects and multiple light sources.
High dynamic range lighting means using a maximum illumination that can vary from frame to frame, rather than a single, fixed value.
Color values have a space, just like positions or normals. Lighting equations work in a linear colorspace, where twice the brightness of a value is achieved by multiplying its value times two. It is vital for proper imaging results to make sure that the final result of lighting is in the colorspace that the output display expects. This process is called gamma correction.
Try doing these things with the given programs.
Add a fifth light, a directional light representing the moon, to the gamma-correct scene. This will require creating another set of interpolators and expanding the SunlightValues structure to hold the lighting intensity of the moon. It also means expanding the number of lights the shaders use from 4 to 5 (or removing one of the point lights). The moon should be much less bright than the sun, but it should still have a noticeable effect on brightness.
Play with the ambient lighting intensity in the gamma-correct scene, particularly in the daytime. A little ambient, even with a maximum intensity as high as 10, really goes a long way to bringing up the level of brightness in a scene.
HDR is a pretty large field. This tutorial covered perhaps the simplest form of tone mapping, but there are many equations one can use. There are tone mapping functions that map the full [0, ∞) range to [0, 1]. This would not be useful for a scene that needs a dynamic aperture size, but if the aperture is static, it does allow the use of a large range of lighting values.
When doing tone mapping with some form of variable aperture setting, computing the proper maximum intensity value can be difficult. Having a hard-coded value, even one that varies algorithmically, works well enough for some scenes. But for scenes where the user can control where the camera faces, it can be inappropriate. In many modern games, they actually read portions of the rendered image back to the CPU and do some computational analysis to determine what the maximum intensity should be for the next frame. This is delayed, of course, but it allows for an aperture that varies based on what the player is currently looking at, rather than hard-coded values.
Just remember: pick your HDR and tone mapping algorithms before you start putting the scene together. If you try to change them mid-stream, you will have to redo a lot of work.