OpenGL VBO 没有正确更新
Posted
技术标签:
【中文标题】OpenGL VBO 没有正确更新【英文标题】:OpenGL VBO not updating properly 【发布时间】:2012-03-04 13:50:12 【问题描述】:我遇到了 OpenGL VBO 问题。我从 NeHe 下载了名为 Lesson45 的旧 VBO 示例,并对其进行了修改以进行检查。
我的最终结果是创建了大约 9 个图块,其中一个是原点。然后当玩家在屏幕上移动时,顶部/底部的行/列会更新数据。但现在我想要一些基本的东西:
我创建了一个 VBO,然后我想在另一个线程中更新数据。在上传数据时,我不想绘制 VBO,因为那样会导致问题。
我在这里创建 VBO:
glGenBuffersARB( 1, &m_nVBOVertices );
glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_nVBOVertices);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, m_nVertexCount*3*sizeof(float), m_pVertices, GL_DYNAMIC_DRAW_ARB);
我创建了一个线程,我设置了一个 OpenGL 上下文,我共享列表。然后我处理数据,当用户在键盘上按“R”时:
while(TerrainThreadRun)
//look for R
if(window.keys->keyDown[82] == TRUE && keyactivated == false)
keyactivated = true;
window.keys->keyDown[82] = FALSE;
if(keyactivated)
for(int i = 0; i < g_pMesh->m_nVertexCount; i++)
g_pMesh->m_pVertices[i].y = 800.0f;
while(!wglMakeCurrent(window.hDCThread,window.hRCThread))//This was removed
Sleep(5);//This was removed
glBindBufferARB(GL_ARRAY_BUFFER_ARB, g_pMesh->m_nVBOVertices);
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, g_pMesh->m_nVertexCount*3*sizeof(float), g_pMesh->m_pVertices);
keyactivated = false;
绘制数据:
if(!keyactivated)
glEnableClientState( GL_VERTEX_ARRAY );
glBindBufferARB(GL_ARRAY_BUFFER_ARB, g_pMesh->m_nVBOVertices);
glVertexPointer(3, GL_FLOAT, 0, (char*)NULL);
glDrawArrays(GL_TRIANGLES, 0, g_pMesh->m_nVertexCount);
glDisableClientState(GL_VERTEX_ARRAY);
我知道不推荐使用 ARB 扩展,但这只是一个简单的基本示例。
问题是当我第一次按“R”时,数据没有得到更新。 VBO 绘制相同。我第二次按“R”,它会更新数据。我能做些什么来强制平局。我做错了吗?
数据需要强制到显卡吗?我错过了什么吗?
更新:我查看了我的代码,现在我只使用 wglMakeCurrent 一次,当上下文初始化时。在线程中,我在共享列表后使用它,并在共享列表后立即在主线程上使用它,如下所示:
window->hRC = wglCreateContext (window->hDC);
if (window->hRC ==0)
// Failed
TerrainThreadRun = true;
TerrainThread = CreateThread(NULL, NULL,(LPTHREAD_START_ROUTINE)TerrainThreadProc, 0, NULL, NULL);
while(!sharedContext)
Sleep(100);
if (wglMakeCurrent (window->hDC, window->hRC) == FALSE)
在线程中:
if (!(window.hRCThread=wglCreateContext(window.hDCThread)))
//Error
while(wglShareLists(window.hRC, window.hRCThread) == 0)
DWORD err = GetLastError();
Sleep(5);
sharedContext = true;
int cnt = 0;
while(!wglMakeCurrent(window.hDCThread,window.hRCThread))
Sleep(5);
while(TerrainThreadRun)
//look for R
第二次更新:我尝试使用 glMapBuffer 而不是 glBuferSubData,但应用程序的行为相同。代码如下:
void *ptr = (void*)glMapBuffer(GL_ARRAY_BUFFER_ARB, GL_READ_WRITE_ARB);
if(ptr)
memcpy(ptr, g_pMesh->m_pVertices, g_pMesh->m_nVertexCount*3*sizeof(float));
glUnmapMapBuffer(GL_ARRAY_BUFFER_ARB);
更新三:
我做错了一些事情,所以我修改了它们,但问题仍然存在。这是我现在做所有事情的方式:
当应用程序加载时,我创建了两个窗口,每个窗口都有自己的 HWND。基于它们,我创建了两个设备上下文。
然后我分享他们之间的列表:
wglShareLists(window.hRC, window.hRCThread);
这仅在我初始化时执行一次。 之后,我显示了 OGL 窗口,它呈现;我使上下文处于活动状态。然后我加载函数指针并创建 VBO。 主渲染 OGL 完成后,我创建线程。加载线程后,我将其设备上下文激活。
然后我们做正常的事情。
所以我的问题是:我需要更新每个设备上下文的函数指针吗?这可能是我的问题吗?
作为更新,如果我在 gDEBugger 中运行我的测试应用程序,然后我先按“R”然后暂停,它不会正确显示。我看一下内存(纹理、缓冲区和图像查看器)和 GLContext1(我认为是主渲染线程)设备上下文具有 OLD 数据。而 GLContext2 (Shared-GL1) (我认为线程上下文)具有正确的数据。
奇怪的是,如果我回顾 GLContext1,程序仍处于暂停模式,现在它会显示新数据,就像它以某种方式“刷新”它一样。然后如果我按下播放键,它就会开始正确绘制。
【问题讨论】:
【参考方案1】:我找到了解决办法,我需要在调用glUnmapBuffer
之后在工作线程中调用glFinish()
。这将解决问题,一切都会很好地呈现。
【讨论】:
以上是关于OpenGL VBO 没有正确更新的主要内容,如果未能解决你的问题,请参考以下文章