I have implemented Preetham, Shirley, and Smits’s daylight model using Aubrey Jaffer’s Scheme implementation as a reference and confirmed that my implementation produces the same results in the xyY coordinate space for the same input on all my test cases as Jaffer’s.

However, when I try to convert this output to sRGB using the standard formulae, almost all inputs except for those around sunrise and sunset map to colours ‘darker than black’ (all coordinates less than 0) at night, or ‘lighter than white’ (all coordinates greater than 1.0/255) during the day.

An example: for solar day 38 (declination -15.7117) at solar hour 14 at latitude 52.52 (θs = 72.9996°, φs = 44.0935°) with turbidity 6, Jaffer’s implementation and mine both give xyY values for θ = 30, φ = 0: (0.3576953919457298, 0.3065955987210767, 5.907977352059564). This is the procedure clear-sky-color-xyY in Jaffer’s Scheme implementation. However, using Jaffer’s xyY->XYZ and CIEXYZ->sRGB procedures (which likewise apply the same formulae as my code) on this result yields sRGB octets 255, 255, and 255.

For solar hours around 7 and 17 (sunset and sunrise), the results appear somewhat reasonable, but broad daylight and dark night are both too light and too dark.

What corrections are necessary to make the model practical for rendering in sRGB and similar colour spaces?


1 Answer 1


Consider these facts:

  • Monitors and TVs cannot reproduce the full brightness of the sun, or even many other light sources.
  • Both eyes and cameras react to the overall brightness they perceive (“adaptation” in the first case, and “automatic exposure” in the second) to capture an image which is in a usable range.

Thus, at least one, and often several, of the steps in the path from physical reality (or simulation thereof) to what we perceive in our brains, largely discard the absolute intensity of light in favor of preserving differences between parts of the scene. Most color and image data on computers represents relative luminance, not absolute.

You're attempting to skip that step, and it's not working, because the practice of storing 8 bits per color component (as most image file formats typically do) rests on the premise that the image represents a “reasonable” range of luminance. (High-dynamic-range image formats store more bits per component.)

What you can do instead:

  1. Scale your pixel values (“set the exposure”) differently for day and night. You can do this arbitrarily as an artistic choice, or you can render your scene, make a histogram of the pixels' luminance, and then choose a scale value which ensures that no more than some chosen fraction of the pixels are “overexposed” (greater than 255 after scaling).
  2. Use a HDR output format.

I also notice that you mention pixels that are “blacker than black”. That shouldn't happen in a realistic model, since there's no such thing as negative light. This might mean that small floating-point rounding errors produced numbers slightly less than zero (harmless), or that the color-space conversion math produced a slightly impossible color, or that you have some other more significant arithmetic error.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.