Advertisement

DIsplaying an HDR image

Started by May 27, 2024 12:48 AM
5 comments, last by Josh Klint 7 months ago

When I open an EXR in Nvidia Texture Tools it looks like I would expect:

If I open the same image in RenderDoc or in my own software it looks like this:

What is the equation to “fix” these images?

10x Faster Performance for VR: www.ultraengine.com

I think there are 2 issues with your image:

  • First the gamma seems off, due to the shift in colors (e.g. the tan colored rocks turn more orange in your image). I'd check that you are using the right texture format for the image (a linear one probably, e.g. 16F), and also are doing the correct gamma conversion to sRGB on the final output after sampling the texture. It looks like you are getting an unwanted sRGB→linear conversion on sampling the texture, which is wrong because HDR is already linear.
  • The other issue is the lack of tone mapping, which results in the bright white clipped areas in the sky. In the other thread I posted some shader code to do the mapping from HDR→LDR.

Tone mapping curves have a shape similar to this, which maps an input in [0,infinity] to [0,1]. This is the exponential tone mapping operator I posed in the other thread:

There are other possibilities (e.g. Reinhard, ACES), but this is the one I think looks the best. It's important to note that these tone mapping operators all have different slopes, which can confuse comparisons. To avoid this, I try to normalize the operator so that an input of 1.0 produces an output of 0.8. This makes it look about the same as a LDR rendering, and makes comparisons more meaningful.

Advertisement

I didn't do anything. I am just displaying the actual image data. It's RGBA 32 float, so 1.0,1.0,1.0 equals 255,255,255. RenderDoc displays the exact same thing.

10x Faster Performance for VR: www.ultraengine.com

Josh Klint said:
It's RGBA 32 float, so 1.0,1.0,1.0 equals 255,255,255

That doesn't make sense. 32-bit float shouldn't have a maximum of 255, and is probably calibrated so that 1.0== white, not 255==white like in 8-bit images.

To show how it is indeed a gamma issue, I took your screenshot and applied linear→sRGB gamma (approximately sqrt()) to the image. I get something close to the NVIDIA tool:

So you probably have an issue on the import side which causes incorrect gamma. For example, maybe the image import library does a sRGB→linear gamma conversion for you automatically that shouldn't be done.

If I do an srgb to linear conversion then the results look like what I expect:

s = Sample(iVec2(x, y));

for (int n = 0; n < 3; ++n)

{

if (s[n] <= 0.0031308f)

{

s[n] = s[n] * 12.92f;

}

else if (s[n] < 1.0f)

{

s[n] = 1.055 * pow(s[n], 1.0f / 2.4f) - 0.055f;

}

}

r->WritePixel(x, y, s);

10x Faster Performance for VR: www.ultraengine.com

This topic is closed to new replies.

Advertisement