question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Animating uniforms in ShaderMaterial

See original GitHub issue

Hey, I’m quite new to all this, but I thought this might be a good occasion to get more familiar with THREE. I’m trying to replicate this demo here using react-three-fiber. https://tympanus.net/Development/DistortionHoverEffect/

From the demo source the material is built and animated as below with GSAP (dispFactor value animates from 0 to 1):

var mat = new THREE.ShaderMaterial({
    uniforms: {
        effectFactor: { type: "f", value: intensity },
        dispFactor: { type: "f", value: 0.0 },
        texture: { type: "t", value: texture1 },
        texture2: { type: "t", value: texture2 },
        disp: { type: "t", value: disp }
    },

    vertexShader: vertex,
    fragmentShader: fragment,
    transparent: true,
    opacity: 1.0
});

// animation with GSAP
parent.addEventListener(evtIn, function(e) {
    TweenMax.to(mat.uniforms.dispFactor, speedIn, {
        value: 1,
        ease: easing
    });
});

I’ve tried to do the same with react-three-fiber and react-spring but nothing happens or nothing shows. Any idea what I’m doing wrong?

const [hovered, setHover] = useState(false)
const hover = useCallback(() => setHover(true), [])
const unhover = useCallback(() => setHover(false), [])
const { progress } = useSpring({ progress: hovered ? 1 : 0 })

return (
    <anim.mesh {...props} onHover={hover} onUnhover={unhover}>
      <planeBufferGeometry name="geometry" args={[3.8, 3.8]} />
      <anim.shaderMaterial
        name="material"
        uniforms={{
          effectFactor: { type: 'f', value: intensity },
          dispFactor: { type: 'f', value: progress },
          texture: { type: 't', value: texture1 },
          texture2: { type: 't', value: texture2 },
          disp: { type: 't', value: displacement }
        }}
        {...HoverShader}
        transparent
        opacity={1}
      />
    </anim.mesh>
);

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:13 (12 by maintainers)

github_iconTop GitHub Comments

1reaction
mysterybearcommented, Jan 7, 2022

@marceloavf this is what worked for me in some code from many months ago, maybe you can try writing your code in a similar way and see if it works? Here it is:

import { animated } from "@react-spring/three"
import { shaderMaterial } from "@react-three/drei"
import { extend } from "@react-three/fiber"
import glsl from "glslify"
import * as THREE from "three"
import fragmentShader from "./fragment.glsl"
import vertexShader from "./vertex.glsl"

const CanvasImageMaterial = shaderMaterial(
  {
    u_mode: 0,
    u_texture: new THREE.Texture(),
    u_border_color: new THREE.Color(),
    u_border_thickness: new THREE.Vector2(0, 0),
    u_inset: new THREE.Vector4(0, 0, 0, 0),
    u_handle_length: 0.5,
    u_scale: 1,
  },
  glsl(vertexShader),
  glsl(fragmentShader)
)

export type CanvasImageMaterialImpl = {
  u_mode?: { value: number }
  u_texture?: { value: THREE.Texture }
  u_border_color?: { value: THREE.Color }
  u_border_thickness?: { value: THREE.Vector2 }
  u_inset?: { value: THREE.Vector4 }
  u_handle_length?: { value: number }
  u_scale?: { value: number }
} & JSX.IntrinsicElements["shaderMaterial"]

extend({ CanvasImageMaterial })

declare global {
  namespace JSX {
    interface IntrinsicElements {
      canvasImageMaterial: CanvasImageMaterialImpl
    }
  }
}

export const AnimatedCanvasImageMaterial = animated(
  (props: CanvasImageMaterialImpl) => <canvasImageMaterial {...props} />
)

There’s also a blog post I wrote around the same time (hopefully not too out of date) on this topic https://bearjam.dev/blog/react-three-fiber-shaders-setup

1reaction
drcmdacommented, Mar 12, 2019

now it works: https://codesandbox.io/s/x37p4kk6p4

but that’s still weird. it should be able to pierce into the value, but for some reason it only works when i write the object around it, for which it needs to interpolate.

i’ll fix this tomorrow, then you will be able to just do: uniforms-xxxxx-value={animatedProp}

Read more comments on GitHub >

github_iconTop Results From Across the Web

Animating uniforms in ShaderMaterial · Issue #23 - GitHub
Hey, I'm quite new to all this, but I thought this might be a good occasion to get more familiar with THREE. I'm...
Read more >
Animating ThreeJS ShaderMaterial Uniforms - JSFiddle
The fiddle listings (Public, Private, Titled, etc) will now display latest versions instead of the ones saved as Base versions - this was...
Read more >
How to Use Shaders as Materials in Three.js (with Uniforms)
I've recently learned how to use Three.js's ShaderMaterial to map shaders onto meshes. If you're not familiar with shaders, I recommend you ...
Read more >
ShaderMaterial#uniforms – three.js docs
Custom uniforms must be defined in both the uniforms property of your ShaderMaterial , whereas any custom attributes must be defined via BufferAttribute ......
Read more >
Synching two meshes, one with ShaderMaterial - Stack Overflow
I've got two meshes created from the same geometry and running the same animation. If I do absolutely nothing to the meshes they...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found