Tone mapping change toneMapping type

Hi!

I using tone mapping in react-three-fiber, I wonder if is possible to access the tonemapping trypes:

THREE.NoToneMapping,
Linear: THREE.LinearToneMapping,
Reinhard: THREE.ReinhardToneMapping,
Cineon: THREE.CineonToneMapping,
ACESFilmic: THREE.ACESFilmicToneMapping,

@drcmda

At the moment, R3F’s Canvas component doesn’t expose these options. You’ll have to access THREE.WebGLRenderer directly and set them. Perhaps there’s a more elegant way, but one option would be:

function ToneMapping() {
  const { gl, scene } = useThree(({ gl, scene }) => ({ gl, scene }));
  useEffect(() => {
    gl.toneMapping = THREE.ACESFilmicToneMapping;
    gl.toneMappingExposure = 1.5;
    scene.traverse((object) => {
      if (object.material) {
        object.material.needsUpdate = true;
      }
    });
  }, [gl, scene]);
  return <></>;
}

export default function App() {
  return (
    <div className="App">
      <Canvas>
        <ToneMapping />o
        <mesh>
          <sphereBufferGeometry />
          <meshPhongMaterial />
        </mesh>
        <ambientLight args={[0xff0000]} intensity={0.1} />
        <directionalLight position={[0, 0, 5]} intensity={0.5} />
      </Canvas>
    </div>
  );
}
1 Like

@drcmda FWIW I suggested the following property names to the Threlte team, both for supporting other tone mapping methods, and to support wide-gamut display output in the future. Possibly worth considering in a future major release of R3F:

<Canvas 
  colorSpace={"srgb" | THREE.SRGBColorSpace | ...}
  toneMapping={THREE.ACESFilmicToneMapping}>
</Canvas>

gl is defined like this

type GLProps =
  | Renderer
  | ((canvas: Canvas) => Renderer)
  | Partial<Properties<THREE.WebGLRenderer> | THREE.WebGLRendererParameters>
  | undefined

that means it can accept everything the running instance will take, not just ctor args. this runs before render, so no needsUpdate … needed. :slight_smile:

<Canvas gl={{ 
  outputEncoding: THREE.sRGBEncoding,
  toneMapping: THREE.ACESFilmicToneMapping
}}

also possible

<Canvas onCreated={(state) => {
  state.gl.outputEncoding = THREE.sRGBEncoding,
  state.gl.toneMapping = THREE.ACESFilmicToneMapping

we could add better shortcuts in v9 though. “shadows” already uses strings to set the shadow map quickly, why not do it for encoding and tonemapping.

2 Likes