ОБНОВЛЕНИЕ: Поскольку мне что-то нужно было сразу, я создал простую оболочку шейдера, которая выполняет то, что мне нужно. Вы можете найти его здесь: ShaderManager на GitHub . Обратите внимание, что он разработан для Objective-C / iOS, поэтому может быть полезен не всем. Если у вас есть предложения по улучшению дизайна, дайте мне знать!
Исходная проблема:
Я новичок в использовании шейдеров GLSL. Я достаточно знаком с языком GLSL и интерфейсом OpenGL, но у меня возникли проблемы с проектированием простого API для использования шейдеров.
Интерфейс C OpenGL для взаимодействия с шейдерами кажется громоздким. Кажется, я не могу найти в сети каких-либо руководств по разработке API для таких вещей.
У меня такой вопрос: есть ли у кого-нибудь хороший, простой дизайн API или шаблон для обертывания шейдера OpenGL программный API?
Возьмем следующий простой пример. Скажем, у меня есть один вершинный шейдер, который просто имитирует фиксированную функциональность, и два фрагментных шейдера - один для рисования сглаженных прямоугольников и один для рисования сглаженных кругов. У меня есть следующие файлы:
Shader.vsh : Simple vertex shader, with the following inputs/outputs:
-- Uniforms: mat4 Model, mat4 View, mat4 Projection
-- Attributes: vec4 Vertex, vec2 TexCoord, vec4 Color
-- Varying: vec4 vColor, vec2 vTexCoord
Square.fsh : Fragment shader for drawing squares based on tex coord / color
Circle.fsh : Fragment shader for drawing circles based on tex coord / color
Каков стандартный способ их использования? Могу ли я связать вышеперечисленные шейдеры с двумя программами шейдеров OpenGL? То есть:
Shader.vsh + Square.fsh = SquareProgram
Shader.vsh + Circle.fsh = CircleProgram
Или я вместо этого создаю одну большую программу, в которой шейдеры фрагментов проверяют некоторые условные однородные переменные и вызывают функцию шейдера для генерации их результата. Например:
Shader.vsh + Square.fsh + Circle.fsh + Main.fsh = ShaderProgram
//Main.fsh here would simply check whether to call out to square or circle
С двумя отдельными программами мне, вероятно, нужно будет вызывать
glUseProgram(CircleProgram); or glUseProgram(SquareProgram);
перед каждым типом элемента, который я хочу нарисовать. Затем мне нужно будет установить униформу (Модель / Вид / Проекция) и атрибуты каждой программы, прежде чем я буду ее использовать. Это кажется таким громоздким.
С единственной опцией ShaderProgram мне все равно нужно будет установить какой-то логический переключатель (круг или квадрат) во фрагментном шейдере, который будет проверяться перед отрисовкой каждого пикселя. Это тоже кажется сложным.
В качестве примечания, могу ли я связать два фрагментных шейдера, каждый с функцией main () в одну программу шейдера? Как OpenGL узнает, какой из них вызывать?
Вызовы:
glUniform*
glVertexAttribPointer
Используются для установки униформ и местоположений указателей атрибутов в текущей программе.
Различные классы и структуры могут нуждаться в доступе и установке переменные в текущем шейдере (или изменить текущий шейдер) из разных мест кода. Я не могу придумать хороший способ сделать это, чтобы отделить код шейдера от кода, который хочет его использовать.
То есть каждая фигура, которую я хочу нарисовать, должна будет установить атрибуты координат вершины и текстуры - требуя дескрипторы этих атрибутов, сгенерированных OpenGL.
Камера должна будет установить свою матрицу проекции как униформу в вершинном шейдере, в то время как класс, управляющий стеком матриц модели, должен будет установить свою собственную униформу в вершинном шейдере.
Изменение шейдеров на полпути к рисованию сцены будет означать, что всем этим классам нужно будет снова установить свои униформы и атрибуты.
Как большинство людей строят проекты вокруг этого?
Глобальный словарь шейдеров, доступ к которому осуществляется дескриптором или имя, с геттерами и сеттерами для их параметров?
Объектно-ориентированный проект с шейдерными объектами, каждый из которых имеет параметры?
Я посмотрел на следующие оболочки:
Чайник Джона: GLSL Shader Manager - Это обертывает шейдеры в классы C ++. Похоже, что это не что иное, как оболочка, которая реализует принципы объектно-ориентированного программирования в C API, в результате чего API C ++ почти такой же.
Мне нужен какой-либо дизайн, упрощающий использование программ шейдеров, и меня это не волнует. о конкретной используемой парадигме (OO, процедурная, и так далее)