<p>There are multiple different ways to do tone-mapping, including both local and global methods. I won't discuss local methods (i.e. methods based on using surrounding information as part of the tone mapping process) here. Global methods can be broken down into two components:</p>

<ol>
<li>A formula for mapping from $[0,\infty)$ to $[0,1]$.</li>
<li>A method of applying this to the color.</li>
</ol>

<p>The simplest formula out there is just $out = in / (in + 1)$, but the results are also fairly boring. A fancier curve is the filmic tone mapping function developed by John Hable, which is <a href="http://frictionalgames.blogspot.de/2012/09/tech-feature-hdr-lightning.html" rel="noreferrer">popular in the video gaming industry</a>:</p>

<pre><code>float hable(float x)
{
    float A = 0.15;
    float B = 0.50;
    float C = 0.10;
    float D = 0.20;
    float E = 0.02;
    float F = 0.30;

    return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;
}
</code></pre>

<p>You can also get even fancier if you can constrain the input domain to a known, fixed peak value.</p>

<p>As for how to apply this function to an actual color value, there are again multiple techniques. A very simple way is to do it per-channel, i.e. <code>color.r = map(color.r); color.g = map(color.g); color.b = map(color.b);</code>. But this has the downside of warping the appearance of bright colors towards white (e.g. orange becomes yellowish under tone-mapping). Some in the movie industry tend to like this look, for whatever reason.</p>

<p>To do color-preserving tone mapping, you can perform the calculation on a single value only and then apply the same scale to all three channels. A good choice for the value to use is to choose the “brightest” of the three components:</p>

<pre><code>float sig = max(color.r, max(color.g, color.b));
color.rgb *= vec3(map(sig) / sig);
</code></pre>

<p>However, this approach also has downsides, namely that it takes very bright objects to unnaturally saturated versions of
themselves. For example, a bright sun might suddenly appear various shades of yellow and orange - which also looks unnatural on photographic content.</p>

<p>So ultimately, what I do is first desaturate the color based on how bright it is, and then apply tone mapping after the fact, leading to an algorithm that looks something like this:</p>

<pre><code>// Calculate the desaturation coefficient based on the brightness
float sig = max(color.r, max(color.g, color.b));
float luma = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));
float coeff = max(sig - 0.18, 1e-6) / max(sig, 1e-6);
coeff = pow(coeff, 20.0);

// Update the original color and signal
color.rgb = mix(color.rgb, vec3(luma), coeff);
sig = mix(sig, luma, coeff);

// Perform tone-mapping
color.rgb *= vec3(map(sig) / sig);
</code></pre>

<p>But YMMV.</p>

<p>References:</p>

<ul>
<li><a href="https://github.com/haasn/libplacebo/blob/master/src/shaders/colorspace.c#L664" rel="noreferrer">https://github.com/haasn/libplacebo/blob/master/src/shaders/colorspace.c#L664</a></li>
<li>You can also poke at ITU-R Report BT.2390-2 for some more ideas and guidelines.</li>
</ul>

CC BY-SA 3.0
2018-02-21T17:49:20.640Z
Thank you for your lenghty and detailed response. However the sun still looks unrealistic ( I attached an image in the description above). Is this a tone mapping issue? I want my sun to look more like a glow.
Maria
CC BY-SA 3.0
2018-02-21T17:50:10.393Z
It sounds like you want to be implementing a bloom filter?
haasn
CC BY-SA 3.0
2018-02-21T16:28:07.693Z
2018-02-21T16:33:53.197Z
2018-02-21T16:33:53.197Z
haasn
<p>I am rendering the sun in an image, and the sun comes out white and is basically very unrealistic. I have tried searching for  tone mapping algorithms but I'm very lost. Can someone guide me to do this? or perhaps help me with the pseudo</p>

<p><a href="https://i.sstatic.net/IqqlS.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/IqqlS.png" alt="Sun"></a></p>

CC BY-SA 3.0
2018-02-21T18:28:56.290Z
You probably also want to look into a bloom effect to simulate the glare of the sun.
Nathan Reed
CC BY-SA 3.0
2018-02-21T18:40:58.213Z
@NathanReed She probably mean radial blur light shafts.
mdkdy
<raytracing><rendering><mapping>
Tone mapping bright images
Maria
# Tone mapping bright images

(Asked by: username_0 on 2018-02-21)

I am rendering the sun in an image, and the sun comes out white and is basically very unrealistic. I have tried searching for tone mapping algorithms but I'm very lost. Can someone guide me to do this? or perhaps help me with the pseudo

[![Sun](https://i.sstatic.net/IqqlS.png)](https://i.sstatic.net/IqqlS.png)

**Tags:** raytracing, rendering, mapping

> **Comments:**
> **username_1**: You probably also want to look into a bloom effect to simulate the glare of the sun.  
> **username_2**: @username_1 She probably mean radial blur light shafts.  

---

## 1 answers

### Answer by username_3 on 2018-02-21. Score: 5

There are multiple different ways to do tone-mapping, including both local and global methods. I won't discuss local methods (i.e. methods based on using surrounding information as part of the tone mapping process) here. Global methods can be broken down into two components:

1. A formula for mapping from $[0,\infty)$ to $[0,1]$.
2. A method of applying this to the color.

The simplest formula out there is just $out = in / (in + 1)$, but the results are also fairly boring. A fancier curve is the filmic tone mapping function developed by John Hable, which is [popular in the video gaming industry](http://frictionalgames.blogspot.de/2012/09/tech-feature-hdr-lightning.html):

```
float hable(float x)
{
    float A = 0.15;
    float B = 0.50;
    float C = 0.10;
    float D = 0.20;
    float E = 0.02;
    float F = 0.30;

    return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;
}

```

You can also get even fancier if you can constrain the input domain to a known, fixed peak value.

As for how to apply this function to an actual color value, there are again multiple techniques. A very simple way is to do it per-channel, i.e. `color.r = map(color.r); color.g = map(color.g); color.b = map(color.b);`. But this has the downside of warping the appearance of bright colors towards white (e.g. orange becomes yellowish under tone-mapping). Some in the movie industry tend to like this look, for whatever reason.

To do color-preserving tone mapping, you can perform the calculation on a single value only and then apply the same scale to all three channels. A good choice for the value to use is to choose the “brightest” of the three components:

```
float sig = max(color.r, max(color.g, color.b));
color.rgb *= vec3(map(sig) / sig);

```

However, this approach also has downsides, namely that it takes very bright objects to unnaturally saturated versions of
themselves. For example, a bright sun might suddenly appear various shades of yellow and orange - which also looks unnatural on photographic content.

So ultimately, what I do is first desaturate the color based on how bright it is, and then apply tone mapping after the fact, leading to an algorithm that looks something like this:

```
// Calculate the desaturation coefficient based on the brightness
float sig = max(color.r, max(color.g, color.b));
float luma = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));
float coeff = max(sig - 0.18, 1e-6) / max(sig, 1e-6);
coeff = pow(coeff, 20.0);

// Update the original color and signal
color.rgb = mix(color.rgb, vec3(luma), coeff);
sig = mix(sig, luma, coeff);

// Perform tone-mapping
color.rgb *= vec3(map(sig) / sig);

```

But YMMV.

References:

* <https://github.com/username_3/libplacebo/blob/master/src/shaders/colorspace.c#L664>
* You can also poke at ITU-R Report BT.2390-2 for some more ideas and guidelines.

> **Comments:**
> **username_0**: Thank you for your lenghty and detailed response. However the sun still looks unrealistic ( I attached an image in the description above). Is this a tone mapping issue? I want my sun to look more like a glow.  
> **username_3**: It sounds like you want to be implementing a bloom filter?  

---

