Search code examples
three.jsshader

Three.js InstancedMesh: Shader is NOT changed after updating instance matrix


I am using InstancedMesh with an custom outline shader:

<script type="x-shader/x-vertex" id="vertexShader">
    uniform float offset;

    void main() {
        vec4 pos = modelViewMatrix * vec4( position + normal * offset, 1.0 );
        gl_Position = projectionMatrix * pos;
    }
</script>

<script type="x-shader/x-fragment" id="fragmentShader">
    uniform vec3 color;
    uniform float intensity;

    void main() {
        gl_FragColor = vec4( color, intensity );
    }
</script>

Then, I created shader material:

var uniforms = {
        offset: { type: 'f', value: 0.001 },
      color: { type: 'c', value: new THREE.Color(0x6B6B6B) },
      intensity: { type: 'f', value: 1.0 },
};

var outlineMaterial = new THREE.ShaderMaterial( {
      uniforms: uniforms,
      vertexShader: document.getElementById( 'vertexShader' ).textContent,
      fragmentShader: document.getElementById( 'fragmentShader' ).textContent
});

Then I created an InstancedMesh with a box geometry and this material. However, when I update instance matrix, the shader seems NOT be affected.

var dummy = new THREE.Object3D();
var outlineGometry = new THREE.BoxGeometry(1, 1, 1);
var outline = new THREE.InstancedMesh(outlineGometry, outlineMaterial, 1);
    
dummy.position.set(0, 0, 0);
dummy.rotation.set(0, Math.PI/4, 0);
dummy.scale.set(0.1, 0.1, 0.1);
dummy.updateMatrix();
outline.setMatrixAt( 0, dummy.matrix );
outline.instanceMatrix.needsUpdate = true;

Please check the fiddle link below: I updated the instance rotation and scale, but shader is NOT changed.

Fiddle Link

Do you know how to solve this problem?

Thanks.


Solution

  • According to the Westlangley suggestion, I can use instanceMatrix in vertex shader to solve the problem based on the document https://threejs.org/docs/#api/en/renderers/webgl/WebGLProgram