ОБНОВЛЕНИЕ: Поскольку мне нужно что-то сразу, я создал простую обертку шейдера, которая делает то, что мне нужно.Вы можете найти его здесь: ShaderManager на GitHub .Обратите внимание, что он предназначен для Objective-C / iOS, поэтому может быть полезен не всем.Если у вас есть предложения по улучшению дизайна, пожалуйста, дайте мне знать!
Исходная проблема:
Я новичок в использовании шейдеров GLSL.Я достаточно знаком с языком GLSL и интерфейсом OpenGL, но у меня возникают проблемы при разработке простого API, с помощью которого можно использовать шейдеры.
Интерфейс C OpenGL для взаимодействия с шейдерами кажется громоздким.Я не могу найти какие-либо учебники в сети, которые бы касались дизайна API таких вещей.
У меня такой вопрос: есть ли у кого-нибудь хороший, простой дизайн API или шаблон для переноса?API шейдерной программы OpenGL?
Возьмем следующий простой пример.Скажем, у меня есть один вершинный шейдер, который просто эмулирует фиксированную функциональность, и два фрагментных шейдера - один для рисования гладких прямоугольников и один для рисования гладких кругов.У меня есть следующие файлы:
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
Используются для установки униформ и расположения указателей атрибутов на текущемprogram.
Разным классам и структурам может потребоваться доступ и установка переменных в текущем шейдере (или изменение текущего шейдера) из разных мест в коде.Я не могу придумать хороший способ сделать это, чтобы отделить код шейдера от кода, который хочет его использовать.
То есть каждая фигура, которую я хочу нарисовать, должна будет установить атрибуты координат вершины и текстуры- требуя маркеров для этих атрибутов, сгенерированных OpenGL.
Камера должна будет установить свою матрицу проекции как униформу в вершинном шейдере, в то время как класс, управляющий стеком матрицы модели, должен будет установить свою собственную униформу ввершинный шейдер.
Изменение шейдеров в процессе рисования сцены означало бы, что все эти классы должны будут снова установить свои униформы и атрибуты.
Как большинство людей проектируют вокруг этого?
Глобальный словарь шейдеров, доступ к которым осуществляется по дескриптору или имени, с геттерами и сеттерами для их параметров?
OO-дизайн с шейдерными объектами, каждый из которых имеет параметры?
Я посмотрел на следующееОбертки:
Чайник Джона: GLSL Shader Manager - Оборачивает шейдеры в классах C ++.Кажется, это всего лишь оболочка, которая обеспечивает соблюдение принципов ОО в C API, в результате чего API C ++ почти такой же.
Я предпочитаю любой вид проектирования, который упрощает использование программ Shader, именя не волнует конкретная используемая парадигма (ОО, процедурная и т. д.)