Используйте однородные буферы (то есть постоянные буферы в D3D Lingo).
Пока все ваши шейдеры согласовывают расположение и точку привязки каждого такого буфера, обновление становится быстрым. Моделям вообще не нужно ничего знать о шейдерах. Им нужно только обновить матрицу вида модели в своем постоянном буфере, и конвейер рендеринга будет использовать ее автоматически.
Как минимум, я бы сказал, что у вас должно быть два таких буфера. Первый должен хранить вашу матрицу проекции, матрицу камеры, сцепленную матрицу проекции камеры, информацию о области просмотра, подробные сведения о кадре и обратные матрицы. Вам нужно обновить этот буфер только один раз для каждой сцены.
Затем дайте каждой модели другой буфер для хранения ее матрицы вида модели, нормальной матрицы, инверсий и свойств материала. Это обновляется один раз для каждой модели и может быть выполнено на другом этапе обновления (если / когда это необходимо). Информация о материале может / должна быть перемещена в третий буфер для конкретного материала, если у вас есть возможность обмениваться материалами между несколькими объектами.
В настройке с передним затенением имеет смысл поместить все источники света в другой буфер, а при отложенном затенении также имеет смысл использовать буфер для каждого источника света для прохода света (вместо буфера модели / материала, используемого в геометрия прохода).
Обратите внимание, что вам нужна умеренно современная версия GL, чтобы вообще использовать унифицированные буферы (3.1 или расширение; достаточно распространенное сегодня, за исключением некоторых старых, но все еще работающих ноутбуков), и вам нужна довольно свежая версия, чтобы возможность привязывать одинаковые буферы к определенным местам привязки из кода шейдера (4.2; все еще необычно, но становится все лучше), в противном случае вам придется проделать большую работу в коде на стороне ЦП, чтобы все настроить (код ЦП должен знать правильную привязку в любом случае, это скорее запах API, чем серьезная проблема). OpenGL | ES не добавлял унифицированные буферы до версии 3.0, которая, к сожалению, до сих пор не поддерживается на большинстве популярных мобильных платформ.
Если буферы недоступны, вам понадобится глобальное место для хранения местоположений индекса для активного шейдера. Вы можете использовать glGetUniformLocation
после загрузки своего шейдера, чтобы найти индексы для известных имен (например, ModelViewMatrix
или тому подобное), а затем сохранить эти индексы. Ваш рендер может отображать значения перечисления, например, MODEL_VIEW
передаваемые в функцию- SetUniform
обертку, чтобы посмотреть в связанный шейдер, найти индекс и glUniform
правильно вызвать . Это не очень большое изменение в использовании клиентского кода по сравнению с буферами, за исключением необходимости устанавливать каждую униформу индивидуально, если вы все правильно завершили.
См. GLSL Inteface Blocks и Uniform Buffer Objects .