How to implement postprocessing in React with React three fiber using EffectComposer and Passes like OutlinePass from the three.js addons

Struggling with the R3F -postprocessing library, I decided to turn to raw threejs classes:

After delving into tutorials on extending third party libraries for R3F, I was able to configure the renderPass and outlinePass using TypeScript. Check out this helpful link:

import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer";
  import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass";
  import { OutlinePass } from "three/examples/jsm/postprocessing/OutlinePass";
  extend({ RenderPass, EffectComposer, OutlinePass });
  declare global {
    namespace JSX {
      interface IntrinsicElements {
        outlinePass: Node<OutlinePass, typeof OutlinePass>;
      }
    }
  }

  export default function GaussianViewer({
    return (
      /**
       * It creates a scene, a camera & Raycaster.
       * It also sets up the webGlrenderer and the animationLoop.
       */
      <Canvas
        gl={{ localClippingEnabled: true }}
        onClick={onCanvasClickHandler}
      >
        <ViewerContent />
      </Canvas>
    );
  })

  function ViewerContent(){
    const { camera, gl, scene, raycaster, get, set } =
      useThree();
    return (
          <effectComposer args={[gl]}>
            <renderPass
              attach="passes"
              args={[scene, camera]}
            />
            <outlinePass attach="passes" />
            {/* <outlinePass /> */}
          </effectComposer>
  )
  }
  

However, while successfully setting up the effect composer and passes, a new issue arose as seen in the picture: https://i.sstatic.net/Jf99dVN2.png Do you think it's better to stick with the R3F -postprocessing library despite these issues with integrating raw threejs add-ons? Or is there a way to resolve this problem?

Answer №1

I encountered a similar problem with the @react-three/postprocessing library not functioning properly in my current project, most likely due to compatibility issues with NextJS builds.

After finding inspiration from this post, I developed a simple component that simplifies the creation of a series of post-processing effects using three-js within react-three-fiber:

import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass';
import { DotScreenPass } from 'three/examples/jsm/postprocessing/DotScreenPass';
import { RenderPixelatedPass } from 'three/examples/jsm/postprocessing/RenderPixelatedPass.js';
import { OutlinePass } from 'three/examples/jsm/postprocessing/OutlinePass';
import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass';
import { Canvas, extend, Object3DNode, useFrame, useThree } from '@react-three/fiber';
import { Vector2 } from 'three';
import { useRef, useEffect } from 'react';

extend({
  RenderPass,
  EffectComposer,
  OutlinePass,
  DotScreenPass,
  RenderPixelatedPass,
  UnrealBloomPass,
});

declare global {
  namespace JSX {
    interface IntrinsicElements {
      outlinePass: Object3DNode<OutlinePass, typeof OutlinePass>;
      dotScreenPass: Object3DNode<DotScreenPass, typeof DotScreenPass>;
      renderPixelatedPass: Object3DNode<RenderPixelatedPass, typeof RenderPixelatedPass>;
      unrealBloomPass: Object3DNode<UnrealBloomPass, typeof UnrealBloomPass>;
    }
  }
}

// Toggle the passes you wish to include
export const ThreeEffects = () => {
  const { camera, gl, scene } = useThree();
  const composer = useRef<EffectComposer>();

  useEffect(() => {
    composer.current = new EffectComposer(gl);
    composer.current.addPass(new RenderPass(scene, camera));

    // Uncomment/comment the desired passes
    // const pixelatedPass = new RenderPixelatedPass(6, scene, camera);
    // composer.current.addPass(pixelatedPass);

    const bloomPass = new UnrealBloomPass(
      new Vector2(window.innerWidth, window.innerHeight),
      1.5,
      0.4,
      0.85
    );
    composer.current.addPass(bloomPass);

    // const dotScreenPass = new DotScreenPass(
    //   new Vector2(window.innerWidth, window.innerHeight),
    //   0.5,
    //   0.8
    // );
    // composer.current.addPass(dotScreenPass);

    // const outlinePass = new OutlinePass(new Vector2(window.innerWidth, window.innerHeight), scene, camera);
    // composer.current.addPass(outlinePass);

    // Adjust the composer size when the window dimensions change
    composer.current.setSize(window.innerWidth, window.innerHeight);
  }, [gl, scene, camera]);

  useFrame(() => {
    composer.current?.render();
  }, 1);

  return null;
};

https://gist.github.com/jelling/f2974011ae1dce107f7aba1406a7795b

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Angular Routing can be a powerful tool for managing multiple article posts in an efficient and organized way

I am in the process of building a website with Angular that features numerous articles. Whenever a user clicks on an article, I want it to navigate to a new URL using routing. To achieve this, I have created a new Article component and here is how my app- ...

Receive the most recent query in a Nuxt plugin following the completion of page loading

So, here's the issue - I have a plugin containing some functions that are supposed to update URL queries. However, every time I run $global.changePage(2) or $global.changeLimit(2), the console.log(query) outputs an empty object and doesn't show t ...

What is the best way to incorporate a @types module into a TypeScript file that is not already a module?

Setting the Stage: In the process of shifting a hefty ~3,000 line inline <script> from a web-page to a TypeScript file (PageScripts.ts) to be utilized by the page through <script src="PageScripts.js" defer></script>. This script entails ...

Issue: Unhandled promise rejection: BraintreeError: The 'authorization' parameter is mandatory for creating a client

I'm currently working on integrating Braintree using Angular with asp.net core. However, I've encountered an issue that I can't seem to solve. I'm following this article. The version of Angular I'm using is 14, and I have replicate ...

Utilizing Video Content as a Texture in three.js

I'm currently experimenting with Three.js and found this interesting example: In my modified version of the example, I decided to use 5 images and a video file (.ogv format) as textures instead of the original 6 images. The code excerpt below showcas ...

Error: JavaScript object array failing to import properly

In my code, I have an array of objects named trace which is defined as follows: export const trace: IStackTrace[] = [ { ordered_globals: ["c"], stdout: "", func_name: "<module>", stack_to_render: [], globals: { c: ["REF" ...

Issue with deprecated TypeORM connection and isConnected functions

import { Module } from '@nestjs/common'; import { Connection } from '../../node_modules/typeorm/connection/Connection'; import { TypeOrmModule } from '@nestjs/typeorm'; @Module({ imports: [TypeOrmModule.forRoot()], exports ...

What is the best way to apply a texture in react-three-fiber?

const texture = useLoader(THREE.TextureLoader, 'assets/texture.png') return ( <mesh position={[-0.00008, -0.00008, -1.26303]}> {/*Alioth*/} <sphereBufferGeometry attach="geometry" args={[1.26068]} > ...

The term "containerName" in SymbolInformation is utilized to represent the hierarchy of

In my quest to make the code outline feature work for a custom language, I have made progress in generating symbols and displaying functions in the outline view. However, my next challenge is to display variables under the respective function in the outlin ...

Error encountered with Angular version 11.2.6 or Typescript indicating TS2345 issue

Currently, I am stuck on an Angular tutorial that includes some code, but unfortunately, I am encountering an error that I haven't been able to troubleshoot. In all instances within my code where dish or getDish are present, they are stored as strings ...

Is it possible to eliminate additional properties from an object using "as" in Typescript?

I am looking for a way to send an object through JSON that implements an interface, but also contains additional properties that I do not want to include. How can I filter out everything except the interface properties so that only a pure object is sent? ...

Insert a new item into a current array using Typescript and Angular

-This is my curated list- export const FORMULARLIST: formular[] = [ { id: 1, name: 'Jane Doe', mobileNumber: 987654, secondMobileNumber: 456789, email: '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e1bcc0d9ec ...

What is the best way to manage multiple tsconfig files for an Angular application?

Our customer has requested that we have two separate applications (with navigation from appA to appB) in one single package for easier deployment. However, we face a challenge as one section is coded in typescript with jQuery and the other is built in Ang ...

Incorporating external plugins with jQuery in Angular 2

My experience with Angular 2 and jQuery has been quite positive. I am eager to incorporate external libraries such as masonry-layout, but I have encountered a frustrating issue: When trying to use jQuery(...).masonry(), I receive an error stating that i ...

Generate user-customized UI components from uploaded templates in real-time

Summary: Seeking a solution to dynamically generate UI pages using user-provided templates that can be utilized for both front-end and back-end development across various use cases. Ensuring the summary is at the top, I am uncertain if this question has b ...

Explicit final argument in TypeScript

Is it feasible to define a function in TypeScript 2.7.2 and above with variable parameters, but ensuring that the final parameter has a specific type? I am attempting to craft an ambient TypeScript declaration for a JavaScript library that utilizes functi ...

There was an error in parsing the module: an unexpected token was encountered during the rendering

Recently, I've been working on configuring React with Typescript (for type checking), Babel for code transpilation, Jest for testing, ESLint for code checking, and a few other tools. You can find all the necessary files in the repository linked below. ...

Encountering a TSLint interface error when adding a value to a nested array

Currently, I am transforming responses into an array of Months and Days, with each Day containing an array of numbers. The logic itself is functioning properly, however, I am encountering a tslint error specifically when attempting to push a value into the ...

What is the best way to search for and sort through the data in this particular scenario?

This code snippet is specifically created for extracting and comparing data from the Google spreadsheet shown in the images. exports.processosjudiciais = functions.https.onRequest(async (request, response): Promise<any> => { const jwtClient = ...

Error: Failed to retrieve the name property of an undefined value within the Array.forEach method

Upon pressing the button to display the task pane, I encountered an error message in the console window that reads: "Uncaught (in promise) TypeError: Cannot read property 'name' of undefined". This error persists and I am unable to resolve or com ...