Tone Mapping

Started by
52 comments, last by MJP 6 years, 5 months ago
1 hour ago, turanszkij said:

Keep in mind, you should still do the inverse tonemap trick for MSAA for best results. You have to do a custom resolve for that.

So if I understand correctly, you need to tone-map at the end of the Lighting pass. And then perform another pass to apply the inverse tone-mapping? But isn't this a no-op? The output color is calculated once per pixel and distributed based on the coverage mask among the sub pixels. How is this influenced by the color space?

🧙

Advertisement
1 minute ago, matt77hias said:

So if I understand correctly, you need to tone-map at the end of the Lighting pass. And then perform another pass to apply the inverse tone-mapping? But isn't this a no-op? The output color is calculated once per pixel and distributed based on the coverage mask among the sub pixels. How is this influenced by the color space?

No, I mean that if you have an AA resolve shader, you do the tonemapping right there before the resolve (for all the samples), and inverse tonemap right after, in the same shader (for the final resolved sample). It helps when there are huge discontinuities in the image in nearby samples, because the averaging operation would be biased towards the high values, and aliasing would not be eliminated.

1 hour ago, turanszkij said:

I like to avoid alpha-to coverage and instead use a two pass approach. This consists of first rendering the opaque parts only with alpha test and depth writes turned on. The second pass is depth read only (greater or less depth test but not equal) and with alpha blending but not alpha tested. You don't have to sort alpha blended geometry, because it really won't be visible because of the opaque parts are dominating and are correctly sorted because of the depth buffer. Obviously this works best for vegetation, but not glass and the like. But so does alpha-to coverage.

So you render all models (opaque and transparent) first and perform a clip in the PS based on the alpha value and some threshold (or just 1.0f?). Then you render only transparent models with alpha blending, and only reading the depth buffer.

I actually perform a similar approach if the user does not select MSAA. Though, I do not have the only reading the depth buffer part, but this is not really an issue I suppose if you don't use the depth buffer anymore (sprites just go on top). The alpha blended geometry looks pretty artificial? If I go up and look at the Crytek Sponza scene from above, the pillar plants look very white since they start blending with each other.

🧙

16 minutes ago, turanszkij said:

No, I mean that if you have an AA resolve shader, you do the tonemapping right there before the resolve (for all the samples), and inverse tonemap right after, in the same shader (for the final resolved sample). It helps when there are huge discontinuities in the image in nearby samples, because the averaging operation would be biased towards the high values, and aliasing would not be eliminated.

But in case of MSAA what would the purpose of the AA resolve shader be? Temporal AA only?

🧙

14 minutes ago, matt77hias said:

But in case of MSAA what would the purpose of the AA resolve shader be? Temporal AA only?

The MSAA resolve shader is just sampling all your subsamples of the MSAA texture and averaging them. Now, DX11 provides a built in function for this, but you want to avoid it and write your own if you have a HDR pipeline with tonemap - average - inversetonemap.

26 minutes ago, matt77hias said:

So you render all models (opaque and transparent) first and perform a clip in the PS based on the alpha value and some threshold (or just 1.0f?). Then you render only transparent models with alpha blending, and only reading the depth buffer.

I actually perform a similar approach if the user does not select MSAA. Though, I do not have the only reading the depth buffer part, but this is not really an issue I suppose if you don't use the depth buffer anymore (sprites just go on top). The alpha blended geometry looks pretty artificial? If I go up and look at the Crytek Sponza scene from above, the pillar plants look very white since they start blending with each other.

The opaque clipping is like this:


clip(baseColor.a - AlphaTestThreshold);

Where AlphaTestThreshold is 1.0f / 255.0f by default (so that only the completely transparent parts are clipped, but the user can modify it with values between 0 and 1.

The transparent part is depth read not equal because we need to reject samples based on depth test, so every part of the texture gets discarded which was rendered in the opaque pass. Optionally, there could be an additional clip(alpha - 1.0/255.0) to try to early out on the completely transparent parts. The blending equation should be color  = ( srcA x srcCol ) + ( invSrcA x destCol ) , so you shouldn't be getting white on the plants as you say. You should be getting something like the attached image. You could notice sorting artifacts where there is a lot of overlap, but that is not so obvious. Instead you get very nice soft edges on distant silhouettes for example, see the part where there is sky at the background. Anyway, this is getting off-topic. :)

 

grass.png

Ok I didn't looked into this, but it actually makes really sense :D 

Alpha-to-Coverage:

Clipboard01.png.7b0acaf751590df8b0027f399254ab36.png

Not so good "alpha blending":

Clipboard02.png.d3e1af8fbd4e70254c10d6a92f657d1e.png

I must remove all the opaque fragments when alpha blending. (This will increase the number of shaders by 2).

8 minutes ago, turanszkij said:

The MSAA resolve shader is just sampling all your subsamples of the MSAA texture and averaging them. Now, DX11 provides a built in function for this, but you want to avoid it and write your own if you have a HDR pipeline with tonemap - average - inversetonemap.

Ah, in order to get rid of of the multi-sample texture before post-processing?

Interesting, the MSAA and alpha-to-coverage could still be of some use for forward. Though with all the post-processing, I clearly need to have a non-multi-sampled back buffer.

🧙

11 minutes ago, turanszkij said:

Where AlphaTestThreshold is 1.0f / 255.0f by default (so that only the completely transparent parts are clipped, but the user can modify it with values between 0 and 1.

For my shadow maps, I use a value of 0.8f in the presence of transparent geometry :o

🧙

6 minutes ago, matt77hias said:

For my shadow maps, I use a value of 0.8f in the presence of transparent geometry :o

That is perfectly fine, just less conservative. I used something like 0.75 hardcoded for some time, now it can be tweaked. :)

22 minutes ago, turanszkij said:

color  = ( srcA x srcCol ) + ( invSrcA x destCol )

Hmm. I remember originally to use some blends of the DirectXTK, though their naming wasn't very convincing.

Opaque Blend: (source × 1) + (destination × 0) = source

Alpha Blend: (source × 1) + (destination × (1 - source.alpha))

Additive Blend:(source × source.alpha) + (destination × 1)

Non-premultiplied Blend: (source × source.alpha) + (destination × (1 - source.alpha))

The one you propose seems more like alpha blending :D

Opaque Blend: (source × 1) + (destination × 0) = source

Alpha Blend: (source × source.alpha) + (destination × (1 - source.alpha))

Additive Blend:(source × 1) + (destination × 1)

Non-premultiplied Blend: nvm

 

🧙

2 hours ago, turanszkij said:

The blending equation should be color  = ( srcA x srcCol ) + ( invSrcA x destCol )

I refactored all my blend equations.

Alpha blending:

image.png.01a0ea67d44a7c62f96a06217f65a110.png

I used LESS_EQUAL in all cases, never rendered any model twice and did not use alpha testing.

  1. Render opaque non-light interacting models (no blending)
  2. Render opaque light interacting models (no blending)
  3. Render transparent light non-interacting models (alpha blending)
  4. Render transparent light interacting models (alpha blending)

My transparent models are those which use (A instead of X in DXGI_FORMAT) the alpha channel in their base color texture.

 

Thanks for explicitizing the blend equation.

 

🧙

This topic is closed to new replies.

Advertisement