将着色器从shadertoy移植到react vite应用程序时遇到问题

问题描述 投票:0回答:1

我想使用 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中,但我认为这是不正确的,甚至是愚蠢的。

有什么想法吗?

reactjs three.js vite react-three-fiber shadertoy
1个回答
0
投票

如果您阅读错误消息,您可以看到

texture
函数未定义。

这是因为 ShaderToy 默认在 OpenGL ES 中。 对于

three.js
着色器默认位于
GLSL1

默认函数的命名差异不大。

texture
在旧版本中将是
texture2

或者,如果您想使用与

OpenGL ES
等效的
three.js
更新版本,您可以将材质版本设置为
THREE.GLSL3
材质常量页尾

© www.soinside.com 2019 - 2024. All rights reserved.