Расширение ARB_texture_cube_map в OpenGL
Стандартный OpenGL поддерживает всего два типа текстур - одномерные (1D) и двухмерные (2D).
Начиная с версии 1.2 в OpenGL добавлена поддержка трехмерных (3D) текстур.
Расширение GL_ARB_texture_cube_map (также как и расширение GL_EXT_texture_cube_map) добавляет еще
один тип текстур - кубические (cube maps). Таким образом OpenGL поддерживает следующие типы
текстур (texture targets) 1D, 2D, 3D и cube maps.
С каждым их этипов связзана своя константа, передаваемая в такие функции как glBindTexture,
glTexParameter и glEnable. Для кубических текстур такой константой является
GL_TEXTURE_CUBE_MAP_ARB (или равная ей по значению GL_TEXTURE_CUBE_MAP_EXT).
Для проверки его поддержки следует использовать
isExtensionSupported ( "GL_ARB_texture_cube_map" )
Но в отличие от традиционных (одно-, двух- и трехмерных) текстур, каждая кубическая текстура
представляет из себя на самом деле набор из шести текстур одинакого размера, которые как бы наложены
на грани куба.
Рис. 1. Наложение изображений на грани куба.
При этом, когда возникает необходимость работы с одной из этих шести текстур (например для загрузки
в память графического ускорителя), следует использовать константы, однозначно идентифицирующие
соответствующую текстуру (грань куба, на которую она должна быть наклеена).
Для этого используются следующие шесть констант:
GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
Каждая из этих шести констант соответствует одной из граней куба, расположенном в положительном или
отрицательном направлении соответствующей координатной оси (перпендикулярной данной грани), впервые
подобная схема использовалась в системе RenderMan.
Рис. 2. Ориентация куба относительно координатных осей
Значения всех этих констант идут последовательно одно за другим, поэтому, например
GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + 1 = GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
При использовании функций, работаюшими именно с конкретными текстурами (например, glTexImage2D)
следует использовать именно эти константы.
Ниже приводится функция, осуществляющая загрузку кубической текстуры в память графичского ускорителя.
unsigned createCubeMap ( bool mipmap, const char * maps [] )
{
unsigned textureId;
glGenTextures ( 1, &textureId );
glBindTexture ( GL_TEXTURE_CUBE_MAP_ARB, textureId );
glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 );
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
loadTexture ( GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, mipmap, maps [0] );
loadTexture ( GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, mipmap, maps [1] );
loadTexture ( GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, mipmap, maps [2] );
loadTexture ( GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, mipmap, maps [3] );
loadTexture ( GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, mipmap, maps [4] );
loadTexture ( GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, mipmap, maps [5] );
glEnable ( GL_TEXTURE_CUBE_MAP_ARB );
if ( mipmap )
{
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
}
else
{
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
}
return textureId;
}
В данном примере функция получает на вход список из шести имен текстур и признак использования
пирамидального фильтрования (mipmapping).
Для работы с кубическими текстурами используются три текстурные координаты (s, t, r).
Фактически эти координаты задают направление прямой,выходящей из начала координат. Тогда точка на
текстуре определяется как точка, соответствующая пересечению этой прямой с единичным кубом, описанным
вокруг начала координат (с гранями, параллельными осям координат).
Рис. 3. Определение точки на кубе, соответствующей координатам (s, t, r).
Легко видно, что персекаемая грань будет определяться той текстурной координатой, котоорая имеет
наибольшее по модулю значение.
Так, если наибольшее по модулю значение имеет координата r, то в зависимости от знака r
будет выбрана либо GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, либо GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB.
При этом текстурные координаты (u,v) для обращения к текстуре соответствующей грани,
вычисляются по следующим формулам:
u = (s/|r| + 1) / 2
v = (t/|r| + 1) / 2
Для задания текстурных координат можно использовать явное задание:
glTexCoord2f ( s, t, r );
Также можно использовать автоматическое вычисление текстурных координат.
При этом поддерживается два способа автоматичской генерации текстурных координат - отражение или
вектор нормали.
Для задания автоматической генерации текстурных координат, соответствующих отражение, используется
следующий фрагмент кода:
glEnable ( GL_TEXTURE_GEN_S );
glEnable ( GL_TEXTURE_GEN_T );
glEnable ( GL_TEXTURE_GEN_R );
glTexGeni ( GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB );
glTexGeni ( GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB );
glTexGeni ( GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB );
Для задания текстурных координат, соответствующих нормали, служит следующий фрагмент кода:
glEnable ( GL_TEXTURE_GEN_S );
glEnable ( GL_TEXTURE_GEN_T );
glEnable ( GL_TEXTURE_GEN_R );
glTexGeni ( GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB );
glTexGeni ( GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB );
glTexGeni ( GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB );
Также полезным может оказаться режим GL_EYE_LINEAR, который позволяет получать ненормированный вектор
от наблюдателя.
Для предотвращение появления артефактов в случаях, когда точка на поверхности куба, соответствующая
текстурным координатам, подходит слишком близко к какому-либо из ребер куба, следует использовать
режим GL_CLAMP_TO_EDGE (вместо GL_REPEAT или GL_CLAMP) при задании texture wrapping.
Задание этого режима осуществляется следующими командами:
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
Обратите внимание, что данный режим устанавливается только для s и t, поскольку
texture wrapping происходит в пределах одной из граней куба, т.е. в 2D.
Поскольку в OpenGL по умолчанию устанавливается режим GL_REPEAT, то при работе с кубическими картами
вам следует явно выставить режим GL_CLAMP_TO_EDGE для всех кубических карт.
Для использоывания кубических текстур их (подобно всем остальным) следует сперва разрешить при помощи
следующей команды
glEnable ( GL_TEXTURE_CUBE_MAP_ARB );
Обратите внимание, что в OpenGL кубические текстуры имеет более высокий приоритет по сравнению с
обычными, поэтому если одновременно разрешиь и кубическую и обычную (например, двухмерную) текстуры,
то будет использована именно кубическая.
Кубическая текстура позволяет в простой и удобной форме задавать функции от направления - каждому
направлению естественным образом соответствует точка на кубе, поэтому достаточно просто задать
значения функции в виде текстур на гранях данного куба.
Одним из применений этого является задание источника света в виде проектора, когда сила света,
падающего в точку, зависит от направления из этой точки на источник света. Кубическая текстура
в этом случае позволяет в легкой и удобной форме задать подобный проектор.
Еще одним возможным применением (мы с ним сталкнемся позже, когда будем рассматривать bump mapping)
является нормализация векторов.
Единичному трехмерному вектору можно легко сопоставить значние RGB. Но при интерполяции подобных
значений (векторов)(или ряде других простых операциях) у нас могут получиться ненормированные
значения (не пригодные для использовании в уравнении освещенности).
Кубическая текстура предоставляет простой способ нормализации.
Исходный код примера, демонстрирующего использование кубических текстур можно скачать
здесь.
В данном примере при помощи клавишь 'r' и 'n' можно переключаться между режимами автоматической
генерации текстурных координат, а цифровые клавиши (так же как и клавиши '+' и '-') управляют
используемой фигурой.
Рис 4. Скриншот из примера.
Текстуры для данного примера были взяты с сайта компании
nvidia.
Дополнительную информацию по данным расширениям можно найти на
OpenGL Extension Registry
|