- •Что такое OpenGl?
- •Первое знакомство с программой OpenGl
- •Синтаксис OpenGl
- •Конвейер визуализации OpenGl
- •Подготовка данных для отправки в OpenGl
- •Вершинные шейдеры
- •Мозаичные шейдеры
- •Наша первая программа: Подробное обсуждение Ввод main()
- •Запуск OpenGl
- •Распределение объектов буфера вершин
- •Инициализация вершинных и фрагментарных шейдеров
- •Наш первый рендеринг в OpenGl
- •Рисование в OpenGl
- •Включение и выключение команд в OpenGl
- •Шейдеры и OpenGl
- •Настраиваемый конвейер OpenGl
- •Обзор OpenGl Shading Language
- •Создание шейдера при помощи glsl Точка отправления
- •Задача переменных
- •Охват переменных
- •Инициализация переменных
- •Сложные типы
- •Получение доступа к элементам матриц и векторов
- •Структуры
- •Квалификаторы хранилищ
- •Заявления
- •Вычислительная инвариантность
- •Глобальные функции компиляции шейдеров
- •Блоки интерфейса
- •Унифицированные блоки
- •Указание унифицированных блоков в шейдере
- •Доступ к унифицированным блокам из приложения
- •Блоки In/Out
- •Компилирование шейдеров
- •Наша функция LoadShaders()
- •Подпрограммы шейдеров
- •Установка подпрограмм glsl
- •Раздельные объекты шейдеров
Инициализация переменных
Переменные также могут вступать в силу по заявлении. Например:
int i, numParticles = 1500;
float force, g = −9.8;
bool falling = true;
double pi = 3.1415926535897932384626LF;
Прямые интегральные переменные могут быть в восьмеричной, десятичной или шестнадцатеричной системе. Возможно использования отрицательного знака перед цифрой, чтобы игнорировать её в коде, или приписание u или U денотации неподписанного интегрального значения.
Прямые значения с плавающей запятой должны иметь десятиричный вид, если только не описываются научным языком, напр., 3E-7. (Однако, бывают случаи, когда прямые интегралы будут неявно конвертированы в значения с плавающей запятой.) Дополнительно, переменные могут иметь рефикс f или F (на языке “С”)для обозначения прямого значения “float”. Необходимо приписка суффикса "lF” или “LF”, чтобы задать прямому значению точность “double”.
Булевы значения могут иметь приписку или “true” или “false”, и могут быть инициализированы любым из этих значений, или быть результатом операции, вычисление которой представляется булевым (логическим) числом.
Составляющие
Как говорилось ранее, GLSL более строго типизирован, чем С++, и в нем меньше неявных конвертаций между значениями. Например, результатом
int f = false;
будет ошибка компиляции, так как значением интеграла не может быть логическое число. Типы будут неявно конвертированы как показано в таблице.
Table 2.2 Неявные конвертации в GLSL
Нужный тип: Может неявно конвертироваться в:
uint int
float int, uint
double int, uint, float
Вышеприведенные типы конвертаций действительны для скаляров, векторов и матриц данных типов. Конвертации никогда не изменяют матрицы на векторы и т.д., или количество их компонентов. Конвертации также не применяются к массивам и структурам.
Все другие конвертации значений требуют явной конвертации с использованием заданного конструктора конвертации. Конструктор, как и в других языках C++, это функция с тем же наименованием, что и тип, которая возвращает значение этого типа. Например,
float f = 10.0;
int ten = int(f);
использует конструктор конвертации int для применения конвертации. Похожим образом у других типов данных есть свои конструкторы конвертации: float, double, uint, bool, а также векторы и матрицы этих типов. Каждый из них принимает несколько других типов для явной конвертации. Эти функции также демонстрируют другую особенность GLSL: функцию перегрузки, когда каждая функция принимает значения разного типа, но все имеют одинаковое наименование. Дальше по тексту мы еще обсудим функции подробнее.
Сложные типы
Базовые типы данных GLSL могут быть объединены, чтобы лучше соответствовать основным типам данных OpenGL и облегчить задачу вычислений.
Сначала GLSL поддерживает двух-, трех- и четырех-компонентные векторы для каждого базового типа данных (bool, int, uint, float и double). Также доступны матрицы float и double-типа. В Таблице 2.3 перечислены разрешенные типы векторов и матриц.
Таблица 2.3 GLSL Vector and Matrix Types
Base Type 2D vec 3D vec 4D vec Matrix Types
float vec2 vec3 vec4
mat2 mat3 mat4
mat2x2 mat2x3 mat2x4
mat3x2 mat3x3 mat3x4
mat4x2 mat4x3 mat4x4
double dvec2 dvec3 dvec4
dmat2 dmat3 dmat4
dmat2x2 dmat2x3 dmat2x4
dmat3x2 dmat3x3 dmat3x4
dmat4x2 dmat4x3 dmat4x4
int ivec2 ivec3 ivec4 ---
uint uvec2 uvec3 uvec4 ---
bool bvec2 bvec3 bvec4 ---
Данные матричного типа с указанием обоих измерений, такие как mat4x3, первым числом содержать число столбцов, а вторым - рядов.
Переменные, обозначенные таким типом данных, могут быть инициализированы таким же образом как и подобные им скаляры:
vec3 velocity = vec3(0.0, 2.0, 3.0);
и конвертация между этими типами данных также возможна:
ivec3 steps = ivec3(velocity);
Конструкторы векторов также могут быть использованы для усечения или облегчения вектора. Если в конструктор более короткого вектора попадает длинный вектор, конструктор усекает его до установленной длинны.
vec4 color;
vec3 RGB = vec3(color); // now RGB only has three elements
Схожим образом попав в конструктор векторы могут удлинняться. Скалярные данные могут трансформироваться в вектора, как например,
vec3 white = vec3(1.0); // white = (1.0, 1.0, 1.0)
vec4 translucent = vec4(white, 0.5);
Матрицы строятся таким же образом и могут быть инициализированы в или диагональную матрицу, или полную. В случае с диагональными матрицами, в конструктор передается одно значение, и диагональ матрицы устанавливается на это значение, а все остальные числа равняются в ней нулю.
m = mat3(4.0) =
⎛⎝
4.0 0.0 0.0
0.0 4.0 0.0
0.0 0.0 4.0
⎞⎠
Также возможно создание матрицы путём указания каждого её числового значения в конструкторе. Значения можно указать набором скаляров и векторов, главное, чтобы было указано достаточно значений и все они имели общий вид. Кроме того, матрицы определяются по приоритету столбца, то есть, значения указываются сначала по столбцам, а не по рядам, как в “С” при инициализации двухмерных массивов.
Например, мы можем инициализировать матрицу три-на-три так:
mat3 M =mat3 (1.0, 2.0, 3.0,
4.0, 5.0, 6.0,
7.0, 8.0, 9.0);
или так:
vec3 column1 = vec3(1.0, 2.0, 3.0);
vec3 column2 = vec3(4.0, 5.0, 6.0);
vec3 column3 = vec3(7.0, 8.0, 9.0);
mat3 M = mat3(column1, column2, column3);
или даже так:
vec2 column1 = vec2(1.0, 2.0);
vec2 column2 = vec2(4.0, 5.0);
vec2 column3 = vec2(7.0, 8.0);
mat3 M = mat3(column1, 3.0,
column2, 6.0,
column3, 9.0);
или получить ту же матрицу:
⎛⎝
1.0 4.0 7.0
2.0 5.0 8.0
3.0 6.0 9.0
⎞⎠
