#c #design-patterns #opengl
#c #шаблоны проектирования #opengl
Вопрос:
В настоящее время я начинаю разбираться с OpenGL. Я начал с GLUT, но решил «перейти» на библиотеки SFML. SFML на самом деле предоставляет еще меньше утилит GL, чем GLUT, но является переносимым и предоставляет некоторые другие функциональные возможности. Так что на самом деле это только я, GL и GLU. Да, я любитель наказаний.
Я хотел спросить о стратегиях, которые люди используют для управления такими вещами, как изменения матрицы, изменения цвета, изменения материала и т.д.
В настоящее время я выполняю рендеринг из одного потока, следуя философии проектирования «Голых объектов». ie. У каждого графического объекта есть Render()
функция, которая выполняет работу по рисованию самой себя. Эти объекты сами по себе могут быть совокупностями других объектов или совокупностями графических примитивов. Когда вызывается конкретное Render()
, у него нет информации о том, какие преобразования / существенные изменения были вызваны до этого (что, безусловно, хорошо).
По мере развития событий я остановился на определенных стратегиях, таких как предоставление каждой функции обещания нажимать, а затем извлекать матрицы, если они выполняют какие-либо преобразования. С другими настройками я явно устанавливаю все, что требуется перед вызовом glBegin()
, и ничего не принимаю как должное. Проблемы возникают, когда одна функция визуализации вносит некоторые изменения в менее распространенные переменные состояния, и я начинаю рассматривать возможность использования некоторого RAII для принудительного отмены всех изменений состояния, сделанных в области видимости. Использование OpenGL иногда сильно напоминает мне программирование на ассемблере.
Чтобы сохранить все это управляемым и помочь в отладке, я обнаружил, что практически разрабатываю свою собственную оболочку OpenGL, поэтому я подумал, что было бы неплохо услышать о стратегиях, которые использовали другие, или мыслях и соображениях по этому вопросу. Или, может быть, просто пришло время переключиться на что-то вроде библиотеки графов сцен?
Обновление: 13/5/11
Теперь, изучив рендеринг с использованием массивов вершин / нормалей / цветов и VBO, я решил объединить все фактические коммуникации OpenGL в отдельный модуль. Процесс рендеринга будет состоять в получении загрузки независимых от GL пространственных / материальных данных из моих объектов и последующей передаче всей этой информации в OpenGL в интерпретируемом формате. Это означает, что вся обработка необработанного массива и манипулирование состоянием будут объединены в одну область. Это добавляет дополнительную косвенность и небольшие накладные расходы на вычисления в процессе рендеринга, но это означает, что я могу использовать один VBO / array для всех своих данных, а затем передавать все это сразу, один раз за кадр, в OpenGL.
Комментарии:
1. Это хороший вопрос, и вас также может заинтересовать gamedev.stackexchange.com . Что касается вашего вопроса, это выше моего понимания, но заставляет меня захотеть вернуться к программированию игр. Удачи
Ответ №1:
Так что на самом деле это только я, GL и GLU
Я не вижу в этом ничего плохого. Я бы даже избавился от GLU, если это возможно.
С другими настройками я явно устанавливаю все, что требуется, перед вызовом glBegin() и ничего не принимаю как должное.
Также это хорошая стратегия, но, конечно, вы должны свести дорогостоящие переключатели состояний к минимуму. Вместо немедленного режима (glBegin / glEnd) вам следует перейти на использование массивов вершин и, при наличии, объектов буфера вершин.
Проблемы возникают, когда одна функция визуализации вносит некоторые изменения в менее распространенные переменные состояния, и я начинаю рассматривать возможность использования некоторого RAII для принудительного отмены всех изменений состояния, сделанных в области видимости.
Более старые версии OpenGL предоставляют вам стек атрибутов с функциями доступа к glPushAttrib / glPopAttrib и glPushClientAttrib / glPopClientAttrib для состояний клиента.
Но да, огромное пространство состояний старых версий OpenGL было одной из основных причин сокращения OpenGL-3; то, что было покрыто множеством состояний конвейера фиксированных функций, теперь настраивается и доступно через шейдеры, где каждый шейдер инкапсулирует то, что могло бы быть десятками значений переменных состояния OpenGL.
Использование OpenGL иногда сильно напоминает мне программирование на ассемблере.
Это совсем не удивительно, поскольку самое первое воплощение OpenGL было разработано с учетом некоторой абстрактной машины (реализации), на которой вызовы OpenGL являются своего рода операционными кодами этой машины.
Комментарии:
1. Спасибо за предложения по
glPushAttrib()
иPopAttrib()
. Я думаю, что некоторый RAII в сочетании с этими командами должен немного упростить управление состоянием. Тогда сложность будет в том, чтобы не переусердствовать. Массивы вершин и VBO являются следующими в моем списке целей. Могу ли я спросить, почему вы упомянули «Я бы даже избавился от GLU» ?2. @EdF: Из-за простого факта, что GLU устарел и больше активно не поддерживается. Также, насколько мне известно, все существующие реализации GLU используют немедленный режим, что означает, что он не работает с профилем ядра OpenGL-3/4.
3. @EdF: Если вы собираетесь делать это через систему RAII, я не вижу причин реализовывать это через атрибут gl{Push, Pop}[Client]. Я бы реализовал это с помощью шаблонного механизма, где рассматриваемое состояние является параметром шаблона; в конструкторе запрашивается рассматриваемое состояние, в деструкторе устанавливается его обратно; также допускается цепочка состояний, так что вызов одного «повторного набора» повторяется по цепочке, снова устанавливая все состояния.
4. Я понимаю, что нажатие и выскакивание на стороне «сервера» лучше, чем запрос, а затем сброс значений самостоятельно. Я упускаю какое-то понимание здесь?
5. Атрибуты, с помощью которых можно передавать, имеют всего несколько битов, они на самом деле не потребляют много пропускной способности, так что выигрыша очень, очень мало.
Ответ №2:
Во-первых, постарайтесь не использовать вызовы glBegin / glEnd для новой разработки. Они устарели в OpenGL 3 и просто не работают в OpenGL ES (iOS, WebOS, Android). Вместо этого используйте массивы вершин и VBO для консолидации вашего чертежа.
Во-вторых, вместо того, чтобы писать свою собственную оболочку, взгляните на некоторые недавние программы с открытым исходным кодом, чтобы увидеть, как они работают. Например, ознакомьтесь с библиотекой визуализации (http://www.visualizationlibrary.com/jetcms /). Это довольно тонкая оболочка вокруг OpenGL, так что на нее стоит взглянуть.