- •Что такое OpenGl?
- •Первое знакомство с программой OpenGl
- •Синтаксис OpenGl
- •Конвейер визуализации OpenGl
- •Подготовка данных для отправки в OpenGl
- •Вершинные шейдеры
- •Мозаичные шейдеры
- •Наша первая программа: Подробное обсуждение Ввод main()
- •Запуск OpenGl
- •Распределение объектов буфера вершин
- •Инициализация вершинных и фрагментарных шейдеров
- •Наш первый рендеринг в OpenGl
- •Рисование в OpenGl
- •Включение и выключение команд в OpenGl
- •Шейдеры и OpenGl
- •Настраиваемый конвейер OpenGl
- •Обзор OpenGl Shading Language
- •Создание шейдера при помощи glsl Точка отправления
- •Задача переменных
- •Охват переменных
- •Инициализация переменных
- •Сложные типы
- •Получение доступа к элементам матриц и векторов
- •Структуры
- •Квалификаторы хранилищ
- •Заявления
- •Вычислительная инвариантность
- •Глобальные функции компиляции шейдеров
- •Блоки интерфейса
- •Унифицированные блоки
- •Указание унифицированных блоков в шейдере
- •Доступ к унифицированным блокам из приложения
- •Блоки In/Out
- •Компилирование шейдеров
- •Наша функция LoadShaders()
- •Подпрограммы шейдеров
- •Установка подпрограмм glsl
- •Раздельные объекты шейдеров
Раздельные объекты шейдеров
Продвинутый уровень
До версии OpenGL 4.1 (без учета дополнений) только одна программа шейдера могла быть привязана в один момент времени к исполняемой программе. Это было неудобно, особенно если вам нужно было работать с несколькими фрагментарными шейдерами для обработки набора геометрии, которая трансформировалась посредством одного вершинного шейдера. Из-за этого приходилось использовать несколько одинаковых программ одного и того же вершинного шейдера, растрачивая впустую ресурсы и копируя код.
Раздельные объекты шейдеров позволяют разным стадиям шейдеров (напр., вершинному шейдеру) из разных программ собираться в один программный конвейер.
Первым делом нужно создать программу, которую можно использовать в конвейере. Это делается с помощью вызова glProgramParameteri() с параметром GL_PROGRAM_SEPARABLE до привязки в программе шейдера. Это помечает программу шейдера как применимую в конвейере. Для облегчения этой задачи, новая команда, glCreateShaderProgramv(), была добавлена. Эта команда включает в себя процесс компиляции шейдера, вместе с определение программы, как доступной для других программ (как упоминалось выше), и привязывает эту программу для создания конечного объекта.
Когда наборы программ шейдеров будут объединены, вам понадобится использовать конструкторы нового конвейера шейдреров, для объединения стадий шейдеров разных программ в конвейер программ, доступный для использования. Как и со всем объектами в OpenGL, вы используете набор запросов gen-bind-delete. Конвейер шейдеров создается командой glGenProgramPipelines(), которая создаст новый идентификатор программного конвейера, который вы передаёте в glBindProgramPipelines(), делая программу доступной для поправок (напр., добавления или замены стадий шейдинга), а затем и использования. Также как и с другими генерированными объектами, программные конвейеры удаляются запросом glDeleteProgramPipelines().
Когда вы связали программный конвейер, вы можете добавить в него программы, которые были помечены как сепарабельные, к вашему конвейеру вызовом glUseProgramStages(), для этого требуется описание в битовом поле, какие стадии из подключенной программы нужно использовать, когда данный конвейер обрабатывает данные геометрии и делает шейдинг объектов. Более старый glUseProgram() при запросе заменит нынешнюю привязку программного конвейера.
Интерфейсы для разных стадий шейдеров (in и out переменные) должны соответствовать порядку работы конвейера. В отличие от использования шейдера с нераздельными объектами, конвейер шейдеров с раздельными программными объектами нужно проверять на наличие проблем на стадии отрисовки(???). Если инрефейсы не совпадают, все изменяемые переменные (переменные вывода out) будут неопределены.
Встроенный блок gl_PerVertex должен быть переопределен для прямого указания, что будет использоваться подмножество интерфейса закрепленного конвейера. Это необходимо при использовании множества программ в вашем конвейере.
Наример,
out gl_PerVertex {
vec4 gl_Position; // makes gl_Position is part of interface
float gl_PointSize; // makes gl_PointSize is part of interface
}; // no more members of gl_PerVertex are used
Эта команда устанавливает интерфейс шейдера, который должен использовать конвейер на следующей стадии. Это должно быть подмножеством встроенных членов gl_PerVertex. Если встроенные блок используется несколькими программами конвейера, все одни должны заявлять этот блок одинаковым образом.
Поскольку отделяемые объекты могут каждый содержать свой набор униформ программ, существует два метода для назначения значений унифицированных переменных. Сначала вы выбираете активную программу шейдера при помощи glActiveShaderProgram(), тем самым назначив значения унифицированным переменным данной программы шейдера через glUniform*() и glUniformMatrix*(). Или же, что даже лучше, вызываете glProgramUniform*() и glProgramUniformMatrix*(), которые берут определенный объект программы в дополнение к другим использованным для индентификации униформ программы параметрам.
void glProgramUniform{1234}{fdi ui}(GLuint program,
GLint location,
TYPE value);
void glProgramUniform{1234}{fdi ui}v(GLuint program,
GLint location,
GLsizei count,
const TYPE * values);
void glProgramUniformMatrix{234}{fd}v(GLuint program,
GLint location,
GLsizei count,
GLboolean transpose,
const GLfloat * values);
void glProgramUniformMatrix{2x3,2x4,3x2,3x4,4x2,4x3}{fd}v(
GLuint program, GLint location,
GLsizei count,
GLboolean transpose,
const GLfloat * values);
glProgramUniform*() and glProgramUniformMatrix*() routines
operate exactly as glUniform*() and glUniformMatrix*(), except that
program specifies the shader program to update the uniform variable for.
The advantage of these routines is that program need not be the currently
bound program (i.e., the last specified shader program to
glUseProgram()).
