Custom vector uniform are not updated by VectorKeyframeTrack correctly

I have this code below:

const planeGeometry = new THREE.PlaneGeometry(1, 1)
const mat = new THREE.ShaderMaterial({
  lights: false,
  transparent: true,
  uniforms: {
    ax: { value: [0, 1, 0] }
  },
  vertexShader: /* glsl */ `
    void main() {
      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }`,
  fragmentShader: /* glsl */ `
    uniform vec3 ax;
    void main() {
      gl_FragColor = vec4(ax, 1.);
    }`
})

const mesh = new THREE.Mesh(planeGeometry, mat)
scene.add(mesh)
const times = [0, 1, 2]
const values = [1, 0, 0, 0, 1, 0, 0, 0, 1]
const track = new THREE.VectorKeyframeTrack('.material[uniforms].ax[value]', times, values, THREE.InterpolateDiscrete)
// const track = new THREE.VectorKeyframeTrack('.position', times, values, THREE.InterpolateDiscrete)
const clip = new THREE.AnimationClip('c', 3, [track])
const mixer = new THREE.AnimationMixer(mesh)
const action = mixer.clipAction(clip)
action.play()

it will throw
three.module.js:17181 Uncaught TypeError: Failed to execute 'uniform3fv' on 'WebGL2RenderingContext': Overload resolution failed.
when mixer.update() is called.

When I switch track name from .material[uniforms].ax[value] to .position,
plane’s postion animated properly.
I also tried float uniform track and it works too, looks like it only throws with vector uniforms.

Any idea of how can I make this work?

value:new THREE.Vector3(0,1,0)

I believe simple array like [0, 1, 0] works too, it renders if I remove mixer.update() call.

But you are using keyframes of vector type, how does it update your array correctly?

well, change to new THREE.Vector3(0, 1, 0) still throws after mixer.update() call, I believe it just set the initial value of uniform and infer its type by arraylength or THREE.Vector3 type.
what acutally cause the problem is VectorKeyframeTrack set number value to this uniform.

The animation system is not able to parse .material[uniforms].ax[value] so it does not find the path to the respective uniforms property. You have to find another way to animate the uniforms for now.

Alright, but when I change to a float uniform, it actually works. Why vector uniform not work in same way…

Any chances to demonstrate what you are doing with a small live example? Edit fiddle - JSFiddle - Code Playground

sure, I updated the live example to use float uniforms, but when you uncomment .material[uniforms].ax[value] track, it throws this:

1 Like

Thanks for the fiddle! Indeed, the animation system does not support the above path definition. It can not detect an instance of Vector3 as the uniform value. It assumes instead a primitive number in an array which is why a single float works.

1 Like

Understood, I’ll switch to aniamte them in render loops, thanks for explaining!