2012-03-04 64 views
0

我有OpenGL VBO問題。我從NeHe下載了一個名爲Lesson45的舊VBO例子,我修改了它來檢查一些東西。OpenGL 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(我認爲主要渲染線程)設備上下文具有舊數據。雖然GLContext2(Shared-GL1)(我認爲線程上下文)具有正確的數據。

奇怪的是,如果我回頭看看GLContext1,程序仍處於暫停模式,現在它顯示新數據,就像它以某種方式「刷新」它。然後如果我按播放,它開始正確繪製。

回答

0

我找到了解決方案,我需要在調用glUnmapBuffer之後在工作線程中調用glFinish()。這將解決問題,一切都會呈現得很好。