Как я могу выследить эти вызовы OpenGL, которые искажают объекты в моей сцене?
Я смешиваю две библиотеки, которые используют OpenGL: Qt и OpenSceneGraph. Я ориентируюсь на OpenGL ES 2, поэтому все делается с помощью шейдеров и вызовов, совместимых с ES 2.
Я специально использую OSG с QtDeclarative, пытаясь нарисовать OSG на QDeclarativeItem. Я делаю это способом, предложенным в документации Qt: обернуть все вызовы OpenGL между beginNativePainting()/endNativePainting().
Это работает нормально, пока я не использую текстуры в моей сцене OpenSceneGraph. Когда я делаю это, мое окно QML "запутывается" из-за отсутствия лучшего слова. Чтобы сделать его максимально простым, моя сцена OSG состоит из плоскости с наложенной на нее текстурой. Я воссоздал сцену, используя базовые вызовы OpenGL, и проблема больше не возникает. Вот проблема, обобщенная в виде набора картинок:
- Движок QtDeclarative использует OpenGL для рисования. Я установил простую страницу QML:
- Я создаю простую сцену, используя OpenGL напрямую. Это самолет с нарисованной на нем текстурой.
- Сейчас я пытаюсь настроить ту же сцену в OSG... идентичные шейдеры и т. Д.
Вы можете видеть что-то странное, что происходит на последнем скриншоте. Не беспокойтесь о черном фоне, где исходная сцена OpenGL была прозрачной, это просто OSG с использованием черного прозрачного цвета. Проблема в том, что другие элементы, настроенные с помощью QML (прямоугольники), испорчены.
Редактировать: чтобы прояснить, что происходит: прямоугольники, которые я рисую с помощью QML, растянуты до правого края экрана. Я также заметил, что если я рисую прямоугольники после элемента OpenSceneGraph в QML, они не отображаются (раньше я этого не замечал). Я рисую пурпурно-черный прямоугольник после элемента OSG на следующих снимках экрана... обратите внимание, что он исчезает. Может быть, происходит больше странных вещей, но это все, что я наблюдал, играя с прямоугольниками.
До
После
Я довольно новичок в OpenGL, поэтому я не знаю, какие настройки вызова / состояния могут вызвать что-то подобное. Я думаю, что OpenSceneGraph делает некоторые изменения состояния OpenGL, которые портят движок рисования Qt. Я также знаю, что это происходит только тогда, когда OSG использует текстуры... если я не применяю текстуры в моей сцене OSG, этого не происходит. Вот где я застрял.
Кроме того, я попытался использовать BuGLe, чтобы получить трассировку вызовов OpenGL с включенными и не включенными текстурами в OSG, чтобы выяснить, могу ли я выяснить проблемные изменения состояния. Я обнаружил несколько различий, и даже какое-то глобальное состояние, в котором OSG изменился (например, glPixelStorei()) между ними, но сброс найденных изменений не имел значения. Было бы очень полезно, если бы я знал, что искать. Если кто-то чувствует себя безумным, у меня также есть следы стека:
- OSG с текстурированием: http://pastie.org/4223182 (текстура текстур osg - строки 637 ~ 650)
- OSG без текстурирования: http://pastie.org/4223197
Изменить 2: Вот разница, которая может быть полезна. Вам нужно будет прокрутить путь вниз до того, как появятся соответствующие строки. http://www.mergely.com/nUEePufa/
Редактировать 3: Вау! Ладно, эта разница мне очень помогла. OSG включает VertexAttribArray 3, но не отключает его. Вызов glDisableVertexAttribArray(3) после того, как OSG визуализирует свой фрейм, кажется, частично решает проблему; больше нет растяжения прямоугольников QML. Однако прямоугольники, нарисованные после элемента OSG, по-прежнему не отображаются.
2 ответа
После изучения журналов трассировки, я думаю, что обнаружил две вещи OpenGL, которые необходимо сбросить перед передачей управления обратно в Qt, чтобы вышеуказанные проблемы исчезли. Я упомянул один в редактировании... Я обобщу оба в этом ответе.
Искажение прямоугольника /QML
QPainter напрямую использует атрибуты вершин 3, 4 и 5 для чего-то похожего на геометрию этих прямоугольников. Это можно увидеть в след:
[INFO] trace.call: glVertexAttrib3fv(3, 0x2d94a14 -> { 0.00195312, 0, 0 })
[INFO] trace.call: glVertexAttrib3fv(4, 0x2d94a20 -> { 0, -0.00333333, 0 })
[INFO] trace.call: glVertexAttrib3fv(5, 0x2d94a2c -> { 0.2, 0.4, 1 })
Отключение соответствующих массивов атрибутов вершин решает проблему растягивающихся прямоугольников:
glDisableVertexAttribArray(3);
glDisableVertexAttribArray(4);
glDisableVertexAttribArray(5);
Элементы, нарисованные после элемента OSG, не отображаются
Оглядываясь назад, это было легко и не имело никакого отношения к текстурированию. Я не заметил этого до того, как попытался добавить текстуры в мою сцену, поэтому смешение этих двух вопросов было моей ошибкой. Я также облажался со следами и различиями, которые я отправил; Я никогда не обновлял их, чтобы учесть проблему заказа после того, как я обнаружил это (извините!)
В любом случае, QPainter ожидает, что тестирование глубины будет отключено. Qt выключит тестирование глубины, когда вы вызываете beginNativePainting(), а также когда он начинает рисовать свои элементы... но вы должны выключать его всякий раз, когда возвращаете управление:
- QPainter рисует вещи (DEPTH_TEST = off)
- OSG рисует вещи (DEPTH_TEST = on)
- QPainter рисует больше вещей [ожидает DEPTH_TEST = off]
Правильные журналы трассировки показали, что я этим не занимался...
glDisable(GL_DEPTH_TEST)
Может быть, вам просто нужно включить GL_TEXTURE_2D? Я заметил в вашем примере с текстурами, которые OSG включает, а затем отключает GL_TEXTURE_2D. Таким образом, разница между вашими двумя случаями (с текстурой и без) заключается в том, что тот, который использует текстуры, заканчивается с отключенным текстурированием, а тот без текстурирования оставляет GL_TEXTURE_2D в своем исходном состоянии.
Если Qt требует / ожидает, что текстурирование включено для рисования квадратов, это может привести к тому, что ничего не появится.