sRGB encoding as a postprocess pass

I found out that setting renderer.outputEncoding = THREE.sRGBEncoding doesn’t work when using postprocessing #18451. I’ve been told I need to do the encoding as a postprocess pass but I’m not sure how to do that. Can somebody point me in the right direction or give me some sample code I can use for reference?

1 Like

Turns out they have a gamma correction shader in https://threejs.org/examples/js/shaders.
Create the pass like this
const gammaCorrectionPass = new THREE.ShaderPass(THREE.GammaCorrectionShader)
and add it as the final pass
composer.addPass(gammaCorrectionPass)
If you set renderer.gammaFactor = 2.2 it simulates sRGBEncoding or so I’ve been told

Is there anything else I need or is this enough?

2 Likes

The gamma correction pass fudges the colors a bit. Anybody know how to fix this?

Screenshot from 2020-01-22 17-16-40

Not really, it’s fairly close but not exactly the same. What we need is an sRGBPass I guess.

It’s not clear from your screenshot what you mean. How are they fudged?

The gradients are harsh. The same model without postprocessing looks much smoother up close.

fudging-outlined
Screenshot from 2020-01-22 17-47-39

Ah yeah, I couldn’t see that on my phone screen earlier, but it’s obvious now.

Can you try @Mugen87’s suggestion in this thread?

Effect Composer Gamma Output Difference

1 Like

That works. Was a merge request made for this?

The gamma correction pass makes the background color lighter. This doesn’t happen with renderer.outputEncoding = THREE.sRGBEncoding. Is anyone working on a sRGBEncoding pass? In the meantime is there a way to exclude the background and other objects from the gamma correction pass?

You’re right. The difference is pretty noticeable.

Composer with gamma correction pass: three.js dev template - module - JSFiddle - Code Playground
Renderer with sRGBEncoding: three.js dev template - module - JSFiddle - Code Playground

I think I’m going to have to give up on GammaCorrectionShader as a workaround.

So back to my original question. How do I mimic the result of https://jsfiddle.net/n80zcu9a/ when using EffectComposer to render the scene?

I don’t think the difference should be that noticeable. But in any case, you can just write your own sRGBCorrectionPass.

Use the gammaCorrectionPass as a template:

And you’ll find the LinearTosRGB function here:

You don’t need to redefine the function in the pass, since the pass has access to the function defined in the core. Simply replace LinearToGamma with LinearTosRGB in the GammaCorrectionPass.

2 Likes

Okay but the background color still changes. Is that the intended behavior?

composer.renderTarget1.texture.encoding = THREE.sRGBEncoding;
composer.renderTarget2.texture.encoding = THREE.sRGBEncoding;

4 Likes

Performance-wise I’m not sure about this if you have many passes, but instead of adding a pass, I just changed the last line of my CopyShader from

"	gl_FragColor = opacity * texel;"

to

"	gl_FragColor = LinearTosRGB( opacity * texel );"
1 Like

Oh my lord you absolute genius, this nailed it for me :smiley:

Is there any reason NOT to do this?

1 Like

If the render target encoding is set to sRGB then postprocessing effects will be operating in sRGB rather than Linear color which could lead to some incorrect colors in the result. With some passes it may not matter and in cases where it does it may not be significant. If the the result looks good to you I say go ahead and use sRGB!

2 Likes

From the time this question was asked, it looks like GammaCorrectionShader was improved. But it still doesn’t resolve the issue in these fiddles. The issue seems to occur when the opacity is set. If you set the opacity to 1 in both fiddles, things are fine. It’s looking like the opacity being set up front and then corrected in a pass doesn’t work well. Any idea on how to resolve this problem?

1 Like