【发布时间】:2017-02-17 17:34:56
【问题描述】:
glBufferData 为当前的缓冲区对象创建一个新的数据存储 绑定到目标。任何预先存在的数据存储都将被删除。新数据 以指定的字节大小和使用情况创建存储。
所以我编码
// allocate storage in GPU and copy data
glBufferData(
GL_ARRAY_BUFFER,
myData.VertexCount()*sizeof(GL_FLOAT),
myData.Vertex(),
GL_STREAM_DRAW);
...
glDrawArrays(
GL_TRIANGLES,
0,
myData.VertexCount() );
每次我需要刷新场景时都会执行。
顶点的数量有时会发生很大变化。当顶点数减少时,旧数据似乎仍然存在,并出现旧数据的乱码渲染。
我可以通过在每次刷新开始时创建缓冲区索引,然后将其删除来解决此问题
// construct buffer index
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
...
glDeleteBuffers(1,&vertexbuffer);
目前这很好,但我想稍后进行优化,包括重用缓冲区中的一些顶点,而无需在每次刷新时制作新副本。
问题并未出现在我的所有机器上。显卡好一点的机器好像没有问题
作为参考,这里是整个渲染代码:
void Render()
{
// Background color
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
glUseProgram( myShaderID );
// Send our transformation to the currently bound shader,
// in the "MVP" uniform
glUniformMatrix4fv(myMatrixID, 1, GL_FALSE, &MVP[0][0]);
// enable vertices attribute buffer
glEnableVertexAttribArray(0);
// make current
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
// allocate storage in GPU and copy data
glBufferData(GL_ARRAY_BUFFER, myData.VertexCount()*sizeof(GL_FLOAT),
myData.Vertex(), GL_STREAM_DRAW);
// let shaders access buffer
glVertexAttribPointer(
0, // attribute. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 2nd attribute buffer : colors
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glBufferData(GL_ARRAY_BUFFER, myData.VertexCount()*sizeof(GL_FLOAT),
myData.Color(), GL_STREAM_DRAW);
glVertexAttribPointer(
1, // attribute. No particular reason for 1, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glDrawArrays(GL_TRIANGLES, 0, myData.VertexCount() );
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glFlush();
myCanvas->SwapBuffers();
}
这是最终的、固定的生产代码。 VertexCount() 现在返回实际的顶点数,而不仅仅是顶点向量中的浮点数。
/** Update GL display */
void Render()
{
// Background color
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
glUseProgram( myShaderID );
// Send our transformation to the currently bound shader,
// in the "MVP" uniform
glUniformMatrix4fv(
myMatrixID,
1,
GL_FALSE,
myCamera.ModelViewProjection() );
// enable vertices attribute buffer
glEnableVertexAttribArray(0);
// make current
glBindBuffer(GL_ARRAY_BUFFER, myVertexBufferID);
// allocate storage in GPU and copy data
glBufferData(
GL_ARRAY_BUFFER,
3 * myData.VertexCount()*sizeof(GL_FLOAT),
myData.Vertex(),
GL_STREAM_DRAW);
// let shaders access buffer
glVertexAttribPointer(
0, // attribute. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 2nd attribute buffer : colors
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, myColorBufferID);
glBufferData(
GL_ARRAY_BUFFER,
3 * myData.VertexCount()*sizeof(GL_FLOAT),
myData.Color(),
GL_STREAM_DRAW);
glVertexAttribPointer(
1, // attribute. No particular reason for 1, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glDrawArrays(GL_TRIANGLES, 0, myData.VertexCount() );
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glFlush();
myCanvas->SwapBuffers();
}
【问题讨论】:
-
“预先存在的数据存储已被删除”而不是“数据存储d”您如何渲染旧数据?刷新的时候不更新吗?您是否在 glDrawXXX 上使用了不同的 count 与在 glBufferData 中使用的不匹配?您希望如何重用您之前声明为已删除的数据?请多解释一下。
-
考虑像 C++ 指针一样的 bufferID(即“数据存储”)。您可以删除指针而不清除指向的数据。仅将内存再次标记为空闲。
-
glBufferData 是缓冲区副本,而不是缓冲区映射 - 存储应该被认为是新的并且未初始化。如果您在渲染时看到旧数据,则说明您正在上传旧数据,或者以某种方式触发了未定义的行为(例如,渲染了太多顶点)。
标签: opengl