OpenGL VBO没有正确更新

时间:2012-03-04 13:50:12

标签: opengl vbo

我有一个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 个答案:

答案 0 :(得分:0)

我找到了解决方案,我需要在调用glFinish()后在工作线程中调用glUnmapBuffer。这将解决问题,一切都会好起来。