OpenGL материал для сетки (шейдер)

Итак, я работаю над простым игровым движком с C++ и OpenGL 4. Сейчас я борюсь с рендерингом импортированных моделей.

Я использую FBX SDK для импорта моделей FBX, используя очень наивный подход: в основном, я посещаю каждый узел FBX и добавляю данные сетки в одну большую структуру, которая позже используется для рендеринга. Однако я хочу иметь возможность указать разные фрагментные шейдеры для каждого материала, используемого моделью (например, разные шейдеры для автомобильных дисков и фар).

В качестве ссылки, UE4 имеет материальную систему, которая позволяет пользователю определять простой шейдер с помощью редактора, похожего на чертеж.

Я хотел бы применить аналогичную концепцию к моему движку, позволяющую создать материальный объект, который определяет фрагмент кода шейдера фрагмента и набор текстур для использования.

Проблемы, с которыми я сталкиваюсь:

  1. Ясно, что я должен разделить вызовы отрисовки для каждой детали модели, которая использует другой материал, поскольку я не могу поменять местами программу в середине вызова отрисовки (могу ли я?): На этом этапе лучше иметь отдельный vao/vbo/ebo для каждой части или одной и отслеживать, где заканчивается часть и начинается следующая? (Я думаю, это лучший вариант)
  2. Это хорошая практика, чтобы предварительно скомпилировать только фрагмент шейдера и присоединить его к текущей программе на лету (т.е. glAttach + glLinkProgram + glUseProgram) или лучше предварительно связать всю программу для каждого материала, учитывая, что вершина шейдер всегда один и тот же?

1 ответ

Решение
  1. Нет, вы не можете изменить программу во время вызова. Существуют разные мнения и тесты о том, как GPU будет работать на основе макета ваших данных. По моему опыту, если вы не собираетесь изменять данные своей сетки после первой загрузки, наиболее эффективным способом является создание одного VAO с двумя VBO: один для индексов и один для остальных данных. При выполнении вызовов отрисовки вы смещаете буфер индексов на основе данных сетки (которые вы должны отслеживать), а также смещаете конфигурацию атрибутов шейдера. Такой подход обеспечивает более удобный и эффективный доступ к памяти, так как блок памяти будет нестабильным. Однако, как я уже упоминал, бывают случаи, когда этот подход не будет наиболее эффективным (хотя я считаю, что он все еще будет достаточно эффективным). Это зависит от вашего оборудования и драйвера.

  2. Прекомпилируйте и свяжите все ваши программы перед запуском цикла рендеринга. Это самый эффективный подход

В качестве дополнения я бы порекомендовал вам изучить технику шейдеров UBER. Эта методология основана на создании шейдера для различных возможных входов и создании набора defines или архитектура подпрограмм, которая позволяет вам компилировать разные версии одного и того же шейдера (например, у вас может быть модель с нормальной текстурой, и вы, вероятно, захотите применить рельефное отображение, но другие модели могут не иметь этой текстуры, поэтому выполнение точно такой же шейдер приведет к неопределенному поведению или падению).

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