Opengl glBufferData不删除现有数据存储
美国 glBufferData为当前缓冲区对象创建新的数据存储Opengl glBufferData不删除现有数据存储,opengl,Opengl,美国 glBufferData为当前缓冲区对象创建新的数据存储 一定要瞄准目标。任何预先存在的数据存储都将被删除。新数据 使用指定的大小(以字节为单位)和用法创建存储 所以我编码 // allocate storage in GPU and copy data glBufferData( GL_ARRAY_BUFFER, myData.VertexCount()*sizeof(GL_FLOAT), myData.Vertex(),
一定要瞄准目标。任何预先存在的数据存储都将被删除。新数据 使用指定的大小(以字节为单位)和用法创建存储 所以我编码
// 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();
}
发生的情况是,当您调用
glBufferData
时,GL驱动程序会在其内存中为您提供一个可能与上一个位置相同的位置。您认为可以使用glBufferData
更新整个过程的一部分,但事实并非如此。其余数据可能与旧数据一致,也可能不一致。
我认为您最好使用glBufferSubData
而不是glBufferData
来更新新数据(或其中的一部分),而无需删除和重新创建数据存储。
当newSize>oldSize时,您需要删除并重新创建。发生的情况是,当您调用
glBufferData
时,GL驱动程序会在其内存中为您提供一个可能与上一个位置相同的位置。您认为可以使用glBufferData
更新整个过程的一部分,但事实并非如此。其余数据可能与旧数据一致,也可能不一致。
我认为您最好使用glBufferSubData
而不是glBufferData
来更新新数据(或其中的一部分),而无需删除和重新创建数据存储。
当newSize>oldSize时,您需要删除并重新创建。您的代码不正确。将顶点属性指针设置为每个顶点读取3
GLfloat
s,并使用myData.VertexCount()
作为绘图调用中的顶点数,但仅将myData.VertexCount()*sizeof(GL\u FLOAT)
字节上载到VBO。因此,您将读取超过缓冲区末尾的内容,结果只是未定义的行为
.您的代码就是不正确。将顶点属性指针设置为每个顶点读取3
GLfloat
s,并使用myData.VertexCount()
作为绘图调用中的顶点数,但仅将myData.VertexCount()*sizeof(GL\u FLOAT)
字节上载到VBO。因此,您将读取超过缓冲区末尾的内容,结果只是未定义的行为
.“已删除现有数据存储”而不是“已存储数据”如何呈现旧数据?刷新时不更新它吗?是否对glDrawXXX使用了与glBufferData使用的计数不匹配的计数?您希望如何重用以前声明为已删除的数据?请解释一下,考虑一个像C++指针一样的缓冲区(即“数据存储”)。您可以删除指针,而无需清除指向的数据。仅再次将内存标记为可用。glBufferData是缓冲区副本,而不是缓冲区映射——您应该认为该存储是新的,未初始化。如果在渲染中看到旧数据,则可能是在上载旧数据,或者以某种方式触发未定义的行为(例如渲染过多的顶点)。“已删除现有数据存储”而不是“已存储数据”如何渲染旧数据?刷新时不更新它吗?是否对glDrawXXX使用了与glBufferData使用的计数不匹配的计数?您希望如何重用以前声明为已删除的数据?请解释一下,考虑一个像C++指针一样的缓冲区(即“数据存储”)。您可以删除指针,而无需清除指向的数据。仅再次将内存标记为可用。glBufferData是缓冲区副本,而不是缓冲区映射——您应该认为该存储是新的,未初始化。如果在渲染中看到旧数据,则可能是在上载旧数据,也可能是在以某种方式触发未定义的行为(例如渲染过多的顶点)。这一解释是有道理的。它没有解释为什么要绘制旧数据。我使用正确的、减少的顶点计数调用glDrawArrays,但它会继续进行,并渲染超过该计数的顶点。是否在
glBufferData
之前再次调用glBufferData
?不确定“再次”是什么意思。我确实在GLBUFFERDATA之前调用了glBindBuffer这个解释就其本身而言是有意义的。它没有解释为什么要绘制旧数据。我使用正确的、减少的顶点计数调用glDrawArrays,但它会继续进行,并渲染超过该计数的顶点。是否在glBufferData
之前再次调用glBufferData
?不确定“再次”是什么意思。我确实在GLBUFFERDATA出现之前调用了glBindBuffer。我需要编写gldrawArray(GL_三角形,0,myData.VertexCount()/3);你可以这么做,但我建议你打电话给VertexCount,因为这不是名字所暗示的。这是一个快速修复方法,可以测试我对你答案的理解。在生产代码中,我保持glDrawArrays调用不变,并编写了传递给GLBUFFERDATA的字节数,并将其增加了三倍。我需要编写gldrawArray(GL_三角形,0,myData.VertexCount()/3);你可以这样做,但是我建议你调用VertexCount
其他的东西,因为它不是这个名字所暗示的