OpenGL VBO не обновляется должным образом - PullRequest
0 голосов
/ 04 марта 2012

У меня проблема с OpenGL VBO. Я скачал старый пример VBO под названием Lesson45 с NeHe и изменил его, чтобы что-то проверить.

Мой конечный результат - создать около 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», а затем делаю паузу, оно отображается неправильно. Я смотрю на контекст устройства памяти (Textures, Buffers и Image Viewers) и GLContext1 (я думаю, основной поток рендеринга) с данными OLD. В то время как GLContext2 (Shared-GL1) (я думаю, что контекст потока) имеет правильные данные.

Странная часть, если я оглядываюсь назад на GLContext1, когда программа все еще находится в режиме паузы, теперь она отображает новые данные, как будто они каким-то образом «обновили» их. И затем, если я нажимаю кнопку воспроизведения, он начинает рисовать правильно.

1 Ответ

0 голосов
/ 05 марта 2012

Я нашел решение, мне нужно вызвать glFinish() в рабочем потоке после вызова glUnmapBuffer. Это решит проблему, и все будет хорошо.

...