Ответ 1
Я прочитал все вопросы о SO, которые я смог найти о qt 4 и 5 opengl. Этот самый ближайший OpenGL против QOpenGL/QtOpenGL в Qt 5: различия и ограничения?, Я понятия не имею, почему он был закрыт, потому что это отличный вопрос. Единственный аспект, который я вижу в нем, - это разница в скорости.
Чтобы быть более конкретным, мне нужно использовать связь physx, tcp/ip и большие числа быстрого обновления вершин и сеток. Цель состоит в том, чтобы сделать это как можно ближе к реальному времени. Такие вещи, как рендеринг, не являются проблемой, но любой бит накладных расходов от qt повреждает. (Все в 3D с С++)
В вашем вопросе есть несколько вопросов.
"Raw" OpenGL vs "Qt" OpenGL
Этот вопрос плохо поставлен, поскольку нет такой вещи, как "Qt OpenGL". OpenGL является стандартом, принадлежащим и опубликованным Khronos. Qt просто использует его.
Что Qt может сделать для вас, помогает вашему приложению управлять несколькими вещами.
Создание окна/контекста
Вы когда-нибудь пробовали создавать контекст OpenGL под Win32? Для этого требуется куча кода котла (см. здесь или здесь), что предполагает создание временного контекста для проверки для возможностей WGL, а затем создать фактический контекст в конце...
Вы когда-нибудь пробовали создать контекст OpenGL в X11? Для этого требуется куча кода котла (см. здесь), который включает проверку наличия GLX_ARB_create_context
, а затем его использование для создания контекста или возврат к GLX 1.3 путь кода и...
Вы когда-нибудь пробовали создать контекст OpenGL в Mac OS X?
Вы когда-нибудь пробовали создавать контекст OpenGL под Android?
Вы когда-нибудь пробовали создать контекст OpenGL в QNX?
Вы когда-нибудь пробовали создавать контекст OpenGL в DirectFB/EGLFS?
Ой, подождите. Здесь это Qt:
class Window : public QWindow {
QOpenGLContext *context;
public:
Window() {
QSurfaceFormat format;
format.setVersion(3,3);
format.setProfile(QSurfaceFormat::CoreProfile);
setSurfaceType(OpenGLSurface);
setFormat(format);
create();
context = new QOpenGLContext;
context->setFormat(format);
context->create();
}
...
Да, это все. Это создает окно OpenGL (toplevel) и контекст основного профиля 3.3. Объедините его с QTimer, и у вас есть жизнеспособный рендерер. Что, конечно, будет работать на всех вышеперечисленных платформах: Win32, Mac, X11, Linux/EGLFS, QNX, iOS, Android.
Есть ли накладные расходы, которые вы должны заплатить за все это? Да, конечно. Но это абсолютно ничтожно; и вы платите за него только один раз, т.е. при создании окна и контекста.
Реальный тяжелый материал происходит из самого чертежа OpenGL, который полностью находится под вашим контролем: вы делаете контекст актуальным в окне и начинаете выдавать необработанные команды OpenGL. Qt здесь не так. Единственный момент, когда Qt и OpenGL снова соберутся, будут в буферах подкачки; но это операция, которая практически не требует затрат.
Итак: Qt не добавляет никаких измеримых служебных данных.
Управление окнами
Конечно, в комплекте с вышесказанным приходит тот факт, что вы можете f.i. управляйте клавиатурой и мышью с идентичным кодом на любой из этих платформ. Или измените размер окна. Или сделайте это в полноэкранном режиме. Или закройте его.
Помощники OpenGL
Qt не "просто" предлагает способ создания поверхности и контекста OpenGL (и связанных с ним операций: устанавливать как текущий, swap-буферы и т.д.). Он идет (много) дальше и предлагает целый ряд вспомогательных классов и функций:
- QMatrix4x4 - это... 4x4 матрица. У вас есть все хорошие функции, которые вам нужны в программе OpenGL:
lookAt()
,ortho()
,perspective()
,normalMatrix()
и т.д. - QOpenGLContext:: hasExtension и QOpenGLContext:: getProcAddress - это независимые от платформы способы разрешения точек входа OpenGL.
- QOpenGLContext:: versionFunctions возвращает объект, содержащий всю точку входа OpenGL для уже разрешенной версии или профиля.
- QOpenGLBuffer обертывает объект буфера.
- QOpenGLVertexArrayObject обертывает объект массива вершин (и имеет помощник RAII для связывания и развязывания VAO).
- QOpenGLTexture обертывает объект текстуры.
- QOpenGLFrameBufferObject обертывает объект буфера фрейма.
- QOpenGLShader и QOpenGLShaderProgram завершают шейдеры и шейдерные программы, предлагая удобные методы для f.i. устанавливая QMatrix4x4 как единую переменную. Таким образом, вы можете вычислить MVP для заданной сетки на процессоре, используя упомянутые выше методы, затем установите ее как единую.
- QOpenGLDebugLoggerwraps
GL_KHR_debug
для отладки ваших приложений OpenGL. - и еще одна группа вещей, которые я сейчас не помню.
Есть ли накладные расходы? Да, но еще раз он минимален, а не включает, как вы используете эти объекты в своем коде OpenGL. Если ваш код OpenGL является быстрым и хорошо структурированным, вы найдете эти помощники полезными для его управления, и они не заставят его работать медленнее.
(Пример "полезно для управления": QOpenGLVertexArrayObject позволит вам использовать VAO на OpenGL 3.0 или на любой версии OpenGL для рабочего стола, где присутствует расширение GL_ARB_vertex_array_object
, или на OpenGL ES2, если GL_OES_vertex_array_object
присутствует. Вам не нужно разрешать правильный набор функций в зависимости от времени выполнения. Qt сделает это для вас и предоставит те же API для создания, связывания, освобождения и уничтожения VAO).
Все ли хорошо? Нет. Я должен быть честным здесь, есть бит и болты, которые выиграют от какой-то любви.
Например, QOpenGLFrameBufferObject имеет ограниченный API, не поддерживающий f.i. любое количество цветных вложений. QOpenGLBuffer потребует некоторой работы для поддержки большего количества типов буферов/привязок. По-прежнему нет поддержки программных конвейеров. Не поддерживается поддержка равномерных буферов.
С другой стороны, у вас есть такие вещи, как QOpenGLTexture, которая поддерживает довольно недавние функции, такие как неизменяемые виды хранения и текстуры.
Означает ли это, что вы не можете использовать эти функции? Конечно вы можете. Просто вернитесь к необработанному OpenGL-коду, если вам нужны функции Qt, которые не дают вам прямо сейчас. Или, рассмотрите предоставляя эти функции Qt!
Qt
Конечно, как только вы идете по пути Qt, у вас есть Qt. Это означает, что в библиотеках QtCore и QtGui:
- циклов событий
- таймеры
- сигналы и слоты
- темы
- Строки Unicode + i18n
- контейнеры
- регулярные выражения
- обработка файлов
- Загрузка плагинов
- Настройки
- MIMETYPES
- обработка ввода
- image I/O
- 2d обязательная окраска с использованием растрового движка
- JSON
- XML
- и еще одна группа вещей, которые я сейчас не помню.
Конечно, все вышеперечисленное относится к кросс-платформе.
Кстати, Qt также имеет:
- QtWidgets для межплатформенных виджетов 2d
- QtSql для доступа к БД
- QtNetwork для сокетов TCP/UDP/SSL, а также высокоскоростной HTTP/FTP-движок
- QtTest для модульных тестов
- QtWebkit для встраивания webkit
- и еще одна группа вещей, которые я не помню прямо сейчас.
OpenGL в Qt 4 против 5
Существуют ли какие-либо огромные различия между обработкой OpenGL в Qt 4 и Qt 5? Не совсем...
В Qt 4 классом, используемым для рендеринга OpenGL, был QGLWidget. Он жил в модуле QtOpenGL (а не в QtGui - помните, что в Qt 4 виджеты тоже жили в QtGui). Кроме того, на самом деле подмножество помощников Qt 5 OpenGL, перечисленных выше, было доступно там под именем QGLFoo
(f.i. QGLBuffer
вместо QOpenGLBuffer
).
В Qt 5 модуль QtOpenGL все еще существует, чтобы поддерживать работу старых приложений. Но:
-
QtGui и QtWidgets были разделены. QtGui теперь содержит бит низкого уровня для обработки WM, создания GL-контекстов и поверхностей, рисования 2d и, в основном, материалов, перечисленных выше. QtWidgets вместо этого содержит сами виджеты.
-
QtOpenGL все еще содержит классы QGL *, но теперь ссылки на QtWidgets (так как он содержит QGLWidget). Это означает, что использование QGLWidget означает, что вы будете ссылаться на какую-то большую библиотеку, даже если вы вообще не используете виджеты (потому что f.i. ваше приложение является чистым OpenGL).
-
Как я уже говорил, QtGui достаточно для создания полного окна OpenGL. Но что, если вы хотите встроить его в приложение на основе виджетов? Затем вы можете использовать QGLWidget или встраивать QWindow через
QWidget::createWindowContainer
. Помимо QGLWidget, вы не должны использовать какой-либо другой класс QtOpenGL (т.е. QGL). Используйте аналоги в QtGui (то есть классы QOpenGL). -
Все вышеперечисленные классы QOpenGL * находятся в QtGui, а не в QtOpenGL; и они больше, чем аналоги QGL * (например, нет QGLVertexArrayObject), у них больше возможностей (например, QOpenGLShader поддерживает геометрию и шейдеры тэсселяции, QGLShader - нет) и, в общем, те, которые нужно использовать (поскольку они будут видеть исправления и улучшения, QGL * не будет).
-
Учитывая, что теперь QtGui предлагает поддержку OpenGL, было бы естественно ожидать, что замена QGLWidget появится непосредственно в QtWidgets. И действительно, это будет, надеюсь, в 5.4 (подготовительная работа идет в 5.3, но, к сожалению, сама функция пропустит замораживание функции).
Есть ли причина ожидать огромной разницы в производительности между Qt 4 и Qt 5? Нет. Я ожидаю, что ваш код GL будет работать точно так же. В конце концов Qt на самом деле не мешает вам.
Desktop GL/ES 2
Вы можете скомпилировать Qt 5 с поддержкой "Desktop GL" или "ES 2" с помощью таймера настройки времени. Очевидно, это изменит, какие заголовки QtGui будут использовать при компиляции, и к каким библиотекам он будет привязан (libGL или libGLES2 и т.д.). Он также изменит формат по умолчанию: вышеуказанный код QWindow создаст хорошую поверхность OpenGL ES2 (и, вероятно, не сможет создать контекст, так как нет OpenGL ES 3.3, ну хорошо).
Но вы понимаете: с помощью того же кода вы также можете поддерживать ES2.
Проблема (на мой взгляд) заключается в том, что она также изменит некоторые другие более тонкие вещи: например, QOpenGLShader вставляет некоторые макросы, такие как
#define highp
#define mediump
#define lowp
перед всеми вашими шейдерами, если вы используете Desktop GL. Причина в том, что он позволяет повторно использовать одни и те же шейдеры в ES2 и Desktop GL, в которых отсутствуют определители точности; поэтому они стираются через макросы, которые расширяются до нуля.
Я думаю, что эти мелочи на самом деле не выигрыш. Возможно, они уменьшают поддержку очень маленьких и простых шейдеров (и программ, созданных только вершинным и афрагментарным шейдером). Было бы лучше, если бы Qt старался быть настолько умным.
Но ваш путь к коду Desktop GL может использоваться с несколькими этапами шейдеров; или, как правило, использовать функции, недоступные на ES2. В конечном счете, это значительно расходится с вашим кодом кода ES2. (Подумайте, что в 3.3 Core вы должны использовать VAO, в то время как ES2 сам по себе не знает, что такое VAO.)
Личный разбор: я ненавижу, ненавижу, ненавижу тот факт, что ES2 не похожа на профиль OpenGL или так, и вместо этого сидит сама по себе. И нужно, по сути, иметь разложенную базу кода, чтобы сделать ES2 счастливой. Бах бах бах.
Окна
Введите мир боли!, также известный как статус драйвера OpenGL в Windows.
В принципе, все, кроме NVIDIA, ломают OpenGL-драйверы в Windows.
По крайней мере, "из коробки". Обновление драйверов обычно работает, но вы не всегда можете попросить пользователей обновить свои драйверы. Это конечные пользователи, а не про-геймеры. Возможно, у них даже нет привилегий администратора.
Это проблема для приложений OpenGL и особенно для одного из самых сильных инструментов Qt: Qt Quick 2. Qt пытается обойти эту проблему, используя ANGLE, который является слоем трансляции OpenGL ES2 → Direct3D. Итак, под Windows у вас есть выбор между
- Рабочий стол OpenGL build
- сборка OpenGL ES2 через ANGLE
Варианты не равны - ES2, конечно, означает забыть о том, что делает какой-либо серьезный Modern GL. Но кроме этого, причины для перехода в одну сторону или другую доступны здесь.
Qt Quick 2
Это важно, и я думаю, что заслуживает отдельного внимания.
Но сначала давайте выясним: нужно ли использовать Qt Quick 2 для создания приложения OpenGL под Qt? NO, NO и NO. Qt Quick 2 - полностью независимая технология, которая также использует OpenGL для рендеринга. Таким образом, вы можете игнорировать его и просто создавать свое приложение OpenGL.
Но что такое Qt Quick 2? Это библиотека, построенная поверх QML-языка, декларативный язык, созданный для создания динамических пользовательских интерфейсов (и теперь используемых для систем сборки... ну хорошо).
Помните о различии: QML - это язык, Qt Quick 2 - это библиотека с набором визуальных элементов (и API С++ для создания собственного), которые вы программируете в QML.
Бывает, что Qt Quick 2 использует OpenGL для рисования этих визуальных элементов. Это гарантирует хорошие результаты без потери качества 60 FPS, очень низкое использование ЦП, все виды шейдеров на основе глаз и т.д.
И что? Ну, вам может быть интересно дать ему удар. Например, API позволяет накладывать на любой чистый контент OpenGL, который вы рисуете. Таким образом, вы можете подумать о том, чтобы использовать Qt Quick 2 для передачи более традиционных пользовательских битов - кнопок, слайдеров и т.д., В то время как вы сохраняете контроль над рендерингом основного контента.
Или вы можете просто игнорировать тот факт, что он существует, и продолжать играть с OpenGL.