Шейдеры — это программы, которые работают на GPU. Шейдеры написаны на OpenGL ES Shader Language (известный как ES SL). ES SL имеет свои собственные переменные, типы данных, классификаторы, встроенные входы и выходы.
Типы данных
В следующей таблице перечислены основные типы данных, предоставляемые OpenGL ES SL.
Sr.No. | Тип и описание |
---|---|
1 |
недействительным Представляет пустое значение. |
2 |
BOOL Принимает истину или ложь. |
3 |
ИНТ Это целочисленный тип данных со знаком. |
4 |
поплавок Это плавающий скалярный тип данных. |
5 |
vec2, vec3, vec4 n-компонентный вектор с плавающей точкой |
6 |
bvec2, bvec3, bvec4 Булево вектор |
7 |
ivec2, ivec3, ivec4 целое число со знаком |
8 |
мат2, мат3, мат4 Матрица с плавающей запятой 2×2, 3×3, 4×4 |
9 |
sampler2D Доступ к 2D-текстуре |
10 |
samplerCube Доступ к текстуре с отображением куба |
недействительным
Представляет пустое значение.
BOOL
Принимает истину или ложь.
ИНТ
Это целочисленный тип данных со знаком.
поплавок
Это плавающий скалярный тип данных.
vec2, vec3, vec4
n-компонентный вектор с плавающей точкой
bvec2, bvec3, bvec4
Булево вектор
ivec2, ivec3, ivec4
целое число со знаком
мат2, мат3, мат4
Матрица с плавающей запятой 2×2, 3×3, 4×4
sampler2D
Доступ к 2D-текстуре
samplerCube
Доступ к текстуре с отображением куба
Отборочные
В OpenGL ES SL есть три основных классификатора:
Sr.No. | Квалификатор и описание |
---|---|
1 |
атрибут Этот классификатор действует как связь между вершинным шейдером и OpenGL ES для данных на каждую вершину. Значение этого атрибута меняется при каждом выполнении вершинного шейдера. |
2 |
единообразный Этот классификатор связывает шейдерные программы и приложение WebGL. В отличие от квалификатора атрибута, значения униформ не меняются. Униформа только для чтения; Вы можете использовать их с любыми основными типами данных, чтобы объявить переменную. Пример — равномерное vec4 lightPosition; |
3 |
варьируя Этот классификатор формирует связь между вершинным шейдером и фрагментным шейдером для интерполированных данных. Он может использоваться со следующими типами данных — float, vec2, vec3, vec4, mat2, mat3, mat4 или массивы. Пример — вариация vec3 нормальная; |
атрибут
Этот классификатор действует как связь между вершинным шейдером и OpenGL ES для данных на каждую вершину. Значение этого атрибута меняется при каждом выполнении вершинного шейдера.
единообразный
Этот классификатор связывает шейдерные программы и приложение WebGL. В отличие от квалификатора атрибута, значения униформ не меняются. Униформа только для чтения; Вы можете использовать их с любыми основными типами данных, чтобы объявить переменную.
Пример — равномерное vec4 lightPosition;
варьируя
Этот классификатор формирует связь между вершинным шейдером и фрагментным шейдером для интерполированных данных. Он может использоваться со следующими типами данных — float, vec2, vec3, vec4, mat2, mat3, mat4 или массивы.
Пример — вариация vec3 нормальная;
Вершинный шейдер
Вершинный шейдер — это программный код, который вызывается для каждой вершины. Он трансформирует (перемещает) геометрию (например, треугольник) из одного места в другое. Он обрабатывает данные каждой вершины (данные для каждой вершины), такие как координаты вершины, нормали, цвета и координаты текстуры.
В коде вершинного шейдера ES GL программисты должны определять атрибуты для обработки данных. Эти атрибуты указывают на объект буфера вершин, написанный на JavaScript. Следующие задачи могут быть выполнены с использованием вершинных шейдеров вместе с вершинным преобразованием —
- Преобразование вершин
- Нормальное преобразование и нормализация
- Генерация координат текстуры
- Преобразование координат текстуры
- Осветительные приборы
- Применение цветного материала
Предопределенные переменные
OpenGL ES SL предоставляет следующие предопределенные переменные для вершинного шейдера:
Sr.No. | Переменные и описание |
---|---|
1 |
highp vec4 gl_Position; Держит позицию вершины. |
2 |
mediump float gl_PointSize; Содержит преобразованный размер точки. Единицами этой переменной являются пиксели. |
highp vec4 gl_Position;
Держит позицию вершины.
mediump float gl_PointSize;
Содержит преобразованный размер точки. Единицами этой переменной являются пиксели.
Образец кода
Взгляните на следующий пример кода вершинного шейдера. Обрабатывает вершины треугольника.
attribute vec2 coordinates; void main(void) { gl_Position = vec4(coordinates, 0.0, 1.0); };
Если вы внимательно наблюдаете приведенный выше код, мы объявили переменную атрибута с координатами имени. (Эта переменная будет связана с объектом буфера вершин с помощью метода getAttribLocation () . Координаты атрибута передаются в качестве параметра этому методу вместе с программным объектом шейдера.)
На втором шаге данной программы вершинного шейдера определяется переменная gl_position .
gl_Position
gl_Position — это предопределенная переменная, которая доступна только в программе вершинного шейдера. Содержит позицию вершины. В приведенном выше коде атрибуты координат передаются в виде вектора. Поскольку вершинный шейдер является операцией для каждой вершины, значение gl_position рассчитывается для каждой вершины.
Позже значение gl_position используется примитивной сборкой, отсечкой, отбраковкой и другими операциями с фиксированной функциональностью, которые работают с примитивами после завершения обработки вершины.
Мы можем написать программы вершинного шейдера для всех возможных операций вершинного шейдера, которые мы обсудим отдельно в этом уроке.
Фрагмент шейдера
Сетка образована несколькими треугольниками, а поверхность каждого треугольника называется фрагментом . Фрагментный шейдер — это код, который выполняется на каждом пикселе каждого фрагмента. Это написано для расчета и заливки цвета на отдельных пикселях. Следующие задачи могут быть выполнены с использованием фрагментных шейдеров —
- Операции с интерполированными значениями
- Доступ к текстуре
- Нанесение текстур
- Туман
- Цветовая сумма
Предопределенные переменные
OpenGL ES SL предоставляет следующие предопределенные переменные для фрагментного шейдера:
Sr.No. | Переменные и описание |
---|---|
1 |
mediump vec4 gl_FragCoord ; Содержит позицию фрагмента в буфере кадра. |
2 |
bool gl_FrontFacing; Содержит фрагмент, принадлежащий переднему примитиву. |
3 |
mediump vec2 gl_PointCoord; Удерживает положение фрагмента внутри точки (только растеризация точки). |
4 |
mediump vec4 gl_FragColor; Содержит значение цвета выходного фрагмента шейдера |
5 |
mediump vec4 gl_FragData [n] Содержит цвет фрагмента для цветного вложения n . |
mediump vec4 gl_FragCoord ;
Содержит позицию фрагмента в буфере кадра.
bool gl_FrontFacing;
Содержит фрагмент, принадлежащий переднему примитиву.
mediump vec2 gl_PointCoord;
Удерживает положение фрагмента внутри точки (только растеризация точки).
mediump vec4 gl_FragColor;
Содержит значение цвета выходного фрагмента шейдера
mediump vec4 gl_FragData [n]
Содержит цвет фрагмента для цветного вложения n .
Образец кода
В следующем примере кода фрагментного шейдера показано, как применить цвет к каждому пикселю в треугольнике.
void main(void) { gl_FragColor = vec4(0, 0.8, 0, 1); }
В приведенном выше коде значение цвета хранится в переменной gl.FragColor
. Программа фрагмента шейдера передает вывод в конвейер, используя фиксированные переменные функции; FragColor является одним из них. Эта переменная содержит значение цвета пикселей модели.
Хранение и компиляция шейдерных программ
Поскольку шейдеры являются независимыми программами, мы можем написать их как отдельный скрипт и использовать в приложении. Или вы можете хранить их непосредственно в строковом формате, как показано ниже.
var vertCode = 'attribute vec2 coordinates;' + 'void main(void) {' + ' gl_Position = vec4(coordinates, 0.0, 1.0);' + '}';
Компиляция шейдера
Компиляция включает следующие три шага —
- Создание объекта шейдера
- Прикрепление исходного кода к созданному объекту шейдера
- Компиляция программы
Создание вершинного шейдера
Чтобы создать пустой шейдер, WebGL предоставляет метод с именем createShader () . Создает и возвращает шейдерный объект. Его синтаксис выглядит следующим образом —
Object createShader (enum type)
Как указано в синтаксисе, этот метод принимает предопределенное значение перечисления в качестве параметра. У нас есть два варианта для этого —
-
gl.VERTEX_SHADER для создания вершинного шейдера
-
gl.FRAGMENT_SHADER для создания фрагментного шейдера.
gl.VERTEX_SHADER для создания вершинного шейдера
gl.FRAGMENT_SHADER для создания фрагментного шейдера.
Присоединение источника к шейдеру
Вы можете присоединить исходный код к созданному объекту шейдера, используя метод shaderSource () . Его синтаксис выглядит следующим образом —
void shaderSource (Object shader, string source)
Этот метод принимает два параметра —
-
шейдер — Вы должны передать созданный объект шейдера как один параметр.
-
Исходный код — Вы должны передать программный код шейдера в строковом формате.
шейдер — Вы должны передать созданный объект шейдера как один параметр.
Исходный код — Вы должны передать программный код шейдера в строковом формате.
Компиляция программы
Чтобы скомпилировать программу, вы должны использовать метод compileShader () . Его синтаксис следующий:
compileShader(Object shader)
Этот метод принимает программный объект шейдера в качестве параметра. После создания объекта программы шейдера присоедините к нему исходный код и передайте этот объект этому методу.
В следующем фрагменте кода показано, как создать и скомпилировать вершинный шейдер, а также фрагментный шейдер для создания треугольника.
// Vertex Shader var vertCode = 'attribute vec3 coordinates;' + 'void main(void) {' + ' gl_Position = vec4(coordinates, 1.0);' + '}'; var vertShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertShader, vertCode); gl.compileShader(vertShader); // Fragment Shader var fragCode = 'void main(void) {' + ' gl_FragColor = vec4(0, 0.8, 0, 1);' + '}'; var fragShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragShader, fragCode); gl.compileShader(fragShader);
Комбинированная программа
После создания и компиляции обеих программ шейдеров вам необходимо создать комбинированную программу, содержащую оба шейдера (вершина и фрагмент). Следующие шаги должны быть выполнены —
- Создать программный объект
- Присоедините оба шейдера
- Связать оба шейдера
- Используйте программу
Создать программный объект
Создайте программный объект с помощью метода createProgram () . Он вернет пустой программный объект. Вот его синтаксис —
createProgram();
Прикрепить шейдеры
Присоедините шейдеры к созданному программному объекту, используя метод attachShader () . Его синтаксис выглядит следующим образом —
attachShader (Object program , Object shader );
Этот метод принимает два параметра —
-
Программа — передать созданный пустой программный объект как один параметр.
-
Shader — пройти одну из программ скомпилированных шейдеров (вершинный шейдер, фрагментный шейдер)
Программа — передать созданный пустой программный объект как один параметр.
Shader — пройти одну из программ скомпилированных шейдеров (вершинный шейдер, фрагментный шейдер)
Примечание. С помощью этого метода необходимо подключить оба шейдера.
Связать шейдеры
Свяжите шейдеры, используя метод linkProgram () , передав объект программы, к которому вы прикрепили шейдеры. Его синтаксис выглядит следующим образом —
linkProgram(shaderProgram);
Используйте программу
WebGL предоставляет метод с именем useProgram () . Вы должны передать ему связанную программу. Его синтаксис выглядит следующим образом —
useProgram(shaderProgram);
В следующем фрагменте кода показано, как создавать, связывать и использовать комбинированную шейдерную программу.