I want to port shader from shadertoy to my React-Vite app using Three.js and @react-three/fiber. Exactly this shader; https://www.shadertoy.com/view/DlySDD I surfed Google for a long time, but I couldn't find an exact answer. There are some posts on porting shadertoy shader on Stack Overflow, but their example shader is a bit different. As I was trying to port it, I got a problem. I think I don't get an idea of BufferShader. Below I attached my code snippet. Please check and give me an idea on what could be wrong.
import { Fragment, useRef, useMemo } from "react";
import * as THREE from "three";
import { Canvas, useFrame, useLoader, useThree } from "@react-three/fiber";
const vertexShader = `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;
const Buffer_A_Frag = `
uniform vec2 iResolution;
void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
// Normalized pixel coordinates (from 0 to 1)
vec2 uv = fragCoord/iResolution.xy;
// Time varying pixel color
vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));
// Output to screen
fragColor = vec4(col, 1.0);
}
void main() {
vec4 fragColor;
mainImage(fragColor, gl_FragCoord.xy);
gl_FragColor = fragColor;
}
`;
const fragmentShader = `
uniform sampler2D iChannel0;
uniform sampler2D iChannel1;
uniform sampler2D iChannel2;
uniform vec3 iResolution; // viewport resolution (in pixels)
uniform float iTime; // shader playback time (in seconds)
void mainImage(out vec4 color, vec2 coord)
{
//Resolution for scaling
vec3 res = iResolution,
//Compute ray direction ranging from -1 to 1 (aspect corrected, with +z forward)
dir = vec3(res.xy-coord*2.,res.x) / res.x,
//Sample position
pos;
//Use RG channels of last frame for the GB (brightened by /.7)
//This produces a simple chromatic aberration effect!
color = vec4(0, texture(iChannel0,coord/res.xy)/.7);
//Loop 100 times
for(float i = 0.; i<1e2; i++)
//Compute sample point along ray direction plus an arbitrary offset
//Starts at random point between 0 and 0.1 and increments 0.1 each step
pos = dir*(texture(iChannel2,coord/1e3).r+i)*.1 + 9.,
//Rotate about the y-axis
pos.xz *= mat2(cos(iTime*.1+asin(vec4(0,1,-1,0)))),
//Add sample point, decreasing intensity with each interation (down to 0)
color.r += (1e2-i) / 1e5 /
//Attenuate from the absolute distance to the noise + gyroid shape
abs(texture(iChannel1,pos*.1).r + dot(sin(pos),cos(pos.yzx)));
}
void main() {
vec4 fragColor;
mainImage(fragColor, gl_FragCoord.xy);
gl_FragColor = fragColor;
}
`;
const OceanShaderMesh = () => {
const materialRef = useRef(null);
const { size, gl } = useThree();
gl.setPixelRatio(1);
useFrame(({ clock }) => {
if (materialRef.current) {
const material = materialRef.current;
material.uniforms.iTime.value = clock.getElapsedTime();
material.uniforms.iResolution.value.set(size.width, size.height);
gl.setSize(size.width, size.height);
}
});
const uniforms = useMemo(() => {
return {
iTime: { value: 0 },
iResolution: { value: new THREE.Vector2(size.width, size.height) },
iChannel0: {
value: Buffer_A_Frag,
},
iChannel1: { value: useLoader(THREE.TextureLoader, "buffer1.png") },
iChannel2: {
value: useLoader(THREE.TextureLoader, "noise.png"),
},
};
}, []);
return (
<mesh scale={[size.width / size.height, 1, 1]}>
<planeGeometry args={[size.width, size.height]} />
<shaderMaterial
ref={materialRef}
uniforms={uniforms}
vertexShader={vertexShader}
fragmentShader={fragmentShader}
/>
</mesh>
);
};
const Background = () => (
<Fragment>
<Canvas
orthographic
camera={{ zoom: 100 }}
style={{
width: "100vw",
height: "100vh",
backgroundColor: "rgba(0, 0, 0, 0.5)",
}}
>
<OceanShaderMesh />
</Canvas>
</Fragment>
);
export default Background;
I made that React component which includes Shader, but it has errors in compiling.
Here is an error log: enter image description here
And I put FragmentShader into the iChannel0 of uniform, but I think it's not correct and even stupid.
Any idea?