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?

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?

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: https://jsfiddle.net/kbgxhodn/
Renderer with sRGBEncoding: https://jsfiddle.net/n80zcu9a/

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 );"

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

Is there any reason NOT to do this?

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!

1 Like