У меня проблема с 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, когда программа все еще находится в режиме паузы, теперь она отображает новые данные, как будто они каким-то образом «обновили» их. И затем, если я нажимаю кнопку воспроизведения, он начинает рисовать правильно.