EffectComposer doesnt work with View in React Three Fiber

Hey you guys, I will try to be direct.

I am creating a react three fiber application which will need multiple View (though I have only one for now), I saw it is better for performance than multiple canvases.

The problem is that I cant make postprocessing working correctly along with View, while without Views it works perfectly…

Here is the Canvas component

import { Canvas } from '@react-three/fiber';
import React from 'react';
import { BaseballTest } from './BaseballTest';
import { Environment, Sky, View, Preload } from '@react-three/drei';
import { BaseballField } from './BaseballAnimations/BaseballField';
import EffectsComponent from './components/EffectsComponent/EffectsComponent';

function App() {
  return (
    <div className='relative h-full w-full'>
      <div className='w-full h-screen bg-red-700'></div>

      <View className='absolute w-full h-screen z-[999]'>
        <mesh position={[500, 100, 2000]}>
          <sphereGeometry args={[200, 200, 200]} />
          <meshStandardMaterial
            color={'#f0dc2b'}
            emissive={'#e4d125'}
            emissiveIntensity={4}
          />
        </mesh>

        <Sky />

        <Environment
          files='./sky.jpg'
          background
          backgroundIntensity={1}
          environmentIntensity={2}
        />

        <BaseballTest />
        <BaseballField />
        <EffectsComponent />
      </View>

      <Canvas
        eventSource={document.getElementById('root')}
        style={{
          width: '100%',
          height: '100vh',
          position: 'fixed',
          top: 0,
          left: 0,
        }}
        camera={{
          fov: 40,
          position: [-1.385, 13.642, -107.34],
          rotation: [3.006, -0.013, -3.123],
        }}
        dpr={window.devicePixelRatio}
        shadows={true}
      >
        <View.Port />
        <Preload all />
      </Canvas>
      
    </div>
  );
}

export default App;

and here is the EffectComposer component with bloom and effects:

import React from 'react';
import {
  ToneMapping,
  Bloom,
  EffectComposer,
  Vignette,
} from '@react-three/postprocessing';
import { ToneMappingMode, VignetteEffect } from 'postprocessing';
import { useFrame } from '@react-three/fiber';
import { damp } from 'maath/easing';

const EffectsComponent = () => {
  const vignetteRef = React.useRef<null | typeof VignetteEffect>(null);

  useFrame((state, delta) => {
    if (vignetteRef.current) {
      damp(vignetteRef.current, 'darkness', 0, 6, delta);
    }
  });

  return (
    <EffectComposer>
      <Bloom
        mipmapBlur
        luminanceSmoothing={0.1}
        luminanceThreshold={1.1}
        intensity={3}
      />
      <Vignette eskil={false} offset={0.1} darkness={1.1} ref={vignetteRef} />
      <ToneMapping mode={ToneMappingMode.NEUTRAL} />
    </EffectComposer>
  );
};

export default EffectsComponent;

Hi. Great question!
It sounds like you’re diving into the exciting world of 3D graphics with React Three Fiber, and I totally understand how tricky it can be to get postprocessing to work seamlessly with multiple views.
By structuring your application with custom view components and properly managing the postprocessing effects, you should be able to achieve the desired results. Remember, experimenting with different configurations can lead to the best performance and visual quality.
Let’s discuss more details via chatting.

Hi there, do you know a solution for the presented problem?

Hi, How can i help you?

The problem is that I can’t make the bloom effect working with View. I don’t know if the reason is because of the order that the EffectComposer is structured because even without View I had to place ToneMapping below everything so it could work, but as soon as I put the View component it doesnt matter the order I try it simply doesnt work.

The issue arises from the way the View component interacts with the rendering pipeline in React Three Fiber. The View component creates a separate rendering context, which can lead to complications with post-processing effects that rely on a single rendering context. This separation can prevent the effects from being applied correctly.
To resolve the issue, we need to ensure that the post-processing effects are applied within the same rendering context as the View. This can be achieved by moving the EffectsComponent inside the Canvas and ensuring it is rendered after the View components.

Oh, thank you for the answer, I had forgot to mention that I already tried placing the EffectsComponent inside Canvas and after the <View.Port /> as well but it got me a blank screen completely. I will send some pics to show the desired result and what I am getting

I don’t have telegram I am sorry, but here are the pics.

This is the desired result:
desired

and this is the one I am getting:

undesired

It feels that at this point you might as well just ask chatgpt directly. I don’t understand why people do this relay thing :confused:

Even chat gpt can’t help me in this, it gives many wrong answers, I ask it how can I place multiple View in the same render as the EffectComposer and it says I should make use of a “camera” property that is in View whereas there is no camera property there, aside from the many others wrong answers it gives.

I am almost abandoning my current approach and adding multiple Canvas that will be bad for performance but I cant make it working the way it is now with View.

Also I don’t see anyone else that had this issue and I dig deep to find in forums if anyone had a similar issue but no one have, I don’t know if there is an alternative for View though

I tried, it doesn’t work for me either.
Maybe use multiple canvases if it means just getting on with your project.
Come back to “doing it the proper way” later.
I’ve been using muiltiple canvases in vanilla for years, and it still works.

2 Likes

Thank you for the answer @seanwasere , I will do that. My only worry was hurting the performance, but if it is a common practice then I think I wont lose my sleep over it. Maybe I will only go with a github issue later for the devs know about this and move on with my project. Thank you really!

Does it hurt the performance? How much?

It’s not common practice, there are plenty of developer colleagues who will jump up and shout at you publicly in the office if you use more than 1 canvas.

But I do it, because I don’t care.

I’ve seen some other developers and asked gpt as well and they say it is bad for performance, maybe I should do some metrics later and try it out for seeing the difference as I didnt do it yet, but as in my project I really need PostProcessing effects and multiple scenes then I can’t go with View so your suggestion is what I will follow for the time being.

I have also encountered a similar situation. If you don’t have many Views, may be try create a separate Fbo for each View . And if you want the Views to have the same EffectComposer. Maybe you should use an Ortho camera, and track Dom information, I still haven’t found an effective solution for this problem. Hope there will be a solution

Here is a 1 canvas approach using R3F.
It uses scissor test to split the canvas into 4 sections with their own effect composer.

3 Likes