我想使用 Three.js 和 @react- Three/Fiber 将着色器从 Shadertoy 移植到我的 React-Vite 应用程序。 正是这个着色器; https://www.shadertoy.com/view/DlySDD 我用谷歌搜索了很长时间,但没有找到确切的答案。 Stack Overflow 上有一些关于移植 Shadertoy 着色器的帖子,但他们的示例着色器有点不同。 当我尝试移植它时,遇到了问题。我想我不了解 BufferShader。 下面我附上了我的代码片段。请检查并告诉我可能出了什么问题。
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;
我制作了包含Shader的React组件,但编译时出现错误。
这是错误日志: 在此输入图片描述
并且我将FragmentShader放入uniform的iChannel0中,但我认为这是不正确的,甚至是愚蠢的。
有什么想法吗?