You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决react-three-fiber中自定义着色器hover状态的着色器错误

问题:React-Three-Fiber自定义着色器编译错误排查与修复

我尝试用react-three-fiber结合自定义着色器实现带hover状态的图片组件,着色器改编自TheFrost的Codepen项目。但出现着色器编译错误,片段着色器未编译,涉及texture函数调用、维度不匹配等问题。已确认图片props传递正常,但画布仅显示粉色背景,图片未渲染。相关错误日志与组件代码如下,求解决方法。

错误日志

REE.WebGLProgram: Shader Error 0 - VALIDATE_STATUS false

RAGMENT

Program Info Log: Fragment shader is not compiled.

ERROR: 0:106: 'texture' : function name expected
ERROR: 0:106: '=' : dimension mismatch
ERROR: 0:106: '=' : cannot convert from 'const mediump float' to 'highp 4-component vector of float'
ERROR: 0:111: 'texture' : function name expected
ERROR: 0:111: '=' : dimension mismatch
ERROR: 0:111: 'assign' : cannot convert from 'const mediump float' to 'highp 4-component vector of float'
ERROR: 0:113: 'texture' : function name expected
ERROR: 0:113: 'r' :  field selection requires structure, vector, or interface block on left hand side
ERROR: 0:114: 'texture' : function name expected
ERROR: 0:114: 'g' :  field selection requires structure, vector, or interface block on left hand side

 101:         float zoomLevel = .2;
  102:         float hoverLevel = exponentialInOut(min(1., (distance(vec2(.5), uv) * hover) + hover));
  103:         uv *= 1. - zoomLevel * hoverLevel;
  104:         uv += zoomLevel / 2. * hoverLevel;
  105:         uv = clamp(uv, 0., 1.);
> 106:         vec4 color = texture2D(texture, uv);
  107:         if(hoverLevel > 0.) {
  108:           hoverLevel = 1.-abs(hoverLevel-.5)*2.;
  109:           //Pixel displace
  110:           uv.y += color.r * hoverLevel * .05;
  111:           color = texture2D(texture, uv);
  112:           // RGBshift

组件代码

import { useState, useMemo } from 'react';
import { TextureLoader } from 'three';
import { Canvas } from '@react-three/fiber';
import { useSpring, animated, config } from '@react-spring/three';

import { HoverImageShader } from 'shader/HoverImageShader';

const AnimatedImage = ({ src, width = '100%', height = '100%' }) => {
  const [hovered, setHover] = useState(false);

  const imgTexture = useMemo(() => {
    const loader = new TextureLoader();
    return loader.load(src);
  }, [src]);

  const { hoverValue } = useSpring({
    hoverValue: hovered ? 1 : 0,
    config: config.molasses,
  });

  return (
    <Canvas
      pixelratio={window.devicePixelRatio || 1}
      style={{ background: 'pink', width, height }}
      camera={{ fov: 75, position: [0, 0, 7] }}
    >
      <animated.mesh
        onPointerOver={() => setHover(true)}
        onPointerOut={() => setHover(false)}
      >
        <planeBufferGeometry attach='geometry' args={[10.7, 10.7]} />
        <animated.shaderMaterial
          attach='material'
          transparent
          args={[HoverImageShader]}
          uniforms-texture-value={imgTexture}
          uniforms-hover-value={hoverValue}
        />
      </animated.mesh>
    </Canvas>
  );
};

export default AnimatedImage;

解决方案

1. 修复着色器变量命名冲突

错误核心原因是纹理uniform的命名texture与GLSL内置函数texture()重名,导致编译器无法识别函数调用。

  • 修改着色器中的uniform定义:将uniform sampler2D texture;改为uniform sampler2D uTexture;
  • 替换片段着色器中所有纹理采样代码:把texture2D(texture, uv)改成texture(uTexture, uv)(WebGL2中推荐使用texture()替代texture2D())

2. 确保自定义缓动函数存在

原着色器中的exponentialInOut是自定义函数,需要确保你的HoverImageShader中包含该函数的定义:

float exponentialInOut(float t) {
  return t == 0.0 || t == 1.0 
    ? t 
    : t < 0.5 
      ? +0.5 * pow(2.0, (20.0 * t) - 10.0) 
      : -0.5 * pow(2.0, 10.0 - (t * 20.0)) + 1.0;
}

3. 修正React-Three-Fiber的ShaderMaterial参数传递

animated.shaderMaterial的参数传递方式有误,需要用shader属性传入着色器对象,并通过uniforms对象传递参数,而不是旧的uniforms-xxx-value语法:

<animated.shaderMaterial
  attach='material'
  transparent
  shader={HoverImageShader}
  uniforms={{
    uTexture: { value: imgTexture },
    hover: { value: hoverValue }
  }}
/>

4. 纹理加载的额外处理(可选)

为避免纹理翻转问题,可以在加载纹理时设置:

const imgTexture = useMemo(() => {
  const loader = new TextureLoader();
  const texture = loader.load(src);
  texture.flipY = false; // 适配three.js的纹理坐标系
  return texture;
}, [src]);

完成以上修改后,着色器应该能正常编译,hover交互效果也能正确渲染。

内容的提问来源于stack exchange,提问作者Oliver

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 05:02:10