Is it possible to partially update vertex data?

Basically to keep the number of draws low, I’m baking thousands of static meshes together into one big one. This works wonders for my FPS but now I face a new bottleneck - while updating the vertex buffers, anything over 500k verts induces a little stutter in that moment.

Thing is though - only around 1% of the data is new upon each update so there is no need to update the whole thing, just a section here and there. Is there a way to perform partial updates to the vertex buffer of a mesh?

Hi @hazarada and welcome to the forum. The Solid Particle System (SPS) should fit your needs. In particular the section headed Start and End indexes for setParticles().

Having said that 500K vertices is a lot to deal with.

As I can see it, start and end parameters restrict the range of particles for which the update function is called but it does not lower the buffer size update.

Near the end of the setParticle function there is:

if (this._computeParticleColor) {
    mesh.updateVerticesData(VertexBuffer.ColorKind, colors32, false, false);
}
if (this._computeParticleTexture) {
    mesh.updateVerticesData(VertexBuffer.UVKind, uvs32, false, false);
}
mesh.updateVerticesData(VertexBuffer.PositionKind, positions32, false, false);
...

The whole buffers (colors32, uvs32, etc) are passed to the update functions.

I don’t think there’s a way to update only a part of the GPU buffer (I think the update function would take an offset and size if that were possible).

However, I can see that the option does exist in the core engine:

public updateDynamicVertexBuffer(vertexBuffer: DataBuffer, data: DataArray,
       byteOffset?: number, byteLength?: number): void {

so maybe something could be done about this…

[…] What you need nearly exists, we can find this function on Geometry:

public updateVerticesDataDirectly(kind: string, data: DataArray, offset: number,
      useBytes: boolean = false): void {

It only misses the vertexCount parameter, which does exist in the underlying buffer class:

public updateDirectly(data: DataArray, offset: number, vertexCount?: number,
        useBytes: boolean = false): void {

I guess the vertexCount parameter could be added to the Geometry.updateVerticesDataDirectly function, but maybe there was a reason why it was not added in the first place, so waiting for inputs from @Deltakosh or @Sebavan about this.

Also, I’m not sure of the use of byteOffset in Engine.updateDynamicVertexBuffer, it seems to only be the offset in the data buffer passed in, not the offset in the destination buffer…

Nope, no particular reasons, feel free to add it and thanks for the PR !!! It is a great addition.

Note that you can in fact already do a partial buffer update. Just pass to geometry.updateVerticesDataDirectly the data you want to update and the offset where you want to write the data to:

https://playground.babylonjs.com/#8T4D75

In the PG I update a single float (the Y coordinate of a vertex) each 1s.

Contrary to what I said, passing a vertexCount won’t help because in this case the Engine.updateDynamicVertexBuffer function will use a destination offset equals to 0, the offset value being used as a source offset in the data buffer and the vertexCound being used as the length of the data from this source offset.

5 Likes