Главная Статьи Ссылки Скачать Скриншоты Юмор Почитать Tools Проекты Обо мне Гостевая Форум |
Обычно создание текстурного объекта и заполнение его данными в OpenGL это довольно длительный процесс. Сначала мы выделяем идентификатор для нашей текстуры при помощи glGenTextures. В этот момент создания самого текстурного объекта еще не произошло - оно произойдет при первом вызове glBindTextureю Тогда же идентификатор этой текстуры будет привязан к ее типу.
Далее мы обычно начинаем задавать уровни текстуры в mipmap-пирамиде, при этом для каждого такого уровня мы можем задать разные размеры, форматы и т.п. Это ведет к необходимости выполнения радя проверок непосредственно при рендеринге, что обладает своей ценой.
Расширение ARB_texture_storage предоставляет механизм, позволяющий всего за один вызов создать всю структуру текстуры, позволяя сразу же выполнить все необходимые прорверки и выделение памяти. После того, как мы один раз зададим формат и размер текстуры, они становятся неизменяемыми, что упрощает проверки при использовании текстуры.
Для задания размера и внутреннего формата текстуры вводятся следующие функции:
void glTexStorage1D ( GLenum targetm GLsizei levels,
GLenum internalFormat, GLsizei width );
void glTexStorage2D ( GLenum targetm GLsizei levels,
GLenum internalFormat, GLsizei width, GLsizei height );
void glTexStorage2D ( GLenum targetm GLsizei levels,
GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth );
Обратите внимание, что такие традиционные параметры как border и format просто отсутствуют - они просто не нужны.
Давайте рассмотрим как работают эти функции на примере gltextStorage1D. Ее вызов эквивалентен выполнению следующего фрагмента кода:
for ( int i = 0; i < levels; i++ )
{
glTexImage1D ( target, i, internalFormat, width, 0, format, type, NULL );
width = max ( 1, width / 2 );
}
Аналогично работает и команды glTexStorage2D и glTexStorage3D, только при работе в кубическими текстурными картами и массивами кубических текстурных карт инициализируются все грани, а при работе массивом 2-мерных текстур - инициализируются все элементы массива.
После успешного вызова glTexStorage у текстуры свойство GL_TEXTURE_IMMUTABLE_FORMAT становится равным GL_TRUE и с этого момента размер и формат тектсруы уже нельзя изменить.
Также после этого для данной текстуры использовать команды glTexImage, glCompressedTexImage, glCopyTexture и glTexStorage.
Вместо этого для задания данных для текстуры (т.е. изображения) используются команды glTexSubImage и glCompressedTexSubImage (а также glGenerateMipmap) соответственно.
Также у этого расширения есть поддержка Direct State Access, позволяющая избегать необходимости "привязывания" текстуры - для этого используются следующие функции, вошедшие в состав OpenGL 4.5:
void glTextureStorage1D ( GLuint texture, GLsizei levels, GLenum internalformat,
GLsizei width );
void glTextureStorage2D ( GLuint texture, GLsizei levels, GLenum internalformat,
GLsizei width, GLsizei height );
void glTextureStorage3D ( GLuint texture, GLsizei levels, GLenum internalformat,
GLsizei width, GLsizei height, GLsizei depth );
Обратите внимание, что если вы хотите использовать эти DSA-функции, то для создания текстуры следует использовать не glGenTextures, а glCreateTextures:
void glCreateTextures ( GLenum target, GLsizei n, GLuint * textures );
Ниже приводится пример кода, создающего двухмерную текстуру и загружающей в нее изображение с использованием рассмотренных выше функций, обратите внимание на использование функции glTextureParameteri вместо glTexParameteri. За основу для этого примера взят код из OpenGL Samples Pack. В этом фрагменте кода создается двухмерная текстура и для нее задаются необходимые свойства и изображения для всех уровней пирамиды вообще не прибегая к команде glBindTexture.
gli::texture2D Texture(gli::load_dds((getDataDirectory() + TEXTURE_DIFFUSE).c_str()));
if(Texture.empty())
return false;
glCreateTextures(GL_TEXTURE_2D, 1, &TextureName[texture::TEXTURE]);
glTextureParameteri(TextureName[texture::TEXTURE], GL_TEXTURE_BASE_LEVEL, 0);
glTextureParameteri(TextureName[texture::TEXTURE], GL_TEXTURE_MAX_LEVEL, static_cast<GLint>(Texture.levels() - 1));
glTextureParameteri(TextureName[texture::TEXTURE], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTextureParameteri(TextureName[texture::TEXTURE], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTextureStorage2D(TextureName[texture::TEXTURE], GLint(Texture.levels()),
gli::internal_format(Texture.format()),
GLsizei(Texture[0].dimensions().x), GLsizei(Texture[0].dimensions().y));
for(std::size_t Level = 0; Level < Texture.levels(); ++Level)
glTextureSubImage2D(TextureName[texture::TEXTURE], GLint(Level), 0, 0,
GLsizei(Texture[Level].dimensions().x), GLsizei(Texture[Level].dimensions().y),
gli::external_format(Texture.format()), gli::type_format(Texture.format()),
Texture[Level].data());
return true;
Обратите внимание, что этот пример ориентирован на использование OpenGL 4.5.