In Three.js, it seems that if you add an empty EffectsComposer, your shaderMaterials unintentionally get brighter and look blown out.
https://codesandbox.io/s/effects-composer-shader-conflict-mysyn
It seems adding a composer also enables color space conversion. To fix the issues, you have to do a couple of things:
encoding
property of your texture to sRGBEncoding
three.js
function mapTexelToLinear()
to convert texels to linear color space#include <encodings_fragment>
shader chunk to your code (not necessary to fix the issue but important if you use no post processing but change the output encoding of the renderer).ShaderMaterial.map
so the renderer can configure mapTexelToLinear()
with the correct code.import './styles.css';
import { TextureLoader, ShaderMaterial, sRGBEncoding } from 'three';
import { useMemo } from 'react';
import { EffectComposer } from '@react-three/postprocessing';
export default function App() {
const texture = new TextureLoader().load('crate.gif');
texture.encoding = sRGBEncoding;
const shaderMaterial = useMemo(
() =>
new ShaderMaterial({
fragmentShader: `
uniform sampler2D u_Txt1;
varying vec2 vUv;
void main() {
gl_FragColor = mapTexelToLinear( texture2D(u_Txt1, vUv) );
#include <encodings_fragment>
}`,
uniforms: {
u_Txt1: { value: texture }
},
vertexShader: `#include <common>
varying vec2 vUv;
void main () {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}`
}),
[texture]
);
shaderMaterial.map = texture;
return (
<>
<mesh name="screen" scale={[10, 10, 1]} material={shaderMaterial}>
{/* <meshBasicMaterial map={texture} color={0xffffff} /> */}
<planeBufferGeometry args={[1, 1]} />
</mesh>
<EffectComposer />
</>
);
}