Подтвердить что ты не робот

Когда следует звонить glGetError?

glLoadIdentity говорит

GL_INVALID_OPERATION генерируется, если glLoadIdentity выполняется между выполнение glBegin и соответствующее выполнение glEnd.

Но GL_INVALID_OPERATION - это флаг, возвращаемый glGetError.

Мой вопрос: когда следует называть glGetError (чтобы узнать, вызываем ли мы opengl в правильной последовательности)?

4b9b3361

Ответ 1

Я не уверен, что ваш вопрос о том, когда вы можете вызвать glGetError, если внутри glBegin/End, или же это более общий вопрос об использовании glGetError в целом. Поэтому я отвечу обоим.

То, что вы можете делать между glBegin и glEnd, очень ограничено. Это по назначению, поскольку вы ставите GL в очень специфическом режиме - в середине Draw. Таким образом, все, что напрямую не связано с атрибутами per-vertex, просто неверно. Даже glGetError недействителен в этом контексте. Попытайтесь и подумайте о glBegin + всех вызовах GL между + glEnd как одном вызове Draw для GL, который помогает приблизиться к тому, что GL действительно делает в любом случае.

Теперь у вас никогда не должно возникать ошибка GL, возникающая внутри пары Begin/End, если вы придерживаетесь простого правила только для вызова методов атрибутов (glNormal, glTexCoord, glColor, glSecondaryColor, glIndex, glMultiTexCoord, glVertexAttrib, glVertex и пара других). Все остальное вызовет ошибку. (err... ну, glMaterial - это немного исключение, оно работает, но его использование не поощряется)

Если у вас вопрос, когда вы можете вызвать glGetError, когда ошибка была вызвана внутри пары Begin/End, ChrisF ответил в комментарии: после вызова glEnd.

Теперь, в более широком смысле, используйте glGetError только как инструмент отладки. Мое личное смещение двоякое:

  • проверить glGetError один раз на фрейм, чтобы убедиться, что ошибки нет.
  • переносит большинство вызовов GL с помощью макроса, который может проверять код ошибки GL и включать его только тогда, когда проверка на кадр не выполняется.

Конечно, поскольку методы атрибутов можно вызывать вне пары Begin/End, немного сложно сделать их правильными. Но на практике эти методы никогда не терпят неудачу, поэтому я не беспокоюсь о макро-проверке.

Вкратце о пустяках: GL API изначально был спроектирован так, что реализация клиента фактически не могла знать, была ли ошибка на сайте вызова. Например. если GL был фактически реализован на удаленной машине (например, в SGI-дни), вызов, скажем, glTexEnv с целью не GL_TEXTURE_ENV, просто может быть добавлен в командный буфер, и в этой точке не будет записана ошибка.

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

Если это звучит тяжело, это было так. Это была основная причина, почему не каждый вызов возвращал код ошибки, кстати, и почему вызов glGetError считался одобренным для целей отладки. В наши дни большинство реализаций GL обрабатывают все управление состоянием в одном и том же процессе, так как я сказал, это действительно мелочи для большинства пользователей.

Наконец, всякий раз, когда я говорю о Begin/End, я чувствую, что должен сказать, что вы, вероятно, должны смотреть на то, чтобы не использовать его вообще. Это о худшем способе рисования с GL.

Ответ 2

Обычно вы должны вызывать glGetError после каждого другого вызова gl..., поскольку одним из эффектов вызова является очистка ошибки из стека (из MSDN):

При возникновении ошибки флаг ошибки устанавливается на соответствующее значение кода ошибки. Никакие другие ошибки не записываются до вызова glGetError, возвращается код ошибки, а флаг reset - GL_NO_ERROR.

Однако, если у вас есть вызовы, завернутые в glBegin и glEnd, вызов glError после glEnd. Это должно вернуть вам правильный код ошибки (если он есть) и очистить стек ошибок.

Ответ 3

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

В первом случае, диагностируя проблему, я использую одну из двух стратегий. Поскольку OpenGL не записывает новые ошибки до тех пор, пока не вызывается glGetError, я могу каждый раз проверять ошибки каждый раз через мой основной цикл. Это говорит мне о первой ошибке, которую я потом отслеживаю, и, надеюсь, исправить. Другая стратегия, которую я использую, когда я сузился до какого-то проблемного кода, но я не уверен, какой вызов вызывает проблему. После каждого gl... звоните вне glBegin., glEnd block Я вызову glGetError и сообщите о любых ошибках. Это скажет мне, какой именно вызов gl... вызывает проблему и, надеюсь, начнет меня на пути к исправлению.

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