Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

three.js gamma correction and custom shaders

Tags:

three.js

webgl

I am not quite sure how THREE.js handles gamma correction internally. It seems that to enable it the only thing you have to do is to set the following flags on the renderer object:

gammaInput = true; gammaOutput = true;

However when you are writing your own custom shaders and fetching a color from a texture, do you still have to convert the color into linear space or does THREE.js transforms the texture before uploading it to the GPU (when gammaInput is set to true)?

Similarly, when determining the final color in your shader, do you have to convert it to gamma space or is there a post process effect that THREE.js automatically applies (when the gammaOutput is set to true) ?

thanks

like image 473
user3138911 Avatar asked Oct 21 '22 15:10

user3138911


1 Answers

Three.js will not map your texture to another space before uploading to the GPU. Everything is done in-place in the shader using chunks.

To convert input value to linear:

As an example, take a look at how Three.js handles the map property here. You will basically see this line:

texelColor = mapTexelToLinear( texelColor );

And mapTexelToLinear is basically created in the WebGLProgram.js file.

You get the idea.

To sum up, you can basically include this chunk at the top of your shader:

#include <encodings_pars_fragment>

And then you need to decode your texel according to the space your texture is in. Example if you use an sRGB texture:

vec4 color = sRGBToLinear(texel);

To output a gamma corrected value:

You also need to include encodings_pars_fragment at the top of your shader:

#include <encodings_pars_fragment>

You then need to include the chunk that modifies the frag color automatically. Take a look at this line.

By including the chunk encodings_fragment at the end of your custom shader, it will automatically map your fragment according to the parameters you used on the THREE.WebGLRenderer.

To understand why this work, you can look at the encodings chunk, containing only:

gl_FragColor = linearToOutputTexel( gl_FragColor );

And then you can take a look at the WebGLProgram.js file to understand how the linearToOutputText function works. This works basically the same way as the texel decoding.

Hope this is useful!

like image 64
David Peicho Avatar answered Oct 23 '22 21:10

David Peicho