- •Что такое OpenGl?
- •Первое знакомство с программой OpenGl
- •Синтаксис OpenGl
- •Конвейер визуализации OpenGl
- •Подготовка данных для отправки в OpenGl
- •Вершинные шейдеры
- •Мозаичные шейдеры
- •Наша первая программа: Подробное обсуждение Ввод main()
- •Запуск OpenGl
- •Распределение объектов буфера вершин
- •Инициализация вершинных и фрагментарных шейдеров
- •Наш первый рендеринг в OpenGl
- •Рисование в OpenGl
- •Включение и выключение команд в OpenGl
- •Шейдеры и OpenGl
- •Настраиваемый конвейер OpenGl
- •Обзор OpenGl Shading Language
- •Создание шейдера при помощи glsl Точка отправления
- •Задача переменных
- •Охват переменных
- •Инициализация переменных
- •Сложные типы
- •Получение доступа к элементам матриц и векторов
- •Структуры
- •Квалификаторы хранилищ
- •Заявления
- •Вычислительная инвариантность
- •Глобальные функции компиляции шейдеров
- •Блоки интерфейса
- •Унифицированные блоки
- •Указание унифицированных блоков в шейдере
- •Доступ к унифицированным блокам из приложения
- •Блоки In/Out
- •Компилирование шейдеров
- •Наша функция LoadShaders()
- •Подпрограммы шейдеров
- •Установка подпрограмм glsl
- •Раздельные объекты шейдеров
Получение доступа к элементам матриц и векторов
Отдельные элементы векторов и матриц могут быть доступны и отмечены. Векторы поддерживают два типа элементов доступа: поименной и метод массивов. Матрицы используют двух-мерный и метод массивов.
Компоненты вектора, к которым получаем поименной доступ, например,
float red = color.r;
float v_y = velocity.y;
или использую нулевую индексированную схему. С помощью этого примера мы получим тот же результат, что и выше:
float red = color[0];
float v_y = velocity[1];
По сути, в Таблице 2.4 три типа наименований компонентов, которые на деле дают один результат. Разные настройки удобны для разъяснения, что вы делаете:
Таблица 2.4 Vector Component Accessors
Component Accessors Описание
(x, y, z, w) компоненты, связанные с положением
(r, g, b, a) компоненты, связанные в цветом
(s, t, p, q) компоненты текстурных координат
Обычно покомпонентный доступ используется в векторах для swizzling-компонентов, такими как, например, цвета, возможно для конверсии цвет-положение. К примеру, вы можете провести следующую операцию для назначения параметра “освещенности”, основанном на красном компоненте цвета ввода:
vec3 luminance = color.rrr;
Таким же образом, если вам понадобится развернуть компоненты в векторе, вы можете это сделать с помощью
color = color.abgr; // reverse the components of a color
Единственное ограничение заключается в том, что в одной строке кода можно изменять только один набор компонентов. То есть, нельзя сделать
vec4 color = otherColor.rgz; // Error: "z" is from a different group
Также ошибка компиляции может появиться из-за попытки доступа к элементам за пределами диапазона этого типа данных. Например,
vec2 pos;
float zPos = pos.z; // Error: no "z" component in 2D vectors
Матричные элементы доступны при использовании системы счисления массивов. Через матрицу можно получить доступ или к значению одного скаляра, или же к массиву элементов:
mat4 m = mat4(2.0);
vec4 zVec = m[2]; // get column 2 of the matrix
float yScale = m[1][1]; // or m[1].y works as well
Структуры
Вы также можете логически сгруппировать набор элементов разных типов в единую структуру. Структуры удобны для передачи ассоциированных данных в функции. Когда определяется структура, она автоматически создает новый тип данных, неявно определяя функцию конструктора, которая принимает типы элементов структуры как параметры.
struct Particle {
float lifetime;
vec3 position;
vec3 velocity;
};
Particle p = Particle(10.0, pos, vel); // pos, vel are vec3s
Для обращения к элементам структуры используйте известную вам из “С” нотацию “dot”.
Массивы
GLSL также поддерживает массивы любых типов данных, в том числе, структуры. Также как с массивами данных в “С”, они обозначаются квадратными скобками [ ]. Диапазон элементов в массиве размера n=0 … n= -1. В отличие от “С”, ни положительные ни отрицательные индексы за пределами диапазона разрешимы. С варсии GLSL 4.3, массивы могут формироваться из массивов, предоставляя возможность работы многомерными данными. Однако версии до 4.3 (4.2 и ранние) на позволяют работать с массивами из массивов, то есть нельзя создать многомерный масив.
Массивы могут быть объявлены измеренными и неизмеренными. Вы можете задать неизмеренный массив заранее в виде массива переменных, а позднее задать им определенный размер. Заявка массива пользуется видо с квадратными скобками, как в
float coeff[3]; // an array of 3 floats
float[3] coeff; // same thing
int indices[]; // unsized. Redeclare later with a size
Массивы - тип данных первого класса GLSL, что означает, что они могут быть использованы и как параметры функции и как возвратные данные. Чтобы статично интернализовать массив значений, вы можете использовать конструктор
float coeff[3] = float[3](2.38, 3.14, 42.0);
Пространственное значение в конструкторе не обязательно.
Также как и в Java, массивы GLSL имеют неявный метод для объявления количества элементов, которые они содержат. Метод использования length(). Если вы хотите работать со всеми элементами в массиве, вот способ использования lenth():
for (int i = 0; i < coeff.length(); ++i) {
coeff[i] *= 2.0;
}
Метод length() также применим к векторам и матрицам. Длинна вектора - это количество составляющих его компонентов. А длинна матрицы - число столбцов в ней. Это именно то, что вам нужно при работе с синтаксисом массивов для индексации векторов и матриц (m[2] это третий столбец в матрице m).
mat3x4 m;
int c = m.length(); // number of columns in m: 3
int r = m[0].length(); // number of components in column vector 0: 4
Если длинна известна на момент компиляции, метод length() возвращает компиляционную постоянную, которую можно использовать там, где требуются компиляционные постоянные. Например,
mat4 m;
float diagonal[m.length()]; // array of size matching the matrix size
float x[gl_in.length()]; // array of size matching the number of
// geometry shader input vertices
Для всех векторов и матриц, и для большинства массивов, lenght() определяется на стадии компиляции. Хотя для некоторых массивов, lenght() не известна до момента привязки. Это происходит, когда массив зависит от привязки для вычисления размера нескольких шейдеров в одной стадии. Для шейдеров объектов буфера хранения (заявленных командой buffer), lenght() может оставаться неизвестной до момента визуализации. Если вы хотите получить компиляционную постоянную от lenght(), убедитесь, что задали размер массива в вашем шейдере перед использованием lenght()-метода.
Многомерный массивы на деле являются массивами из массивов и имеют схожий с “С” синтаксис:
float coeff[3][5]; // an array of size 3 of arrays of size 5
coeff[2][1] *= 2.0; // inner-dimension index is 1, outer is 2
coeff.length(); // this returns the constant 3
coeff[2]; // a one-dimensional array of size 5
coeff[2].length(); // this returns the constant 5
Таким методом можно создать массивы для практически любого типа данных и ресурса. Когда внутренняя (самая правая) часть измерений передаётся приложению, она изменяется быстрее всего из макета памяти.
