try).

Определение языка1

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

Синтаксис языка шейдеров OpenGL заимствован у семейства языков программирования С. Лексемы, идентификаторы, точки с запятыми, обозначение вложения блоков фигурными скобками, структурная схема и многие ключевые слова выглядят так же, как в языке С. Доступны оба вида комментариев,.// …и/* … */.Но многие особенности отличаются от используемых в С, и в этой главе все серьезные отличия будут описаны.

Каждый пример шейдера представлен в виде, в котором он может появиться в файле или на экране. Но на самом деле шейдеры передаются в OpenGL в виде етрок, а не файлов.

3.1. Примеры шейдеров

Обычно программа содержит два шейдера: вершинный и фрагментный. На самом деле шейдеров каждого типа может быть больше, но для всех шейдеров каждого типа может использоваться только одна функция mai п, поэтому обычно все-таки ограничиваются одним шейдером каждого типа.

Далее приведена простая пара вершинного и фрагментного шейдеров, которая может равномерно выразить температуру цветом. Амплитуда температурных значений и их цветов параметризована. Первый фрагмент относится к вершинному шейдеру. Он выполняется один раз для каждой вершины:

// uniform-переменные, изменяемые не чаще, чем при смене примитива uniform float CoolestTemp: uniform float TempRange;

// attribute-переменные, обычно меняются для каждой вершины attribute float VertexTemp;

// varying-переменные передают значения // из вершинного шейдера фрагментному varying float Temperature:

void mainO {

// вычисляется температура для интерполирования во фрагментах // в диапазоне [0.0. 1.0]

Temperature = (VertexTemp - CoolestTemp) / TempRange:

/*

Размещение вершины, установленное, функцией glVertexO, можно прочесть из встроенной переменной gIVertex. Растеризатору для определения положения вершины нужно знать и это значение, и текущую матрицу модели-вида.

*/

gl_Position = gl ModelViewProjectionMatrlx * g1_Vertex:

}

Это код вершинного шейдера. Затем выполняется сборка примитивов, после которой растеризатор получает достаточно информации для создания фрагментов. Растеризатор интерполирует значения Temperature в вершинах и создает значения для фрагмента. После этого каждый фрагмент передается фрагментному шейдеру;

// uni form-переменные меняются не чаще, чем для каждого примитива // vec3 объявляет вектор из трех чисел с плавающей запятой1 uniform vec3 CoolestColor; uniform vec3 HottestColor:

// Temperature содержит интерполированное для фрагментов значение // температуры, установленное вершинным шейдером varying float Temperature;

void mainO {

// получить цвет из промежутка между самый холодный и самым теплым

// с помощью встроенной функции mix()

vec3 color = mix(CoolestColor. HottestColor, Temperature):

// Создать вектор из 4 чисел с плавающей запятой, добавив значение // прозрачности, разное 1.0. и установить фрагменту этот цвет gl_FragColor = vec4.(color. 1.0);


⇐ вернуться назад | | далее ⇒