Jump to content

  • Log In with Google      Sign In   
  • Create Account


Tonemapping Formula Help (Math Help)


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
11 replies to this topic

#1 jeffkingdev   Members   -  Reputation: 738

Like
0Likes
Like

Posted 15 October 2012 - 02:14 PM

Hello,

Can someone please help me understand the details of tone mapping? See my questions throughout this post.

My understanding (I put some example numbers in there, from thin air):
  • Tonemapping brings a range of color values (ex. 0.5 to 2.0) into a range the computer can output (0.0 to 1.0).
  • Tonemapping also uses a curved formula based on what your average luminance value and the highest value in the scene is. So if the scene is darker, more values (ex. perhaps 0.0 to 0.8) will be used for darker colors.
  • The value from my tonemapping formula will be multiplied to my scene's color.
So, I would expect results like this:

0.2 average scene luminance
1.1 brightest pixel on screen
Scene image values (0.0 to 0.4) mapped to output values (0.0 to 0.6). (largest range)
Scene image values (0.4 to 1.1) mapped to output values (0.6 to 1.0).

Another Example I would expect:

0.8 average scene luminance
2.0 brightest pixel on screen
Scene image values (0.0 to 0.6) mapped to output values (0.0 to 0.2).
Scene image values (0.6 to 1.0) mapped to output values (0.2 to 0.8). (largest range)
Scene image values (1.0 to 2.0) mapped to output values (0.8 to 1.0).

Reinhard's tonemapping in HLSL (is my math ok?)

avgLum = average scene luminance;
static const float MIDDLE_GREY = 0.72f;  /// WHY IS THIS 0.72????????  I HATE MAJIK NUMBERS <img src='http://public.gamedev.net//public/style_emoticons/<#EMO_DIR#>/smile.png' class='bbc_emoticon' alt=':)' />
newCol = (MIDDLE_GREY / avgLum) * pxColor;
static const float L_WHITE = 1.5f; // I assume this is just our max value before it's pure white
newCol = newCol * (1.0f + newCol / L_WHITE) / (1.0f + newCol);

Some examples!!!

-------------------------------------------------------------------------------

avgLum = 0.2
pxColor = {1.0, 1.0, 1.0}

newCol = (0.72 / 0.2) * {1.0, 1.0, 1.0};
newCol = newCol * (1.0f + newCol / 1.5) / (1.0f + newCol);
newCol = 12.24 / 4.6;
newCol = {2.66, 2.66, 2.66} ???? WTF Why is my 1.0 now being blown out to 2.6?

-------------------------------------------------------------------------------

avgLum = 0.2
pxColor = {0.1, 0.1, 0.1}

newCol = (0.72 / 0.2) * {0.1, 0.1, 0.1};
newCol = newCol * (1.0f + newCol / 1.5) / (1.0f + newCol);
newCol = 0.0864 / 1.36;
newCol = {0.0635,0.0635,0.0635} ??? why did my 0.1 get darker???

-------------------------------------------------------------------------------

avgLum = 0.5
pxColor = {0.5, 0.5, 0.5}

newCol = (0.72 / 0.5) * {0.5, 0.5, 0.5};
newCol = newCol * (1.0f + newCol / 1.5) / (1.0f + newCol);
newCol = 1.0656 / 1.72;
newCol = {0.62,0.62,0.62} ??? This actually seems ok, other than why did it get brighter? Shouldn't this be a perfect 0.5?

Please see my questions above, thanks for any help. This is confusing. The biggest question is why are some ppl putting 0.72 into a MIDDLE_GRAY variable. I've seen several ppl do this.

Thanks
Jeff.

Sponsor:

#2 Álvaro   Crossbones+   -  Reputation: 12020

Like
0Likes
Like

Posted 15 October 2012 - 02:37 PM

The biggest question is why are some ppl putting 0.72 into a MIDDLE_GRAY variable.


It may have something to do with gamma correction. In a monitor with gamma=2.2, the color 0.7297 maps to middle gray. For gamma=1.8 (the other popular alternative), the number should be 0.6804.

#3 jeffkingdev   Members   -  Reputation: 738

Like
0Likes
Like

Posted 15 October 2012 - 02:48 PM

alvaro,

Of course! That makes sense. One problem solved. Thanks!

Jeff.

#4 jeffkingdev   Members   -  Reputation: 738

Like
0Likes
Like

Posted 15 October 2012 - 08:10 PM

Also,

Where is the correct place to add exposure?

I tried:

avgLum = average scene luminance;

newCol = (MIDDLE_GREY / (exposure / avgLum)) * pxColor;   // NOTICE: exposure added
newCol = newCol * (1.0f + newCol / L_WHITE) / (1.0f + newCol);

That didn't work though. Any other ideas where exposure should be added?

Thanks
Jeff.

#5 Bacterius   Crossbones+   -  Reputation: 8190

Like
1Likes
Like

Posted 15 October 2012 - 08:34 PM

Uh, I think you shouldn't have "newCol *" in the second line. You're already multiplying by the pixel color in the previous line. And L_WHITE needs to be squared. And I'm pretty sure you need to work with luminance, not with colors directly? See my topic. So something like:

[source lang="cpp"]key = exposure / avgLumnewCol = oldCol * (1 + Luminance(oldCol) / L_WHITE^2) / (1 + Luminance(oldCol))[/source]

I think.. not sure where the MIDDLE_GREY goes though.

Edited by Bacterius, 15 October 2012 - 08:34 PM.

The slowsort algorithm is a perfect illustration of the multiply and surrender paradigm, which is perhaps the single most important paradigm in the development of reluctant algorithms. The basic multiply and surrender strategy consists in replacing the problem at hand by two or more subproblems, each slightly simpler than the original, and continue multiplying subproblems and subsubproblems recursively in this fashion as long as possible. At some point the subproblems will all become so simple that their solution can no longer be postponed, and we will have to surrender. Experience shows that, in most cases, by the time this point is reached the total work will be substantially higher than what could have been wasted by a more direct approach.

 

- Pessimal Algorithms and Simplexity Analysis


#6 allingm   Members   -  Reputation: 421

Like
1Likes
Like

Posted 15 October 2012 - 09:54 PM

I finally found the book. You can find all the correct formulas here:

http://content.gpwiki.org/index.php/D3DBook:High-Dynamic_Range_Rendering#Luminance_Transform

Edited by allingm, 15 October 2012 - 09:56 PM.


#7 jeffkingdev   Members   -  Reputation: 738

Like
0Likes
Like

Posted 16 October 2012 - 01:56 PM

Bacterius,

Sounds like I am where you were on that post. If you don't mind me asking you some followup questions:

Working in luminance values makes a lot of sense!

I updated my code to:
[source lang="cpp"]lumAvg = l.r;lumPx = dot(final, LUM_CONVERT);lumScaled = (lumPx) / lumAvg;lumComp = (lumScaled * (1 + (lumScaled / (L_WHITE * L_WHITE)))) / (1 + lumScaled);[/source]
I like to dumb down equations. If L_WHITE = 1 then that line is cancelled out and I'm left with essentially color = oldColor * (lumPx / lumAvg);

Does that seem right? I've noticed a lot of documentation refering to this magical x / (1 + x). Where is that? I thought that was (lumScaled / (1+lumScaled); but closer inspection, it appears I'm doing (1+lumScaled) / (1+lumScaled); (just taking into account for the white squaring. Any ideas where the x/(1+x) occurs?

-----------------------------------------------------------------

allingm,

Thanks for the link! Very informative read. I had a question though. Do I need to do an RGB to XYZ conversion and then back? I couldn't understand if that was necessary along with the way I'm doing it or if it only mattered a different way.

Thanks guys! Very useful information
Jeff.

#8 riuthamus   Crossbones+   -  Reputation: 4332

Like
0Likes
Like

Posted 17 October 2012 - 12:10 PM

We had all of the same issues and this was the thread I had that helped us:

http://www.gamedev.net/topic/630256-hdr-tonemapping-skylight-fail/

#9 jeffkingdev   Members   -  Reputation: 738

Like
0Likes
Like

Posted 18 October 2012 - 01:22 PM

riuthamus,

Great link. I am still reading through it. Can you tell me what your sky color values were? Did you have your sky color being a large value? Also, what was your sun value? Was that proportional to the sky color value?

Thanks
Jeff.

#10 riuthamus   Crossbones+   -  Reputation: 4332

Like
0Likes
Like

Posted 18 October 2012 - 05:48 PM

Honestly, we had to make a damn tool to fix it! I wouldnt mind sharing what we have so long as the coders are cool with it. Ill get with them tonight and see if they dont mind putting some info your way. As for the values, our file looks like this:

<EnvironmentSetting>
	  <Time>7</Time>
	  <SunSetting>
	   <DiffuseColor>
	    <X>0.980</X>
	    <Y>0.776</Y>
	    <Z>0.678</Z>
	    <W>1</W>
	   </DiffuseColor>
	   <AmbientColor>
	    <X>0.364</X>
	    <Y>0.282</Y>
	    <Z>0.494</Z>
	    <W>1</W>
	   </AmbientColor>
	   <DiffuseIntensity>2</DiffuseIntensity>
	   <AmbientIntensity>2</AmbientIntensity>
	   <SpecularPower>1</SpecularPower>
	   <SpecularIntensity>1</SpecularIntensity>
		  <MinLuminance>.5</MinLuminance>
		  <MaxLuminance>100</MaxLuminance>
	  </SunSetting>
	  <FogSetting>
	   <Color>
		    <X>0.345</X>
		    <Y>0.239</Y>
		    <Z>0.415</Z>
	   </Color>
	   <Start>0.6</Start>
	   <End>0.9</End>
	  </FogSetting>
	  <SkySettingSimple>
	   <TopColor>
	    <X>0.141</X>
	    <Y>0.188</Y>
	    <Z>0.356</Z>
	   </TopColor>
	   <BottomColor>
	    <X>0.521</X>
	    <Y>0.317</Y>
	    <Z>0.666</Z>
	   </BottomColor>
	   <BlendAmount>8</BlendAmount>
	   <SkyMultiplier>4</SkyMultiplier>
	  </SkySettingSimple>
	</EnvironmentSetting>


#11 jeffkingdev   Members   -  Reputation: 738

Like
0Likes
Like

Posted 18 October 2012 - 06:06 PM

riuthamus,

Was your sun color diffuse = diffuse * diffuseIntensity?

Same question about your sky:

sky color *= skymultiplier? (In order to get it HDR)

Thanks!
Jeff.

#12 riuthamus   Crossbones+   -  Reputation: 4332

Like
0Likes
Like

Posted 18 October 2012 - 07:35 PM

yeah




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS