ThreeJS中onBeforeRender回调无法正确更新对象几何体的问题
问题:Three.js中onBeforeRender回调内更新物体缩放未达到预期效果
基于Three.js的THREE.Mesh扩展了Test类,想要实现相机缩放时物体大小固定的效果,给类添加了update方法通过修改scale抵消相机缩放的影响。但发现只有在render函数渲染前调用update才能生效,在onBeforeRender回调中调用会得到异常结果。
问题原因
当onBeforeRender回调触发时,Three.js的渲染流程已经完成了**模型视图矩阵(ModelViewMatrix)**的计算。此时修改物体的scale属性,不会触发矩阵的重新计算,当前帧渲染会沿用旧矩阵,导致缩放修改无法生效。而在renderer.render()调用前执行update,修改scale后,Three.js会在渲染流程中重新计算物体的模型矩阵,确保修改被正确应用。
解决方案
方案1:手动触发矩阵更新
在update方法末尾添加矩阵更新标记,强制Three.js重新计算矩阵:
update(zoom) { this.scale.x = width / zoom this.scale.y = height / zoom // 强制更新矩阵,确保修改生效 this.matrixWorldNeedsUpdate = true; }
这样即使在onBeforeRender中调用update,修改后的缩放也会触发矩阵重新计算,渲染时使用最新的矩阵数据。
方案2:保持在render前调用update(原有效方案)
继续沿用在render函数中renderer.render()之前调用test.update(camera.zoom)的方式,确保渲染前完成所有属性修改,让Three.js的默认渲染流程自动处理矩阵计算。
额外优化建议
对于正交相机下的“物体大小固定”需求,还可以直接通过修改相机的投影参数实现,不需要修改物体缩放:
function updateCamera(camera, width, height) { const k = 0.5 / camera.zoom; // 加入zoom抵消逻辑 camera.left = -k * width camera.right = k * width camera.top = k * height camera.bottom = -k * height camera.updateProjectionMatrix() }
这种方式不需要额外维护物体的scale,逻辑更简洁,也避免了矩阵更新的额外开销。
内容的提问来源于stack exchange,提问作者Pavel Yakovlev
相关产品推荐
相关产品推荐

