У меня есть некоторый код, который проходит через набор объектов и отображает экземпляры этих объектов. Список объектов, которые должны быть отображены, хранится в виде std :: map>, где объект класса MeshResource содержит вершины и индексы с фактическими данными, а объект classMeshRenderer определяет точку в пространстве, в которой должна находиться сетка. предоставлено в.
Мой код рендеринга выглядит следующим образом:
glDisable(GL_BLEND);
glEnable(GL_CULL_FACE);
glDepthMask(GL_TRUE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
for (std::map<MeshResource*, std::vector<MeshRenderer*> >::iterator it = renderables.begin(); it != renderables.end(); it++)
{
it->first->setupBeforeRendering();
cout << "<";
for (unsigned long i =0; i < it->second.size(); i++)
{
//Pass in an identity matrix to the vertex shader- used here only for debugging purposes; the real code correctly inputs any matrix.
uniformizeModelMatrix(Matrix4::IDENTITY);
/**
* StartHere fix rendering problem.
* Ruled out:
* Vertex buffers correctly.
* Index buffers correctly.
* Matrices correct?
*/
it->first->render();
}
it->first->cleanupAfterRendering();
}
geometryPassShader->disable();
glDepthMask(GL_FALSE);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
Функция в MeshResource, которая обрабатывает настройку униформ, выглядит следующим образом:
void MeshResource::setupBeforeRendering()
{
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
glEnableVertexAttribArray(4);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0); // Vertex position
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*) 12); // Vertex normal
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*) 24); // UV layer 0
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*) 32); // Vertex color
glVertexAttribPointer(4, 1, GL_UNSIGNED_SHORT, GL_FALSE, sizeof(Vertex), (const GLvoid*) 44); //Material index
}
Код, который отображает объект:
void MeshResource::render()
{
glDrawElements(GL_TRIANGLES, geometry->numIndices, GL_UNSIGNED_SHORT, 0);
}
И код, который очищает это:
void MeshResource::cleanupAfterRendering()
{
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(3);
glDisableVertexAttribArray(4);
}
Конечным результатом этого является то, что я получаю черный экран, хотя конец моего конвейера рендеринга после кода рендеринга (по сути, просто рисование осей и линий на экране) работает должным образом, поэтому я уверен, что это не проблема с прохождение униформы. Однако, если я немного изменю код, чтобы код рендеринга вызывал настройку непосредственно перед рендерингом, вот так:
void MeshResource::render()
{
setupBeforeRendering();
glDrawElements(GL_TRIANGLES, geometry->numIndices, GL_UNSIGNED_SHORT, 0);
}
Программа работает по желанию. Однако я не хочу этого делать, поскольку моя цель - настроить данные вершин, материалов и т. Д. Один раз для каждого типа объекта, а затем визуализировать каждый экземпляр, обновляя только информацию преобразования.
UniformizeModelMatrix работает следующим образом:
void RenderManager::uniformizeModelMatrix(Matrix4 matrix)
{
glBindBuffer(GL_UNIFORM_BUFFER, globalMatrixUBOID);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(Matrix4), matrix.ptr());
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
offsetof
при указании атрибутов вершинОтветы:
Прежде всего, OpenGL полон странных вещей, поэтому ошибка драйвера, какой бы маловероятной она ни была, по-прежнему является опцией - рассмотрите возможность тестирования приложения на разных настройках (nVidia против AMD, более старые драйверы) и других крошечных модификаций кода. Например, вы можете начать с удаления "glBindBuffer (GL_UNIFORM_BUFFER, 0);" линия - похоже, ничего полезного не делает.
Так как все здесь кажется правильным, проблема, скорее всего, не здесь. Есть два варианта: gDEBugger и пошаговое выполнение кода в отладчике C ++. Похоже, что что-то сбрасывается непосредственно перед рисованием. В gDEBugger есть функция «истории вызовов», которая может помочь вам увидеть, какие вызовы были сделаны до вызова и в каком порядке.
Кстати, я настоятельно рекомендую вам обернуть каждый вызывающий ошибку вызов макросом, который проверяет все возможные ошибки и выдает их. Это должен быть макрос для поддержки расширенной отладки (печать файла, строки и самой ошибочной строки кода), которую можно отключить в сборках выпуска. Если какое-то секретное правило нарушено, такая установка должна немедленно предупредить вас об этом.
источник
Я почти уверен, что атрибут должен привязываться к текущему буферу, поэтому нет никакой причины повторять этот бизнес с атрибутами каждый кадр, если вы не перестраиваете буфер каждый раз ....
Таким образом, вы, вероятно, должны сделать это так или иначе - либо оставить все как есть, либо перестраивать все целиком каждый кадр.
источник
TL; DR: ошибки водителя.
В моих тестах по состоянию на сегодня (октябрь 2016 г.) большинство драйверов не поддерживают должным образом одинаковые буферы .
Некоторые не уважают,
glUniformBlockBinding
некоторые не обновляют унифицированные данные (glBufferSubData
иglBufferData
) должным образом, где кешированные шейдеры / графические процессоры внутренних копий указанных буферов не сохраняются согласованными.То, как я понимаю это (и то, как Nvidia также понимает это)
glBindBufferBase
илиglBindBufferRange
.glUniformBlockBinding(shader_id, shader_ubo_index, global_ubo_index);
этот параметр, для каждой программы шейдера , а не для общего доступа.Примечание: global_ubo_index - это НЕ имя объекта единого буфера, а индекс в этой глобальной таблице.
Эта «сложность» (которая является отличной функцией для разделения UBO между различными шейдерами, например значениями освещения), кажется, что большинство драйверов OpenGL ошибаются. Чтобы быть справедливым, формулировка в документации OpenGL не самая однозначная, как это может быть.
Мне пришлось прибегнуть к использованию простой старой формы для других водителей.
Оба скриншота с использованием единых буферных объектов, два разных драйвера:
источник