我正在使用BufferGeometry来绘制构成地形的数千个立方体,但是如果我需要更改其中一个立方体的位置,则很难找到如何更新几何体。例如,我有这个代码来初始化我的几何:(我正在对this example的更新版本进行测试)
// 12 triangles per cube (6 quads)
var triangles = 12 * 150000;
var geometry = new THREE.BufferGeometry();
geometry.attributes = {
position: {
itemSize: 3,
array: new Float32Array( triangles * 3 * 3 ),
numItems: triangles * 3 * 3
},
normal: {
itemSize: 3,
array: new Float32Array( triangles * 3 * 3 ),
numItems: triangles * 3 * 3
},
color: {
itemSize: 3,
array: new Float32Array( triangles * 3 * 3 ),
numItems: triangles * 3 * 3
}
}
positions = geometry.attributes.position.array;
normals = geometry.attributes.normal.array;
colors = geometry.attributes.color.array;
如果我移动一个立方体,在我这样做之前它似乎不会被移动:
geometry.attributes.position.needsUpdate = true;
这会导致FPS在更新时掉线。还有另外一种方法吗?当我只改变一个立方体(12个三角形/ 36个顶点)时,似乎有点不必要了。虽然它可能是 - 我还没有检查needsUpdate
实际上做了什么。猜测它再次将数组发送到着色器。
我在想我可以将几何体拆分成单独的较小的BufferGeometries,但我不确定这是否有助于整体性能。据我所知,更多的几何形状=更少的FPS。
如果有人有任何想法我会怎么做,我们将不胜感激! :)除了更新问题,BufferGeometry似乎正是我需要的。谢谢!
答案 0 :(得分:8)
在更新其中的几个顶点时,我遇到了一个非常大的BufferGeometry问题。
解决方案是使用_gl.bufferSubData而不是_gl.bufferData来仅更新缓冲区的一部分。 (三个js仅使用_gl.bufferData)。
因此,如果你更新你将要做的职位:
//创建要从索引offsetSub更新到offsetSubEnd
的数据视图 var view = geometry.attributes.position.array.subarray(offsetSub, offsetSubEnd);
//将缓冲区绑定到位置(使用webglrenderer获取gl上下文)
_gl.bindBuffer(_gl.ARRAY_BUFFER, geometry.attributes.position.buffer);
//将新值插入gpu缓冲区中的良好索引处(offsetGeometry以字节为单位)
_gl.bufferSubData(_gl.ARRAY_BUFFER, offsetGeometry,view);
请注意,与_gl.bufferData相比,如果更改大部分缓冲区顶点,此解决方案可能会更慢。
答案 1 :(得分:7)
从r71
开始,threejs支持bufferSubData
。
使用DynamicBufferAttribute
,(或只是正确设置updateRange
)
var positionAttr = geometry.attributes.position
// if not using DynamicBufferAttribute initialize updateRange:
// positionAttr.updateRange = {};
positionAttr.updateRange.offset = 0; // where to start updating
positionAttr.updateRange.count = 1; // how many vertices to update
positionAttr.needsUpdate = true;