Как я могу выследить эти вызовы 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()) между ними, но сброс найденных изменений не имел значения. Было бы очень полезно, если бы я знал, что искать. Если кто-то чувствует себя безумным, у меня также есть следы стека:

Изменить 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(), а также когда он начинает рисовать свои элементы... но вы должны выключать его всякий раз, когда возвращаете управление:

  1. QPainter рисует вещи (DEPTH_TEST = off)
  2. OSG рисует вещи (DEPTH_TEST = on)
  3. QPainter рисует больше вещей [ожидает DEPTH_TEST = off]

Правильные журналы трассировки показали, что я этим не занимался...

glDisable(GL_DEPTH_TEST)

Может быть, вам просто нужно включить GL_TEXTURE_2D? Я заметил в вашем примере с текстурами, которые OSG включает, а затем отключает GL_TEXTURE_2D. Таким образом, разница между вашими двумя случаями (с текстурой и без) заключается в том, что тот, который использует текстуры, заканчивается с отключенным текстурированием, а тот без текстурирования оставляет GL_TEXTURE_2D в своем исходном состоянии.

Если Qt требует / ожидает, что текстурирование включено для рисования квадратов, это может привести к тому, что ничего не появится.

Другие вопросы по тегам