GlEnableClientState с современным OpenGL (glVertexAttribPointer и т.д.)

Я хотел бы рассказать о некоторых вещах, которые, как я думаю, узнал, но я не уверен:

  • VBOs - это путь. Они создаются с помощью glGenBuffers и glBufferData.
  • Для максимальной гибкости лучше передать общие атрибуты вершин в шейдеры с glVertexAttribPointer, а не glVertex, glNormal и т.д.
  • glDrawElements может использоваться с буферами вершин и буфером индексов для эффективного рендеринга геометрии с большим количеством общих вершин, таких как ландшафтная сетка.

Предполагая, что все это правильно, вот мой вопрос. Все обучающие материалы, которые я прочитал о современном OpenGL, полностью опускают glEnableClientState. Но man-страницы OpenGL говорят, что без glEnableClientState, glDrawElements ничего не сделает:

http://www.opengl.org/sdk/docs/man/xhtml/glDrawElements.xml

Ключевой проход: "Если GL_VERTEX_ARRAY не включен, геометрические примитивы не создаются".

Это приводит меня к следующим вопросам:

  • Ни один из руководств не использует glEnableClientState перед вызовом glDrawElements. Означает ли это, что страница руководства неверна или устарела?
  • GL_VERTEX_ARRAY, похоже, будет тем, что вы включите, если вы собираетесь использовать glVertexPointer, а также использовать GL_NORMAL_ARRAY с glNormalPointer и так далее. Но если я не использую эти функции и вместо этого использую общие атрибуты вершин с glVertexAttribPointer, то зачем нужно включать GL_VERTEX_ARRAY?

Ответ 1

Если GL_VERTEX_ARRAY не включен, геометрические примитивы не создаются.

Это потому, что справочная страница неверна. Страница руководства охватывает GL 2.1 (и это по-прежнему не так), и по любой причине люди, обновляющие справочную страницу, отказываются обновлять старые версии GL для исправлений ошибок.

В GL 2.1 вы должны использовать либо общий индекс атрибута 0, либо GL_VERTEX_ARRAY. В GL 3.1+ вам не нужно использовать какие-либо конкретные индексы атрибутов.

Это связано с тем, что в версиях GL до 3.1 все функции рендеринга массива были определены в терминах вызовов glArrayElement, которые использовали немедленный рендеринг на основе режима. Это означает, что вам нужно что-то спровоцировать вершину. Напомним, что в непосредственном режиме вызов glVertex*() не только устанавливает положение вершины, но также вызывает отправку вершин с другими атрибутами. Вызов glVertexAttrib*(0, ...) делает то же самое. Поэтому для более старых версий вам потребуется использовать либо атрибут 0, либо GL_VERTEX_ARRAY.

В GL 3.1+, как только они выберут немедленный режим, им пришлось указывать рендеринг массива по-разному. И из-за этого им не пришлось ограничивать себя использованием атрибута 0.

Если вы хотите, чтобы документы API для ядра GL 3.3 работали, я предлагаю вам посмотреть фактические документы API для основного GL 3.3. Хотя, если честно, я бы просто посмотрел на спецификацию, если вам нужна точная информация. В этих документах много дезинформации. И поскольку они не являются вики-страницами, эта информация никогда не исправляется.

Ответ 2

Ваши первые 3 балла верны. И чтобы ответить на вашу последнюю половину вопроса, не используйте glEnableClientState для современного OpenGL. Начните кодирование!

Ответ 3

VBOS - это путь. Они созданы с помощью glGenBuffers и glBufferData.

VBOs часто используются в высокопроизводительных приложениях. Сначала вы можете сделать что-то более простое. Вершинные массивы могут быть хорошим способом быстро начать работу. Поскольку VBOs сидят поверх вершинных массивов в любом случае, вы будете использовать большую часть того же кода при переключении на VBOs, и может быть полезно запустить тест с использованием вершинных массивов или индексированных массивов вершин.

Для максимальной гибкости лучше всего передать общие атрибуты вершин для шейдеров с glVertexAttribPointer, а не glVertex, glNormal, и т.д..

Это хороший подход.

glDrawElements может использоваться с буферами вершин и буфером индексов для эффективно выполнять геометрию с множеством общих вершин, например ландшафтная сетка.

Может быть. Однако вы должны быть уверены, что вершины действительно разделены. Вершина, находящаяся в одном и том же месте, но имеющая обычную нормальную (например, для плоского затенения), по-настоящему не разделена.