Главная Статьи Ссылки Скачать Скриншоты Юмор Почитать Tools Проекты Обо мне Гостевая Форум |
Данное расширение (вошедшее в OpenGL 3.3) позволяет задать часто используемую в GLSL операцию swizzle для произвольной текстуры. Для текстуры можно явно задать, что должно возвращаться при чтении для каждого из четырех цветовых каналов. В качестве источника данных для канала может выступать как один из четырех каналов (GL_RED, GL_GREEN, GL_BLUE и GL_ALPHA), так и значения ноль и единица (GL_ZERO и GL_ONE).
Задание "swizzle"'а можно делать покомпонентно, а можно задать сразу для всех четырех компонент. Обратите внимание, что таким образом можно определить значения всех четырех каналов для текстуры, содержащей менее четырех каналов (например, двухканальной RG-текстуры).
Для задания перестановки для активной (bind) текстуры типа target служат функции glTexParameteri и glTexParameteriv. Так следующий пример изменяет RED и ALPHA компоненты текстуры на ноль и единицу.
glTexParameteri ( target, GL_TEXTURE_SWIZZLE_R, GL_ZERO );
glTexParameteri ( target, GL_TEXTURE_SWIZZLE_A, GL_ONE );
Следующий пример переставляет местами RED и BLUE компоненты, а для ALPHA компоненты возвращает ноль, делая это за один вызов glTexParameteriv.
int swizzle [4] = { GL_BLUE, GL_GREEN, GL_RED, GL_ONE };
glTexParameteriv ( target, GL_TEXTURE_SWIZZLE_RGBA, swizzle );
Получить текущую перестановку можно при помощи функции glGetTexParameteriv:
int swizzle [4];
glGetTexParameteriv ( target, GL_TEXTURE_SWIZZLE_RGBA, swizzle );
Традиционно, при чтении из кубической текстурной карты, происходит выбор одной из сторон и далее все операции идет в пределах выбранной стороны. Хотя во многих случаях это и работает, однако есть ситуации, когда подобное поведение в принципе неверно. Так при билинейной интерполяции нужно прочесть блок 2х2 тексела и если нужное нам значение лежит близко к ребру, то соответствующие четыре значения должны браться с разных сторон кубической карты, чего в данный момент не происходит (т.е. все четыре значения берутся в пределах одной стороны).
Данное расширение (вошедшее в OpenGL 3.2) дает наконец возможность корректно обрабатывать подобные случаи и брать значения для фильтрации кубической текстуры при необходимости с разных сторон. Данная функциональность является глобальной и включается и выключается при помощи команд glEnable и glDisable с параметром GL_TEXTURE_CUBE_MAP_SEAMLESS.
glEnable ( GL_TEXTURE_CUBE_MAP_SEAMLESS );
Как уже указывалось для фильтрации текстуры читается сразу блок 2х2 тексела и из этих четырех значений строится одно. Расширение ARB_texture_gather добавляет в GLSL возможность, присутствующую в DX10.1, а именно получить сразу все четыре значения за одну команду без какой-либо фильтрации. К сожалению, можно получить только значения для RED-компонент блока текселов, которые возвращаются как 4-мерный вектор. Данная функциональность вошла в OpenGL 4.0.
При этом если соответствующий блок 2х2 тексела имеет текстурные координаты (i0,j0)-(i1,j1), то возвращенный вектор будет устроен следующим образом:
(Ri0,j1, Ri1,j1, Ri1,j0, Ri0,j0)
Обратите внимание, что при помощи расширение ARB_texture_swizzle можно вместо RED-компоненты подставить любую другую. В GLSL добавлены следующие функции:
gvec4 textureGather ( gsampler2D sampler, vec2 coord );
gvec4 textureGather ( gsampler2DArray sampler, vec3 coord );
gvec4 textureGather ( gsamplerCube sampler, vec3 coord );
gvec4 textureGather ( gsamplerCube sampler, vec4 coord );
gvec4 textureGatherOffset ( gsampler2D sampler, vec2 coord, ivec2 offset );
gvec4 textureGatherOffset ( gsampler2DArray sampler, vec2 coord, ivec2 offset );
Через gvec4 здесь обозначен любой из классов vec4, ivec4 и uvec4, соответствующий типу сэмплера sampler (который также может возвращать вещественные, целые и целые неотрицательные значения).
Это расширение (вошедшее в OpenGL 3.3) вводит новый ненормализованный формат текстур - GL_RGB10_A2UI. В этом формате на красный, зеленый и синий каналы отводится по 10 бит, а на альфа-канал - всего 2 бита, таким образом один тексел занимает ровно 32 бита. Обратите внимание, что в текстуры этого формата можно осуществлять рендеринг.
Рис 1. Разложение пиксела по битам внутри GPU DRAM.
На следующем рисунке приводится как битовое значение 0x22222222 раскладывается в RGBA-представление.
Рис 2. Разложение пиксела по битам внутри GPU DRAM.
Существует два способа заполнения такой текстуры данными - можно как для обычной текстуры передать покомпонентный массив (используя в качестве типа данных для glTexImage* константы GL_UNSIGNED_INT или GL_UNSIGNED_SHORT), тогда упаковка данных будет произведена автоматически. Второй вариант - сразу передать уже упакованные данные (по одному 32-му слову на тексел), для этого в качестве параметра type функции glTexImage* следует задать константу GL_UNSIGNED_INT_10_10_10_2. Ниже приводится простой пример создание подобной текстуры и заполнения ее данными.
GLenum format = GL_RGBA_INTEGER_EXT;
GLenum intFormat = GL_RGB10_A2UI;
GLenum target = GL_TEXTURE_2D;
GLuint * data = new GLuint [width * height];
GLuint tex;
// Fill the data with packed values
glGenTextures ( 1, &tex );
glBindTexture ( target );
glTexImage2D ( target, 0, intFormat, width, height, 0, format, GL_UNSIGNED_INT_10_10_10_2, data );
delete data;
В состав OpenGL 3.0 вошли массивы одномерный и двухмерных текстур (введенные ранее через расширение EXT_texture_array). Поддержка же массивов кубических текстурных карт появилась позже, она вводится расширением ARB_texture_cube_map_array и вошла в состав OpenGL 4.0.
Массиву кубических текстур соответствует тип (target) GL_TEXTURE_CUBE_MAP_ARRAY, все кубические карты, входящие в состав массива, должны иметь одинаковый размер грани и внутренний формат. Для задания данных для массива служит функция glTexImage3D.
void glTexImage3D ( GLenum target, int level, int internalFormat, GLsizei width, GLsizei height, GLsizei depth,
int border, GLenum format, GLenum type, void * data );
При этом параметр target равняется GL_TEXTURE_CUBE_MAP_ARRAY, параметры width и height совпадают, а значение параметра depth равно размеру массива, умноженному на 6, т.е. массив кубических текстур воспринимается просто как массив граней - сперва идут шесть граней первой карты, потом шесть граней второй карты и т.д.
Максимальный размер массива можно узнать при помощи следующего фрагмента кода:
int size;
glGetIntegerv ( GL_MAX_ARRAY_TEXTURE_LAYERS, &size );
Можно использовать отдельные грани массива кубических текстур как цели для рендеринга при помощи функции glFramebufferTextureLayer:
void glFramebufferTextureLayer ( GLenum target, GLenum attachment, GLuint texture, int level, int layer );
При этом layer/6 задает элемент массива, а layer % 6 - грант выбранного элемента, куда будет осуществляться рендеринг. Вместо glFramebufferTextureLayer можно использовать функцию glFramebufferTextureARB, задав сразу весь текстурный массив как цель для рендеринга. В этом случае выбор элемента массива и конкретной грани осуществляется в геометрическом шейдере записью в переменную gl_Layer, играющую точно такую же роль, как и параметр layer в вызове glFramebufferTextureLayer.
При работе с массивами кубических текстур, используются все четыре текстурные координаты - (s,t,r,q), координата q служит для выбора элемента из массива, а дальше координаты (s,t,r) используются для выборки значения из выбранного элемента массива.
Для работы с массива кубических текстур в GLSL были добавлены новые типы сэмплеров - samplerCubeArray, sampleCubeArrayShadow, isamplerCubeArray и usampleCubeArray и соответствующие функции чтения.