Skip to content

Instantly share code, notes, and snippets.

@RenaudRohlinger
Last active December 31, 2022 21:40
Show Gist options
  • Save RenaudRohlinger/bd5d15316a04d04380e93f10401c40e7 to your computer and use it in GitHub Desktop.
Save RenaudRohlinger/bd5d15316a04d04380e93f10401c40e7 to your computer and use it in GitHub Desktop.
usePostProcess.jsx
import { useFrame, useThree } from '@react-three/fiber'
import { useEffect, useMemo } from 'react'
import * as THREE from 'three'
function getFullscreenTriangle() {
const geometry = new THREE.BufferGeometry()
const vertices = new Float32Array([-1, -1, 3, -1, -1, 3])
const uvs = new Float32Array([0, 0, 2, 0, 0, 2])
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 2))
geometry.setAttribute('uv', new THREE.BufferAttribute(uvs, 2))
return geometry
}
const usePostProcess = () => {
const [{ dpr }, size] = useThree((s) => [s.viewport, s.size])
const [screen, screenCamera, screenScene, renderTarget] = useMemo(() => {
let screenScene = new THREE.Scene()
const screenCamera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1)
const screen = new THREE.Mesh(getFullscreenTriangle())
screen.frustumCulled = false
screenScene.add(screen)
const renderTarget = new THREE.WebGLRenderTarget(512, 512, { samples: 4 })
renderTarget.depthTexture = new THREE.DepthTexture() // fix depth issues
screen.material = new THREE.RawShaderMaterial({
uniforms: {
diffuse: { value: null },
},
vertexShader: /* glsl */ `
precision highp float;
in vec3 position;
in vec2 uv;
out vec2 vUv;
void main() {
vUv = uv;
gl_Position = vec4( position, 1.0 );
}
`,
fragmentShader: /* glsl */ `
precision highp float;
out highp vec4 pc_fragColor;
uniform sampler2D diffuse;
in vec2 vUv;
void main() {
pc_fragColor = texture(diffuse, vUv);
}
`,
glslVersion: THREE.GLSL3,
})
screen.material.uniforms.diffuse.value = renderTarget.texture
return [screen, screenCamera, screenScene, renderTarget]
}, [])
useEffect(() => {
const { width, height } = size
const { w, h } = {
w: width * dpr,
h: height * dpr,
}
renderTarget.setSize(w, h)
}, [dpr, size, renderTarget])
useFrame(({ scene, camera, gl }) => {
gl.setRenderTarget(renderTarget)
gl.render(scene, camera)
gl.setRenderTarget(null)
gl.render(screenScene, screenCamera)
}, 1)
return null
}
export default usePostProcess
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment