Расширения по работе с текстурами, вошедшие в последние версии OpenGL

Расширение ARB_texture_swizzle

Данное расширение (вошедшее в 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 );

Расширение ARB_seamless_cube_map

Традиционно, при чтении из кубической текстурной карты, происходит выбор одной из сторон и далее все операции идет в пределах выбранной стороны. Хотя во многих случаях это и работает, однако есть ситуации, когда подобное поведение в принципе неверно. Так при билинейной интерполяции нужно прочесть блок 2х2 тексела и если нужное нам значение лежит близко к ребру, то соответствующие четыре значения должны браться с разных сторон кубической карты, чего в данный момент не происходит (т.е. все четыре значения берутся в пределах одной стороны).

Данное расширение (вошедшее в OpenGL 3.2) дает наконец возможность корректно обрабатывать подобные случаи и брать значения для фильтрации кубической текстуры при необходимости с разных сторон. Данная функциональность является глобальной и включается и выключается при помощи команд glEnable и glDisable с параметром GL_TEXTURE_CUBE_MAP_SEAMLESS.

glEnable ( GL_TEXTURE_CUBE_MAP_SEAMLESS );

Расширение ARB_texture_gather

Как уже указывалось для фильтрации текстуры читается сразу блок 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 (который также может возвращать вещественные, целые и целые неотрицательные значения).

Расширение ARB_texture_rgb10_a2ui

Это расширение (вошедшее в 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;

Расширение ARB_texture_cube_map_array

В состав 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 и соответствующие функции чтения.

Используются технологии uCoz