如何快速更新大型 BufferGeometry? [英] How to quickly update a large BufferGeometry?

查看:20
本文介绍了如何快速更新大型 BufferGeometry?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

I'm using a BufferGeometry to draw thousands of cubes which makes up the terrain, but having a hard time finding out how to update the geometry if I need to change the position of one of the cubes. For example, I have this code to initialize my geometry: (I'm doing my testing on an updated version of 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;

If I move a cube, it won't appear to be moved until I do:

geometry.attributes.position.needsUpdate = true;

This causes the FPS to drop while it's being updated. Is there another way I could do this? Seems a bit unnecessary when I'm only changing one cube (12 triangles/36 vertices). Although it might be - I haven't checked what needsUpdate actually does. Guessing it sends the array to the shader again.

I was thinking I could split the geometry into separate smaller BufferGeometries but I'm not sure if that would help the performance overall. From what I understand, more geometries = less FPS.

If anyone has any ideas how I would do this, it would be appreciated! :) Besides the updating issue, BufferGeometry seems to be exactly what I need. Thanks!

解决方案

I had the same problem with a very large BufferGeometry when updating a few vertices in it.

A solution is to use _gl.bufferSubData instead of _gl.bufferData to update just a part of the buffer. (three.js uses only _gl.bufferData).

So if you update the positions you will do:

// Create a view of the data to update from index offsetSub to offsetSubEnd
var view = geometry.attributes.position.array.subarray(offsetSub, offsetSubEnd);

// Bind the buffer for positions (get the gl context with webglrenderer)
_gl.bindBuffer(_gl.ARRAY_BUFFER, geometry.attributes.position.buffer);

// Insert the new values at good index in gpu buffer (offsetGeometry is in byte)
_gl.bufferSubData(_gl.ARRAY_BUFFER, offsetGeometry,view);

Note that this solution can be slower if you change a large part of the buffer vertices compared to _gl.bufferData.

这篇关于如何快速更新大型 BufferGeometry?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆