It seems adding a composer also enables color space conversion. To fix the issues, you have to do a couple of things:
- Set the
encoding
property of your texture to sRGBEncoding
- Use the
three.js
function mapTexelToLinear()
to convert texels to linear color space
- For consistency, add the
#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).
- Assign the texture to
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 />
</>
);
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…