Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

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?

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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);
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading