Last active
December 31, 2022 21:40
-
-
Save RenaudRohlinger/bd5d15316a04d04380e93f10401c40e7 to your computer and use it in GitHub Desktop.
usePostProcess.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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