如何在自定义ShaderMaterial中支持InstanceMesh/BatchedMesh?
解决BatchedMesh中自定义着色器的位置偏移问题
你的问题出在BatchedMesh依赖实例化矩阵(instanceMatrix)处理每个实例的变换,而你原来的顶点着色器直接使用modelViewMatrix,没有考虑实例化批次的每个实例的独立变换,导致所有几何体都被渲染在原点。
核心修改点
- 在顶点着色器中引入
instanceMatrix属性,用它计算每个实例的模型变换 - 正确推导模型视图矩阵:
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
相关产品推荐
相关产品推荐

