OpenGL материал для сетки (шейдер)
Итак, я работаю над простым игровым движком с C++ и OpenGL 4. Сейчас я борюсь с рендерингом импортированных моделей.
Я использую FBX SDK для импорта моделей FBX, используя очень наивный подход: в основном, я посещаю каждый узел FBX и добавляю данные сетки в одну большую структуру, которая позже используется для рендеринга. Однако я хочу иметь возможность указать разные фрагментные шейдеры для каждого материала, используемого моделью (например, разные шейдеры для автомобильных дисков и фар).
В качестве ссылки, UE4 имеет материальную систему, которая позволяет пользователю определять простой шейдер с помощью редактора, похожего на чертеж.
Я хотел бы применить аналогичную концепцию к моему движку, позволяющую создать материальный объект, который определяет фрагмент кода шейдера фрагмента и набор текстур для использования.
Проблемы, с которыми я сталкиваюсь:
- Ясно, что я должен разделить вызовы отрисовки для каждой детали модели, которая использует другой материал, поскольку я не могу поменять местами программу в середине вызова отрисовки (могу ли я?): На этом этапе лучше иметь отдельный vao/vbo/ebo для каждой части или одной и отслеживать, где заканчивается часть и начинается следующая? (Я думаю, это лучший вариант)
- Это хорошая практика, чтобы предварительно скомпилировать только фрагмент шейдера и присоединить его к текущей программе на лету (т.е. glAttach + glLinkProgram + glUseProgram) или лучше предварительно связать всю программу для каждого материала, учитывая, что вершина шейдер всегда один и тот же?
1 ответ
Нет, вы не можете изменить программу во время вызова. Существуют разные мнения и тесты о том, как GPU будет работать на основе макета ваших данных. По моему опыту, если вы не собираетесь изменять данные своей сетки после первой загрузки, наиболее эффективным способом является создание одного VAO с двумя VBO: один для индексов и один для остальных данных. При выполнении вызовов отрисовки вы смещаете буфер индексов на основе данных сетки (которые вы должны отслеживать), а также смещаете конфигурацию атрибутов шейдера. Такой подход обеспечивает более удобный и эффективный доступ к памяти, так как блок памяти будет нестабильным. Однако, как я уже упоминал, бывают случаи, когда этот подход не будет наиболее эффективным (хотя я считаю, что он все еще будет достаточно эффективным). Это зависит от вашего оборудования и драйвера.
Прекомпилируйте и свяжите все ваши программы перед запуском цикла рендеринга. Это самый эффективный подход
В качестве дополнения я бы порекомендовал вам изучить технику шейдеров UBER. Эта методология основана на создании шейдера для различных возможных входов и создании набора defines
или архитектура подпрограмм, которая позволяет вам компилировать разные версии одного и того же шейдера (например, у вас может быть модель с нормальной текстурой, и вы, вероятно, захотите применить рельефное отображение, но другие модели могут не иметь этой текстуры, поэтому выполнение точно такой же шейдер приведет к неопределенному поведению или падению).