Morphtargetinfluences undefined

I am trying to implement a particle system morph in between geometries, for some reason morphtargetinfluences stays undefined . I am using three r 143

const shaderMat = new ShaderMaterial( {

        uniforms: {
            color: { value: new Color( 0xffffff ) }, // pointTexture: { value: new THREE.TextureLoader().load( 'textures/sprites/disc.png' ) },
            alphaTest: { value: 0.025 } ,
            size: { value: minScale   },
            scale: { value: 1 }
            
          },
            vertexShader: vShader,
            fragmentShader: fShader,
            blending: AdditiveBlending,
            depthTest: false,
            transparent: true,
        } );

      shaderMat.morphTargets = true;
 const particles = new Points( geometry, shaderMat);
//...

for (let i = 0; i < harmonySamplers.length; i++) 
{ 
let vertices = [];
var tempPosition = new Vector3();
const tempBufferGeometry = new BufferGeometry();

for (let j = 0; j < maxParticles; j++)
   {
    harmonySamplers[i].sample(tempPosition);  
    vertices.push(tempPosition.x, tempPosition.y, tempPosition.z);
    tempBufferGeometry.setAttribute("position", new Float32BufferAttribute(vertices, 3)  );
  }
    geometry.morphAttributes.position[ i ]  = tempBufferGeometry.attributes.position.array 
}


//....

group.children[0].morphTargetInfluences[ 0 ] = 0
 group.children[0].morphTargetInfluences[ 1 ] = 0.5
console.log("child " + group.children[0].morphTargetInfluences) //0 0.5
 console.log("child " + group.children[0].material.morphTargets) // true


You have to setup BufferGeometry.morphAttributes before creating the instance of Points. Otherwise you have to call Points.updateMorphTargets() manually so morphTargetInfluences and morphTargetDictionary are defined.

I added both, that fixed the undefined error however the shader doesnt do much (see below), what is “transformed”, should the morph work as well on Points as with Mesh ?

const geometry = new BufferGeometry(  );
geometry.morphAttributes.position = [];
        const particles = new Points( geometry, shaderMat);
        particles.updateMorphTargets ()
        particles.morphTargetInfluences = testMesh.morphTargetInfluences 
        particles.morphTargetDictionary = testMesh.morphTargetDictionary;
 particles.morphTargetInfluences[0]  = 1;
const vShader = `
      attribute float size;
      varying vec3 vColor;
      uniform float morphTargetInfluences[ 5 ];
       #include <morphtarget_pars_vertex>

      void main() {
         #include <begin_vertex>
        #include <morphtarget_vertex>

    #ifdef USE_MORPHTARGETS
      transformed  += morphTarget0  * morphTargetInfluences[ 0 ];
      transformed  += morphTarget1  * morphTargetInfluences[ 1 ];
      transformed  +=  morphTarget2   * morphTargetInfluences[ 2 ];
      transformed  +=  morphTarget3   * morphTargetInfluences[ 3 ];

      #endif

      vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );
      gl_PointSize = size   ;
      gl_Position = projectionMatrix * mvPosition;

          // gl_Position = vec4( transformed, 1.0 );

   }`

const fShader = `
      uniform vec3 color;
      uniform float alphaTest;
      uniform vec2 u_resolution;
      varying vec3 vColor;

      void main() {
      vec2 xy = gl_PointCoord.xy - vec2(0.5);
      float ll = length(xy);
      gl_FragColor = vec4(color * 10.0 , step(ll, 0.5 ) * alphaTest);
       
   }`


    const shaderMat = new ShaderMaterial( {

        uniforms: {
            color: { value: new Color( 0xffffff ) }, // pointTexture: { value: new THREE.TextureLoader().load( 'textures/sprites/disc.png' ) },
            alphaTest: { value: 0.025 } ,
            size: { value: minScale   },
            scale: { value: 1 },
            morphTargetInfluences: {value: [1.0, 0.0, 0.0, 0.0, 0.0]}

          },
            vertexShader: vShader,
            fragmentShader: fShader,
            blending: AdditiveBlending,
            depthTest: false,
            transparent: true
          
        } );

      shaderMat.morphTargets = true;

If you are using WebGL 2, the above shader code does not work since the renderer assume morph data are defined in a texture.

If you do not fully understand the morph target implementation in the renderer and shaders, I suggest you enhance a built-in material via onBeforeCompile() instead of writing a shader from scratch.

Should I simply remove the conditional instead, like so:

 transformed  += morphTarget0  * morphTargetInfluences[ 0 ];
      transformed  += morphTarget1  * morphTargetInfluences[ 1 ];
      transformed  +=  morphTarget2   * morphTargetInfluences[ 2 ];
      transformed  +=  morphTarget3   * morphTargetInfluences[ 3 ];

I looked up this example: Edit fiddle - JSFiddle - Code Playground
But the morphTargetInfluences dont seem to come through
Unfortunately I have to use a shader on this particular project, however I would welcome any example, or documentation.

Yes, I don’t think the code make sense if you include morphtarget_vertex.

What do you mean by that?

the following shader doesnt seem to react to morphTargetInfluences changfe of value

`const vShader = `
      attribute float size;
      varying vec3 vColor;
      uniform float morphTargetInfluences[ 5 ];
       #include <morphtarget_pars_vertex>

      void main() {
         #include <begin_vertex>
        #include <morphtarget_vertex>

      vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );
      gl_PointSize = size   ;
      gl_Position = projectionMatrix * mvPosition;

   }`
`
group.children[0].morphTargetInfluences[ 0 ] = 0.0
 group.children[0].morphTargetInfluences[ 1 ] = 1.0
  group.children[0].geometry.attributes.position.array       = positions;
  group.children[0].geometry.attributes.size.array           = scales;
  group.children[0].geometry.attributes.position.needsUpdate = true;
  group.children[0].geometry.attributes.size.needsUpdate     = true;

Try to not overwrite position.array and size.array. Set values to the existing arrays via BufferAttribute.set(). Maybe this helps.

Indeed, the geometry was empty. Here is the code should anyone need it:

//geometry
const sphereMesh = new Mesh(new SphereGeometry(2), polyMat)
const tetraGeo = new TetrahedronGeometry(2, 0) //const tetraGeo =  new DecalGeometry( mesh, position, orientation, size );
const tetraMesh = new Mesh(tetraGeo, polyMat)
tetraMesh.rotation.y = Math.PI / 4
tetraMesh.rotation.x = (Math.PI / 4) * 3
const cubeMesh = new Mesh(new BoxGeometry(2, 2, 2), polyMat)
const icoMesh = new Mesh(new IcosahedronGeometry(2, 0), polyMat)
const octoMesh = new Mesh(new TorusKnotGeometry(1.5, 0.5, 80, 15, 2, 3), polyMat)

const sphereSampler = new MeshSurfaceSampler(sphereMesh).build()
const tetraSampler  = new MeshSurfaceSampler(tetraMesh).build()
const cubeSampler   = new MeshSurfaceSampler(cubeMesh).build()
const icoSampler    = new MeshSurfaceSampler(icoMesh).build()
const octoSampler   = new MeshSurfaceSampler(octoMesh).build()

const harmonySamplers = [sphereSampler, tetraSampler, cubeSampler, icoSampler, octoSampler]
const harmonyBuffers = []

//console.log( harmonySamplers[0])

for (let i = 0; i < harmonySamplers.length; i++) {
  const vertices = []
  const tempPosition = new Vector3()
  const tempBufferGeometry = new BufferGeometry()

  for (let j = 0; j < maxParticles; j++) {
    harmonySamplers[i].sample(tempPosition)
    vertices.push(tempPosition.x, tempPosition.y, tempPosition.z)

  }

  geometry.morphAttributes.position[i] = new Float32BufferAttribute(vertices, 3)
  harmonyBuffers[i] = tempBufferGeometry

}

const systemGeom = new BufferGeometry()

    systemGeom.setAttribute('size', new BufferAttribute(OGscales, 1))
    systemGeom.setAttribute('position', new Float32BufferAttribute(OGPos, 3))
    systemGeom.morphAttributes.position = geometry.morphAttributes.position

    const particles = new Points(systemGeom, shaderMat) //mat_P);
    particles.updateMorphTargets()
    particles.morphTargetInfluences[0] = 0

//shader 

const vShader = `
      attribute float size;
      varying vec3 vColor;
     // uniform float morphTargetInfluences[ 5 ];
       #include <morphtarget_pars_vertex>

      void main() {
         #include <begin_vertex>
        #include <morphtarget_vertex>

      vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );
      gl_PointSize = size   ;
      gl_Position = projectionMatrix * mvPosition;

          // gl_Position = vec4( transformed, 1.0 );

   }`

const fShader = `
      uniform vec3 color;
      uniform float alphaTest;
      uniform vec2 u_resolution;
      varying vec3 vColor;

      void main() {
      vec2 xy = gl_PointCoord.xy - vec2(0.5);
      float ll = length(xy);
      gl_FragColor = vec4(color * 10.0 , step(ll, 0.5 ) * alphaTest);
       
   }`

const shaderMat = new ShaderMaterial({
  uniforms: {
    color: { value: new Color(0xffffff) }, // pointTexture: { value: new THREE.TextureLoader().load( 'textures/sprites/disc.png' ) },
    alphaTest: { value: 0.025 },
    size: { value: minScale },
    scale: { value: 1 }
  },
  vertexShader: vShader,
  fragmentShader: fShader,
  blending: AdditiveBlending,
  depthTest: false,
  transparent: true
  //, lighting : true
})

//Updating morph targets
          group.children[0].morphTargetInfluences[i] += 0.001

1 Like

It would be very helpful, if you upload this into the fiddle. Thanks