|
Главная
Статьи
Ссылки
Скачать
Скриншоты
Юмор
Почитать
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.