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

如何在自定义ShaderMaterial中支持InstanceMesh/BatchedMesh?

解决BatchedMesh中自定义着色器的位置偏移问题

你的问题出在BatchedMesh依赖实例化矩阵(instanceMatrix)处理每个实例的变换,而你原来的顶点着色器直接使用modelViewMatrix,没有考虑实例化批次的每个实例的独立变换,导致所有几何体都被渲染在原点。

核心修改点

  1. 在顶点着色器中引入instanceMatrix属性,用它计算每个实例的模型变换
  2. 正确推导模型视图矩阵:viewMatrix * instanceMatrix,再结合顶点位置、投影矩阵计算最终顶点坐标

修改后的着色器代码

const focusMaterial = new THREE.ShaderMaterial({
    vertexShader: /* glsl */`
    // 实例化属性:每个批次实例的focus值
    attribute float focus;
    // BatchedMesh自动提供的实例化矩阵,存储每个实例的模型变换
    attribute mat4 instanceMatrix;

    varying float vFocus;

    void main() {
        vFocus = focus;
        // 计算正确的模型视图矩阵:视图矩阵 × 实例模型矩阵
        mat4 modelViewMatrix = viewMatrix * instanceMatrix;
        // 最终顶点位置计算
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }`,
    fragmentShader: /* glsl */`
        varying float vFocus;

        void main() {
            gl_FragColor = vec4(vFocus, vFocus, 0.5, 1.0);
        }
    `,
});

给BatchedMesh绑定focus实例属性

创建BatchedMesh并添加实例时,需要把focus作为实例属性传入:

// 假设已准备好待批次化的几何体数组和对应的focus值数组
const geometries = [geo1, geo2, geo3];
const focusValues = [0.2, 0.7, 0.9];

// 初始化BatchedMesh
const batchedMesh = new THREE.BatchedMesh(geometries.length, focusMaterial);

// 逐个添加实例并绑定focus属性
geometries.forEach((geo, index) => {
    // 添加几何体时可设置实例的位置、旋转、缩放,会自动写入instanceMatrix
    batchedMesh.addGeometry(geo);
    // 为当前实例设置focus属性值
    batchedMesh.setFloatAttribute('focus', index, focusValues[index]);
});

scene.add(batchedMesh);

关键说明

  • instanceMatrix是BatchedMesh自动为每个实例生成的矩阵,存储该实例的位置、旋转、缩放信息
  • 必须用viewMatrix * instanceMatrix替代原有的modelViewMatrix,因为BatchedMesh场景下modelViewMatrix不会自动包含实例的独立变换
  • focus作为实例属性,每个实例对应一个值,通过setFloatAttribute方法绑定到BatchedMesh上

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 13:04:57