我正在尝试使用带有
react-three-fiber
的着色器创建具有悬停状态的图像组件。
着色器最初由 TheFrost 创建,可以在 https://codepen.io/frost084/full/OKZNRm.
不幸的是,我遇到了一个我不明白的错误。 错误:
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
o
Image组件代码:
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;
除了错误我的网站工作正常,只有图像没有呈现。我已经确认图像已成功通过道具。但是,图像未在画布上呈现。画布正确呈现粉红色背景。
如何解决这个着色器错误?
texture sampler uniform的名称不能是
texture
,因为texture
是GLSL ES 3.00中内置函数的名称。我建议使用tDiffuse
,因为它在threejs中很常见。
统一变量的更改设置:
uniforms-texture-value={imgTexture}
uniforms-tDiffuse-value={imgTexture}
更改片段着色器:
precision highp float;
uniform sampler2D tDiffuse;
uniform float imageAspectRatio;
uniform float aspectRatio;
uniform float opacity;
uniform float hover;
varying vec2 vUv;
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;
}
void main() {
vec2 uv = vUv;
// fix aspectRatio
float u = imageAspectRatio/aspectRatio;
if(imageAspectRatio > aspectRatio) {
u = 1. / u;
}
uv.y *= u;
uv.y -= (u)/2.-.5;
// hover effect
float zoomLevel = .2;
float hoverLevel = exponentialInOut(min(1., (distance(vec2(.5), uv) * hover) + hover));
uv *= 1. - zoomLevel * hoverLevel;
uv += zoomLevel / 2. * hoverLevel;
uv = clamp(uv, 0., 1.);
vec4 color = texture2D(tDiffuse, uv);
if(hoverLevel > 0.) {
hoverLevel = 1.-abs(hoverLevel-.5)*2.;
//Pixel displace
uv.y += color.r * hoverLevel * .05;
color = texture2D(tDiffuse, uv);
// RGBshift
color.r = texture2D(tDiffuse, uv+(hoverLevel)*0.01).r;
color.g = texture2D(tDiffuse, uv-(hoverLevel)*0.01).g;
}
gl_FragColor = mix(vec4(1.,1.,1.,opacity), color, opacity);
}