Create your own post processing shader with React-Three-Fiber, useFBO and Drei’s shaderMaterial with ease 👌

Take a look at this cool impact. It is only a fragment shader with the next operate: colour = texture2D(uScene, uv + vec2(sin(iTime + uv.x * 15.0) * iDistortion, sin(iTime + uv.y * 15.0) * iDistortion)).rgb;


It is only a primary picture texture, however we’ll show a complete scene as texture onto the shader materials. Stick round, it is gonna be enjoyable!



What is that this?

Each WebGL scene, 3D or 2D, will get displayed on a display. So all the things that could be a 3D scene will get transformed into one thing 2D. More often than not, that is finished by the render engine. However we will draw the scene on to a mesh as a texture, and movie it with a orthographic digital camera. That means we will mess around with the feel through fragment shaders. That is tremendous performant and provides a cool impact to a easy scene. It provides cool waves to your scene, and you’ll even change each single worth. For instance improve the distortion the sooner the person scrolls, change easing features… you get the concept.

In a plain three.js scene I normally use this file supplied by Luruke:

With this file you possibly can “redirect” your renderer into PostFX.js. I simply threw the file inside some random three.js vanilla sandbox and that is it!

fork it and use as a template on your questions or experiments.

favicon
codesandbox.io

With React-Three-Fiber it turns into considerably tougher, however we’ll undergo all the things. Pmndrs has an enormous library of parts that work very properly out of the field.

Let’s begin with a primary setup.

devto 1 by eriksachse utilizing @react-three/drei, @react-three/fiber, @varieties/three, lamina, react, react-dom, react-scripts, three

favicon
codesandbox.io

Now we want useFBO to show a scene onto a texture. I used Drei’s storybook to rapidly mesh up the scene.

devto 2 by eriksachse utilizing @react-three/drei, @react-three/fiber, @varieties/three, babel-plugin-glsl, lamina, react, react-dom, react-scripts, three

favicon
codesandbox.io

Image description

useFBO alone would not work with shaders, or if, then I do not know how you can manipulate that. So what we’ve got to do is show the scene as texture onto a shaderMaterial. We will ship the feel as uniform. You might additionally ship movies and pictures to the shader the identical means.

With this snippet we’ve got two uniforms, time and texture. Time will likely be up to date through useRef and useFrame, that means we solely “re-render” the worth as ref, which will not re-render all the part.
The vertex shader is giving the fragment shader the proper coordination of the mesh, so we do not want decision or something. Remember that is simply primary C++ (Or was it C#?) and I hope this snippet is not overwhelming you.

Change the <meshBasicMaterial map={goal.texture} /> with <waveShaderMaterial ref={shader} uTexture={goal.texture} /> and add the shader ref. An entire setup is correct right here:

devto 3 by eriksachse utilizing @react-three/drei, @react-three/fiber, babel-plugin-glsl, lamina, r3f-perf, react, react-dom, react-scripts, three

favicon
codesandbox.io

If CSB is throwing errors, simply obtain the Repo and set up it regionally. With the shader ref we will replace the time worth for additional shading magic 🪄



Okayyyy

Let’s add the magic into the fragment shader.
Create a brand new vec3:
vec3 colour = vec3(vUv, 1.0);

Fragment shader to distort the scene:
colour = texture2D(uTexture, vUv + vec2(sin(uTime + vUv.x * 15.0) * 0.2, sin(uTime + vUv.y * 15.0) * 0.02)).rgb;

Change gl_FragColor = vec4(texture, 1.0); with
vec3 texture = texture2D(uTexture, vUv).rgb;
And it ought to show this:

Now all we’ve got to do is do away with the Controls and mesh the mesh as much as the scale of the display.

If you’re finished, preserve experimenting with totally different values. Change sin with tan, add extra dynamic values, and so forth.
Hope this cluster tutorial helped somebody 👍

Add a Comment

Your email address will not be published. Required fields are marked *