关于使用 glBufferSubData 频繁更新实例化数组的困惑

Confusion regarding frequent updates of instanced array using glBufferSubData

我正在使用实例渲染渲染大片草地,为此我使用了一个由大量 4x4 变换矩阵组成的实例数组。

我在草叶上使用 LOD 算法来根据它们与相机的距离来确定渲染哪些叶子。出于这个原因,我将实例化数组更新为仅包含相关的变换矩阵,然后通过 glDrawArraysInstanced 渲染它们各自的叶子。

我对更新实例化数组感到困惑。我按如下方式创建了一次实例化数组:

glBindBuffer(GL_ARRAY_BUFFER, VBO_Models);
glBufferData(GL_ARRAY_BUFFER, grass.size() * sizeof(glm::vec4), NULL, GL_STREAM_DRAW);

那么最有效的方法是使用 glBufferSubData 更新其内容(以节省昂贵的内存重新分配),我这样做如下:

glBufferSubData(GL_ARRAY_BUFFER, 0, grassModels.size() * sizeof(glm::mat4), &grassModels[0]);

但这就是事情变得奇怪的地方。如果我使用 glBufferSubData 它似乎只会在我在场景周围移动一定距离后(我会说大约每 1000 帧)在渲染期间更新实例化数组,而不是如果我在同一位置保持静态。

当我用 glBufferData 重新分配内存后,它确实可以完美运行。所以我认为这可能是一个同步问题,所以我实现了一个带有多个缓冲区的循环方法;没用。我尝试了确实有效的孤立(因为我再次使用 glBufferData),但我不想使用这种方法。

然而,同步问题通常只发生在几帧内(在我的情况下不是大约 1000 帧,只有在移动之后)。可能涉及移动,因为这会显着改变缓冲区的内容,迫使 GPU 使用新更新的内存?

我不确定是什么导致了 glBufferSubData 的这种行为,并且在文档中找不到与我的问题类似的内容。我可以使用 glBufferData 轻松解决问题,这不会给我带来明显的性能下降,但我很好奇是什么导致了这种行为?

glBindBuffer(GL_ARRAY_BUFFER, VBO_Models);
glBufferData(GL_ARRAY_BUFFER, grass.size() * sizeof(glm::vec4), NULL, GL_STREAM_DRAW);

此处传入的尺寸小于您正在更新的尺寸。这导致 GL_INVALID_VALUE 并将更新变成空操作。