<p>Effectively, before you start to think about clipping/clamping, you'll need a general approach to map the much wider color range you are working in onto the [0,1] triplets you want to output. There are various way to do this, look up <strong>HDR tone mapping</strong> to get a good first impression of what is possible. Simply clipping things to [0,1] will leave you with a very cramped color space to work in, throwing away much of the advantages of raytracying in "high dynamic range" (floats).</p>

<p>On to the actual problem at hand, to prevent clamped colours from shifting hue, a naive but functional approach is:</p>

<ol>
<li>Take the max component <em>m</em> from (R, G, B)</li>
<li>If <em>m</em> > 1, scale all three components by 1 / <em>m</em>.</li>
</ol>

<p>This does not take the relative luminance of the color components into account, but if you eventually end up doing something like tone-mapping anyway that would be a better time to tackle that problem.</p>

CC BY-SA 3.0
2017-12-31T11:11:02.877Z
2017-12-31T11:11:02.877Z
Paul-Jan
<p>In my naïve raytracer experiment I work internally with RGB values, and after all the tracing has been done, I end up with raw RGB triplets that I need to write down to some image format with a limited gamut, typically sRGB.</p>

<p>Since bright spots in my image can have values far beyond (1,1,1), I need to clip them. Right now I just limit each channel individually, but that will obviously introduce a shift in hue when one channel clips before another. Here is a typical (enlarged) example from my code where the yellow-green object turns into yellow around the highlight:</p>

<p><a href="https://i.sstatic.net/V1hMC.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/V1hMC.png" alt="Example of hue shift"></a></p>

<p>I'm now looking for a way to solve this problem, but all the solutions I come up with seems to have the same drawback: eventually you <em>have</em> to discard information. For example, I've thought about working with another colorspace like Lab internally, but even then I would first have to transform it to sRGB for rendering the final image file.</p>

<p>Before I dig myself into this any further, I would like to see if there is either:</p>

<ul>
<li>An objectively "best" way to solve this problem, or..</li>
<li>An industry standard way that is used in practice</li>
</ul>

CC BY-SA 3.0
2017-12-31T10:53:07.487Z
Would I be right in thinking your "raw RGB triplets" are floating-point values, and the problem comes when you clamp them to [0,1]?
Dan Hulme
CC BY-SA 3.0
2017-12-31T23:23:33.040Z
@DanHulme That's right! The same problem could also occur if I work with another colorspace internally and then want to convert to something the display or file format can handle. But in this particular case it is because I use floats with light sources brighter than "one".
pipe
<raytracing><color>
How do you deal with clipping when rendering to a limited colorspace?
pipe
# How do you deal with clipping when rendering to a limited colorspace?

(Asked by: username_0 on 2017-12-31)

In my naïve raytracer experiment I work internally with RGB values, and after all the tracing has been done, I end up with raw RGB triplets that I need to write down to some image format with a limited gamut, typically sRGB.

Since bright spots in my image can have values far beyond (1,1,1), I need to clip them. Right now I just limit each channel individually, but that will obviously introduce a shift in hue when one channel clips before another. Here is a typical (enlarged) example from my code where the yellow-green object turns into yellow around the highlight:

[![Example of hue shift](https://i.sstatic.net/V1hMC.png)](https://i.sstatic.net/V1hMC.png)

I'm now looking for a way to solve this problem, but all the solutions I come up with seems to have the same drawback: eventually you *have* to discard information. For example, I've thought about working with another colorspace like Lab internally, but even then I would first have to transform it to sRGB for rendering the final image file.

Before I dig myself into this any further, I would like to see if there is either:

* An objectively "best" way to solve this problem, or..
* An industry standard way that is used in practice

**Tags:** raytracing, color

> **Comments:**
> **username_1**: Would I be right in thinking your "raw RGB triplets" are floating-point values, and the problem comes when you clamp them to [0,1]?  
> **username_0**: @username_1 That's right! The same problem could also occur if I work with another colorspace internally and then want to convert to something the display or file format can handle. But in this particular case it is because I use floats with light sources brighter than "one".  

---

## 1 answers

### Answer by username_2 on 2017-12-31. Score: 6

Effectively, before you start to think about clipping/clamping, you'll need a general approach to map the much wider color range you are working in onto the [0,1] triplets you want to output. There are various way to do this, look up **HDR tone mapping** to get a good first impression of what is possible. Simply clipping things to [0,1] will leave you with a very cramped color space to work in, throwing away much of the advantages of raytracying in "high dynamic range" (floats).

On to the actual problem at hand, to prevent clamped colours from shifting hue, a naive but functional approach is:

1. Take the max component *m* from (R, G, B)
2. If *m* > 1, scale all three components by 1 / *m*.

This does not take the relative luminance of the color components into account, but if you eventually end up doing something like tone-mapping anyway that would be a better time to tackle that problem.


---

