You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Three.js InstancedMesh更新实例矩阵后自定义Shader未生效如何解决

问题解决方法

根因说明

你自定义的着色器未适配InstancedMesh的实例化渲染逻辑:InstancedMesh的每个实例的独立变换数据存储在instanceMatrix属性中,Three.js内置材质会自动处理该矩阵完成实例级变换,但你手写的顶点着色器直接使用了全局modelViewMatrix,完全没有应用每个实例的独立变换,因此更新实例矩阵不会有任何效果。同时你当前的描边逻辑没有处理实例变换后的法线偏移,会导致描边方向错误。

修改步骤

1. 重写顶点着色器

添加实例矩阵属性,完成实例级的坐标与法线变换:

<script type="x-shader/x-vertex" id="vertexShader">
    uniform float offset;
    // 声明InstancedMesh注入的实例矩阵属性
    attribute mat4 instanceMatrix;

    void main() {
        // 应用实例矩阵变换顶点
        vec4 instancePos = instanceMatrix * vec4(position, 1.0);
        // 计算实例变换后的法线(逆矩阵转置处理缩放/旋转对法线的影响)
        mat3 instanceNormalMatrix = transpose(inverse(mat3(instanceMatrix)));
        vec3 transformedNormal = instanceNormalMatrix * normal;
        // 沿变换后的法线偏移
        instancePos.xyz += transformedNormal * offset;
        // 后续正常应用视图、投影矩阵
        vec4 viewPos = modelViewMatrix * instancePos;
        gl_Position = projectionMatrix * viewPos;
    }
</script>

2. 调整ShaderMaterial配置(可选,优化描边效果)

描边材质一般设置为背面渲染,避免遮挡本体模型:

var outlineMaterial = new THREE.ShaderMaterial( {
    uniforms: uniforms,
    vertexShader: document.getElementById( 'vertexShader' ).textContent,
    fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
    // 新增以下配置
    side: THREE.BackSide,
    depthWrite: false
});

3. 原有实例化逻辑无需修改

你之前更新instanceMatrix、标记needsUpdate的逻辑完全正确,不需要调整。

修改完成后实例的旋转、缩放变换即可正常作用于描边效果,法线偏移方向也会跟随实例变换同步修正。


内容的提问来源于stack exchange,提问作者kiennt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 03:27:02