2012-03-04 3 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을 컨텍스트를 설정, 나는 목록을 공유 할 수 있습니다.

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; 
     } 
    } 

데이터 그리려면 : 사용자가 키보드의 "R"를 누를 때 그 때 나는, 데이터를 처리

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 

두 번째 업데이트 : glBuferSubData 대신 glMapBuffer를 사용했지만 응용 프로그램이 동일하게 동작합니다.

 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 (공유 GL1) (나는 스레드 컨텍스트) 올바른 데이터를 가지고 생각합니다.

이상한 부분은 GLContext1을 되돌아 보면 프로그램이 여전히 일시 중지 모드 상태인데, 이제는 새 정보를 표시합니다. 즉, 어떻게 든 새로 고칩니다. 그리고 내가 놀이를 누르면, 정확하게 그리기 시작합니다.

답변

0

해결책을 찾았다면 glUnmapBuffer을 호출 한 후 작업자 스레드에서 glFinish()을 호출해야합니다. 이렇게하면 문제가 해결되며 모든 것이 잘 처리됩니다.

관련 문제