How to resolve a shader error in a React with react-three-fiber when using a custom shader to create a hover state for an image component?

Advertisements

I am trying to create an image component with a hover state using shaders with react-three-fiber.

The shader was originally created by TheFrost and can be found at https://codepen.io/frost084/full/OKZNRm.

Unfortunately, I come across an error that I don’t understand.
Error:

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

The Image Component code:

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;

Besides the error my website works fine, only the image is not rendered. I have confirmed that the image is successfully passed through props. However, the image is not being rendered on the canvas. The canvas is rendering correctly with a pink background.

How to resolve this shader error?

>Solution :

The name of the texture sampler uniform can’t be texture, because texture is the name of built-in function in GLSL ES 3.00. I suggest to use tDiffuse as it is common in threejs.

Change setting of the uniform variable:

uniforms-texture-value={imgTexture}

uniforms-tDiffuse-value={imgTexture}

Change the fragment shader:

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);
}

Leave a ReplyCancel reply