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

Настраиваемый конвейер OpenGl

Глава 1 вкратце описала процесс конвейера визуализации OpenGL. В это главе мы более подробно опишем разные стадии и что делает каждая команда. Ковейер визуализации версии 4.3 содержит 4 стадии обработки данных плюс стадию вычисления, каждую из которых вы выполняете с помощью шейдера.

  1. Вершинный шейдер. Стадия, на которой вершинные данные, указанные вами в вершинном объекте буфера, обрабатывают каждую вершину в отдельности. Эта стадия обязательна для всех программ на OpenGL, и этот шейдер должен быть привязан к программе обязательно. Применение вершинного шейдера мы пишем в Главе 3, “Рисование в OpenGL”.

  2. Мозаичный шейдер. Это необязательная стадия, которая создает дополнительные геометрические данные внутри конвейера OpenGL, а не оставляет на программу определение каждого отдельного геометрического примитива. Если задействована, эта фаза принимает данные вывода со стадии вершинного шейдера и обрабатывает вершины дальше. Мы опишем стадию мозаичного шейдера в Главе 9, “Мозаичные шейдеры”.

  3. Геометрический шейдер. Еще одна необязательная стадия, которая может модифицировать все имеющиеся геометрические данные конвейера OpenGL. Эта стадия работает с геометрическими примитивами по отдельности, позволяя модифицировать их. На этой стадии доступно создание большего количества геометрических данных, основанных на имеющихся примитивах, также возможно изменение типа примитивов (напр., конвертирование треугольников в линии), или даже сброс всей геометрии. Если задействована, эта фаза получает на обработку данные или после того, как вершинный шейдер закончил создание геометрических примитивов и вершин, или после обработки этих данных мозаичным шейдером, если тот был также задействован.

  4. И наконец, последняя стадия обработки в конвейере OpenGL - это фрагментарный шейдер. Эта стадия обрабатывает отдельные фрагменты (или образцы, если задействована модель шейдера образцов), которые генерировал растеризатор OpenGL. Для нее тоже необходима привязка шейдера. На этой стадии вычисляются цвет и глубина объекта, а потом эти данные перенаправляются на дальнейшую обработку фрагментарным тестированием и смешением на конвейре. О фрагментарной стадии шейдинга будет говориться много раз по ходу книги.

  5. Вычислительный шейдер. Сам по себе этот шейдер не является частью конвейера, а скорее представляет отдельностоящую программу. Вычислительный шейдер обрабатывает данные общих рабочих элементов, внутри заданного программой диапазона, а не из графическихданных, как вершины и фрагменты. Вычислительные шейдеры могут обрабатывать буферы созданные и занятые другими процессами вашего приложения. Туда входят кадровый буфер и буфер пост-обработки, но по сути, всё, что вам угодно. О вычислительных шейдерах читайте Главу 12, “Вычислительные шейдеры”.

Важно понимать, как в целом данные переходят с одной стадии обработки на другую. Шейдеры, как вы могли понять из Главы 1, похожи на запрос процедуры: данные поступают в него, обрабатываются, и идут на выход. В “С”, например, это делается или с помощью глобальных переменных, или независимой переменной к функции. GLSL немного отличается в этом. Каждый шейдер похож законченную программу на языке “С” тем, что начинается с процедуры main(). Однако в отличае от программы на “С”, main() на GLSL не принимает независимые переменные, а вместо этого обрабатывает данные, поступающие из и в шейдеры, в виде глобальных переменных (не спутайте их с глобальными переменными приложения, т.к. глобальные переменные шейдеров имеют совершенно отдельные значения от тех, что вы вписываете в код самой программы). Например, взглянем на Пример 2.1.

Пример 2.1 A Simple Vertex Shader

#version 330 core

in vec4 vPosition;

in vec4 vColor;

out vec4 color;

uniform mat4 ModelViewProjectionMatrix;

void

main()

{

color = vColor;

gl_Position = ModelViewProjectionMatrix * vPosition;

}

Хотя это очень компактный шейдер, здесь есть, что запомнить. Вне зависимости от того, для какой стадии шейдинга вы пишите, все шейдеры будут иметь примерно одинаковую структуру с этим примером. В том числе даже заявка версии в заголовке с #version.

Для начала, обратите внимание на глобальные переменные. Это данные ввода и вывода для шейдера OpenGL. Помимо каждой переменной, данные с заданным типом (напр., vec4, о котором скоро) копируются в шейдер из OpenGL с помощью in-переменных, и точно также копируются из шейдра с помощью out-переменных. Данные в этих переменных обновляются каждый раз при исполнении шейдера (напр., если OpenGL обрабатывает вершины, то новые данные пропускаются через эти переменные для каждой вершины; при работе с фрагментами - для каждого фрагмента). Еще одна категория переменных, которые возможно получить из приложения OpenGL, это унифицированные переменные. Унифицированные (unifrom) переменные не сменяются от вершины к вершине или фрагменту, а сохраняют значение для всех геометрических примитивов, пока приложение не обновит их.