Учебники

WebGL — шейдеры

Шейдеры — это программы, которые работают на 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);

В следующем фрагменте кода показано, как создавать, связывать и использовать комбинированную шейдерную программу.