Главная Статьи Ссылки Скачать Скриншоты Юмор Почитать Tools Проекты Обо мне Гостевая Форум |
Если посмотреть на текстуры в OpenGL, то видно, что они состоят из самого изображения (включая пирамиду mipmap-уровней, грани кубической карты и т.п.) и параметров, управляющих доступом к этому изображению (т.н. sampler state). К этим параметрам относятся режим фильтрации текстуры, режим отсечения текстурных координат, работа с mipmap-уровнями и т.п. При этом сами данные параметры не связаны непосредственно с изображением - они только управляют доступом к нему.
Такое объединение двух различных сущностей (image data и sampler state) в один текстурный объект оказывается довольно неудобным - изменение параметров доступа не самая дешевая операция, периодически возникает необходимость обращаться к одной и той же текстуре с разными параметрами выборки. Часто встречается и обратное - большое число различных текстур используются с одними и теми же параметрами выборки и все эти параметры нужно задавать отдельно для каждой из этих текстур.
Расширение ARB_sampler_objects, входящее в OpenGL 3.3, позволяет отделить параметры выборки от самой текстуры. Для этого вводится новый тип объекта в OpenGL - сэмплер (sampler object). Сэмплер фактически является контейнером для параметров выборки из текстур. Для каждого сэмплера можно задавать параметров выборки (а не привязывать их как ранее к самой текстуре).
Рис 1. Сэмплер, как контейнер для параметров выборки.
Любой сэмплер может быть "привязан" к любому текстурному блоку (texture unit), можно "привязать" один и тот же сэмплер сразу к нескольким текстурным блокам. После этого, параметры для выборки из текстуры будут браться из сэмплера, "привязанного" к текстурному блоку, связанному с текстурой (параметры выборки, заданные для самой текстуры, в этом случае полностью игнорируются).
Таким образом можно легко создать один объект-сэмплер, задать для него все необходимые параметры выборки и привязать ко всем используемым текстурным блоками. Тогда именно этот объект будет управлять параметрами выборки из всех текстур и если нужно будет изменить какой-либо параметр, то это достаточно будет сделать всего один раз - для сэмплера.
Рис 2. Один сэмплер управляет выборками сразу из нескольких текстурных блоков.
С другой стороны можно использовать несколько разных сэмплеров для доступа к одной и той же текстуре - при этом в каждом текстурном блоке выбирается данная текстура и соответствующий сэмплер. Тем самым сэмплер является удобным механизмом управления параметрами выборки из различных текстур.
Рис 3. Доступ к одной и той же текстуре через несколько текстурных блоков, в каждом блоке - свой сэмплер.
Подобно многим другим объектам OpenGL каждый сэмплер идентифицируется беззнаковым целым числом, не равным нулю. Для создания и уничтожения сэмплеров служат функции glGenSamplers и glDeleteSamplers:
void glGenSamplers ( GLsizei count, GLuint * samplers ); void glDeleteSamplers ( GLsizei count, GLuint * samplers );
Проверить, является ли заданное число идентификатором какого-либо сэмплера можно при помощи функции glIsSampler:
GLboolean glIsSampler ( GLuint sampler );
При помощи функции glBindSampler можно "привязать" заданный сэмплер sampler к текстурному блоку unit:
void glBindSampler ( GLuint uint, GLuint sampler );
Для того, чтобы "отвязать" сэмплер от текстурного блока, используется та же функция glBindSampler с параметром sampler равным нулю.
Следующие функции служат для задания параметров сэмплера:
void glSamplerParameteri ( GLuint sampler, GLenum pname, int param ); void glSamplerParameterf ( GLuint sampler, GLenum pname, float param ); void glSamplerParameteriv ( GLuint sampler, GLenum pname, const int * params ); void glSamplerParameterfv ( GLuint sampler, GLenum pname, const float * params ); void glSamplerParameterIiv ( GLuint sampler, GLenum pname, const int * params ); void glSamplerParameterIuiv ( GLuint sampler, GLenum pname, const GLuint * params );
Для того, чтобы получить из сэмплера значения какого-либо его параметра, служат следующие функции:
void glGetSamplerParameteriv ( GLuint sampler, GLenum pname, int * params ); void glGetSamplerParameterfv ( GLuint sampler, GLenum pname, float * params ); void glGetSamplerParameterIiv ( GLuint sampler, GLenum pname, int * params ); void glGetSamplerParameterIuiv ( GLuint sampler, GLenum pname, GLuint * params );
Узнать идентификатор сэмплера выбранного в текущем текстурном блоке можно при помощи вызова функции glGetIntegerv GL_SAMPLER_BINDING
glGetIntegerv ( GL_SAMPLER_BINDING, &sampler );
Для удобства работы "завернем" работу с сэмплером в класс на С++. На следующем листинге приводится заголовочный файл Sampler.h.
// // ARB_sampler_object C++ wrapper // #ifndef __SAMPLER_OBJECT__ #define __SAMPLER_OBJECT__ #include "libExt.h" class Sampler { GLuint id; public: Sampler () { glGenSamplers ( 1, &id ); } ~Sampler () { glDeleteSamplers ( 1, &id ); } bool isOk () const { return id != 0 && glIsSampler ( id ); } GLuint getId () const { return id; } void bind ( int unit ) { glBindSampler ( unit, id ); } void unbind ( int unit ) { glBindSampler ( unit, 0 ); } void setWrap ( GLenum sWrap, GLenum tWrap, GLenum rWrap ) { glSamplerParameteri ( id, GL_TEXTURE_WRAP_S, sWrap ); glSamplerParameteri ( id, GL_TEXTURE_WRAP_T, tWrap ); glSamplerParameteri ( id, GL_TEXTURE_WRAP_R, rWrap ); } void setMinFilter ( GLenum minFilter ) { glSamplerParameteri ( id, GL_TEXTURE_MIN_FILTER, minFilter ); } void setMagFilter ( GLenum magFilter ) { glSamplerParameteri ( id, GL_TEXTURE_MAG_FILTER, magFilter ); } void setMinLod ( int minLod ) { glSamplerParameteri ( id, GL_TEXTURE_MIN_LOD, minLod ); } void setMaxLod ( int maxLod ) { glSamplerParameteri ( id, GL_TEXTURE_MAX_LOD, maxLod ); } void setLodBias ( float bias ) { glSamplerParameterf ( id, GL_TEXTURE_LOD_BIAS, bias ); } void setMaxAnisotropy ( float anisotropy ) { glSamplerParameteri ( id, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy ); } void setTextureCompare ( GLenum mode, GLenum func ) { glSamplerParameteri ( id, GL_TEXTURE_COMPARE_MODE, mode ); glSamplerParameteri ( id, GL_TEXTURE_COMPARE_FUNC, func ); } GLenum getSWrap () const; GLenum getTWrap () const; GLenum getRWrap () const; GLenum getMinFilter () const; GLenum getMagFilter () const; int getMinLod () const; int getMaxLod () const; float getLodBias () const; float getMaxAnisotropy () const; GLenum getTextureCompareMode () const; GLenum getTextureCompareFunc () const; static GLuint activeSampler (); // return sampler bound to current texture unit }; #endif
На следующем листинге приводится соответствующий С++ файл:
// // ARB_sampler_object C++ wrapper // #include "Sampler.h" GLenum Sampler :: getSWrap () const { GLenum sWrap; glGetSamplerParameteriv ( id, GL_TEXTURE_WRAP_S, (GLint *)&sWrap ); return sWrap; } GLenum Sampler :: getTWrap () const { GLenum tWrap; glGetSamplerParameteriv ( id, GL_TEXTURE_WRAP_T, (GLint *)&tWrap ); return tWrap; } GLenum Sampler :: getRWrap () const { GLenum rWrap; glGetSamplerParameteriv ( id, GL_TEXTURE_WRAP_R, (GLint *)&rWrap ); return rWrap; } GLenum Sampler :: getMinFilter () const { GLenum filter; glGetSamplerParameteriv ( id, GL_TEXTURE_MIN_FILTER, (GLint *)&filter ); return filter; } GLenum Sampler :: getMagFilter () const { GLenum filter; glGetSamplerParameteriv ( id, GL_TEXTURE_MAG_FILTER, (GLint *)&filter ); return filter; } int Sampler :: getMinLod () const { int lod; glGetSamplerParameteriv ( id, GL_TEXTURE_MIN_LOD, &lod ); return lod; } int Sampler :: getMaxLod () const { int lod; glGetSamplerParameteriv ( id, GL_TEXTURE_MAX_LOD, &lod ); return lod; } float Sampler :: getLodBias () const { float bias; glGetSamplerParameterfv ( id, GL_TEXTURE_LOD_BIAS, &bias ); return bias; } float Sampler :: getMaxAnisotropy () const { float anisotropy; glGetSamplerParameterfv ( id, GL_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropy ); return anisotropy; } GLenum Sampler :: getTextureCompareMode () const { GLenum mode; glGetSamplerParameteriv ( id, GL_TEXTURE_COMPARE_MODE, (GLint *)&mode ); return mode; } GLenum Sampler :: getTextureCompareFunc () const { GLenum func; glGetSamplerParameteriv ( id, GL_TEXTURE_COMPARE_FUNC, (GLint *)&func ); return func; } GLuint Sampler :: activeSampler () { GLuint sampler; glGetIntegerv ( GL_SAMPLER_BINDING, (GLint *)&sampler ); return sampler; }
По этой ссылке можно скачать весь исходный код к этой статье.
Обратите внимание, что для компиляции данного класса необходимы последние версии библиотек libExt и libTexture.