Advertisement

Tone mapping options/ correct?

Started by June 16, 2019 07:30 PM
4 comments, last by cozzie 5 years, 5 months ago

Hi all,

Now that I've got my specular normalization working, I tried to play around with several tone mapping options (not doing any HDR so far), based on this article:

http://filmicworlds.com/blog/filmic-tonemapping-operators/

After trying out a number of them, I'm wondering if there's maybe something wrong with the approach in general.
The HLSL code is pasted below with some shots of the results. Any input is appreciated.

Also, which one would you say looks best? (knowing this is a preference/ taste thing perhaps).

A = linear exposure, so input color * 8
B = linear exposure / (1 + linear exposure) (Reinhard)
C = Jim Hejl and Richard Burgess-Dawson
D = Uncharted 2

In all cases I left out the linear to sRGB/ gamma conversion, because I let DX11 handle this through the proper RT/ texture buffer formats. Also good to know, the scene has relatively low ambient light (0.15, 0.15, 0.15), and the directional light (moon) has intensity 0.3 (color 1/1/1).


float3 ToneMapA(float3 pInputColor, uint pExposureMul)
{
	float3 output = pInputColor * pExposureMul;
	//output  = pow(output, 1/2.2f);
	return output;
}

float3 ToneMapB(float3 pInputColor, uint pExposureMul)
{
	float3 output = pInputColor * pExposureMul;
	output = output / (1.0f + output);
	//output = pow(output, 1/2.2f);
	return output;
}

float3 ToneMapC(float3 pInputColor, uint pExposureMul)
{
	float3 output = pInputColor * pExposureMul;
	
	float3 x = max(0, output-0.004);
	float3 retColor = (x*(6.2*x+.5))/(x*(6.2*x+1.7)+0.06);
	
	//retColor = pow(retColor, 1/2.2f);
	
	return retColor;
}

float3 ToneMapD(float3 x)		// used for uncharted
{
	float A = 0.15;
	float B = 0.50;
	float C = 0.10;
	float D = 0.20;
	float E = 0.02;
	float F = 0.30;
	float W = 11.2;
	
	return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;
}

float3 ToneMapUncharted(float3 pInputColor, uint pExposureMul)
{
	float W = 11.2;

	float3 output = pInputColor * pExposureMul;
	
	float ExposureBias = 2.0f;
	float3 curr = ToneMapD(ExposureBias * output);
	
	float3 whiteScale = 1.0f/ToneMapD(W);
	float3 color = curr * whiteScale;
	
	//float3 retColor = pow(color,1/2.2);
	return color;
}

// PIXEL SHADER (example, could be options A, B, C or Uncharted

	if(gPerMaterial.Material.IsMetal)
		final.rgb = d + sMetal;
	else
		final.rgb = d + sNonMetal;

	final.rgb = ToneMapC(final.rgb, 8);

// or when I test with tone mapping the lighting part only

	float3 diffuse = ToneMapA(lightSetup.DiffuseAcc, 8);
	float3 specular = ToneMapA(lightSetup.SpecularAcc, 8);
	
	float3 d = diffuse * texColor.rgb * gPerMaterial.Material.Diffuse.rgb;
	float3 sMetal = specular * (texColor.rgb * 2.0f);
	float3 sNonMetal = specular;

	if(gPerMaterial.Material.IsMetal)
		final.rgb = d + sMetal;
	else
		final.rgb = d + sNonMetal;
	
	return final;

Off:

tonemapping-off.jpg

A - linear - exposure 8 (ALL):

tonemapping-A-exp8-linear-all.jpg

A - linear - exposure 8 - only applied to lighting:

tonemapping-A-exp8-linear-lightonly.jpg

B - Reinhard - exposure 8 - ALL

tonemapping-B-exp8-reinhard-all.jpg

B - Reinhard - exposure 8 - only applied to lighting

tonemapping-B-exp8-reinhard-lightonly.jp

C - Jim Hejl and Richard Burgess-Dawson - exposure 8 = ALL

tonemapping-C-exp8-hejl-dawson-all.jpg

C - Jim Hejl and Richard Burgess-Dawson - exposure 8 - only applied to lighting

tonemapping-C-exp8-hejl-dawson-lightonly

D - Uncharted 2 - exposure 8 - all

tonemapping-D-exp8-Uncharted2-all.jpg

D - Uncharted 2 - exposure 8 - only applied to lighting

tonemapping-D-exp8-Uncharted2-lightonly.

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

I recently experimented with several tone mapping options and also felt like there was something "wrong" with each of them, until I found out about "piecewise power curves" (http://filmicworlds.com/blog/filmic-tonemapping-with-piecewise-power-curves/) that looked much more natural, at least in my opinion. This could of course be a matter of taste or depend on what kind of mood you want in the game. I had a forest scene with a bright sky and dark shadows below trees, and the power curves seemed to bring details from bright areas and darks areas without distorting the colors too much.

Advertisement

Thanks @Puffin, that’s interesting indeed, I’ll go through it and so some more testing.

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Tone mapping just the lighting instead of the final result makes no physical sense, but anything goes in non-realistic rendering -- I guess that could be a neat tool...

Tone mapping handles the "film" part of a camera in a scene. The lighting and material code handles what happens as light bounces around the scene, then, eventually it enters a cameras lens and lands on the film/sensor. Tone mapping takes those final rays of light as input, and produces a developed image as output (usually 8bit sRGB). The input light is unbounded - 0 to infinite energy can come in (or some extreme amount that sets the film on fire).

Without HDR rendering, you start with a valid 8bit sRGB image, which is the desired output of a tone mapper... So you don't need one. When you multiply by 8, you're generating a HDR image (but without any of the interesting contrast from actual HDR rendering), but you also know the perfect way to compress this image down to the 8bit sRGB range without losing any data -- just divide by 8 ?

In the general case, you don't know the best way to compress your HDR image down to 8bit sRGB... The right exposure value should be chosen to produce a "pleasing" mapping down to 8 bit, such as making sure that the average output luminance is around middle grey (128 linear / 186? sRGB) and that there's not too much clipping (pixels >256), etc... You can do this the middle grey part of that by measuring the average HDR luminance, call it A, and setting exposure (E) to E=G/A, where G is the HDR value that will result in an output of 0.5 after tone mapping. More advanced systems will generate a luminance histogram instead of just looking at the average.

In your case, you've got such a limited range of luminance values to begin with that you shouldn't expect tone mapping to add much.

As well as having options to choose the tone mapping technique though, you should also at least try manually tweaking the exposure value (if not using auto exposure as above), and even adding some typical photo adjustment sliders like contrast/brightness/levels. 

Thanks @Hodgman. For now I used the uncharted 2 variant and tweaked its values for the night scene. Will look into HDR at a later stage.

This is now:

 

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

This topic is closed to new replies.

Advertisement