Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
калачева перевод.docx
Скачиваний:
2
Добавлен:
01.07.2025
Размер:
237.97 Кб
Скачать

Раздельные объекты шейдеров

Продвинутый уровень

До версии 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()).