Перейти к содержимому


Свернуть чат Чат Открыть чат во всплывающем окне

Folgen : (вчера) Спс.
GranMinigun : (вчера) Готово. Добро пожаловать на форум, механоид.
GranMinigun : (вчера) Указать, кого именно активировать, например.
Гость : (2 дней назад) Активируйте акк. Хз, нужно что-либо указывать дополнительно для этого в чате, или админы сами всех подряд активируют, кто в очереди на активацию?
GranMinigun : (неделю назад) https://forums.unrea...sed-on-gis-data
Yakim (Watco... : (неделю назад) Аа да? Ну окей)
GranMinigun : (неделю назад) А это даже не обсуждается!
Yakim (Watco... : (неделю назад) А кто сказал что мы пьянели?)
GranMinigun : (неделю назад) Ну что, товарищи, протрезвели?
Yakim (Watco... : (2 недель назад) сяп)
Гость : (2 недель назад) Егорыч на праздники с каникул вернулся. За это тост! Всем маны!
lz : (3 недель назад) Наоборот.
Гость : (3 недель назад) Позвольте уточнить, для будущего наркомана прошлое это будущее или наоборот?
lz : (3 недель назад) Как ты его поймаешь, когда он знает, где ты его будешь ловить?
GranMinigun : (3 недель назад) Ловите наркомана из будущего!
PA3UJIb : (3 недель назад) С новым 2018 годом! А то старый-то 2018 мы и не видели даже
Yakim (Watco... : (3 недель назад) С наступающим)
Yakim (Watco... : (3 недель назад) гы
lz : (3 недель назад) Посоны, с наступающим всех!
Yakim (Watco... : (3 недель назад) +
lz : (3 недель назад) Много капитанства.
lz : (3 недель назад) +
Yakim (Watco... : (3 недель назад) ну такое
Gaantro : (3 недель назад) Описывает принцип работы.
Gaantro : (3 недель назад) Антиграв*
Gaantro : (3 недель назад) Система Grable в Star Citizen (Антигуа) : https://youtu.be/2VkzHbJiCAo
Yakim (Watco... : (3 недель назад) Ага :lol:
lz : (3 недель назад) Чё там у нас? Пошла жара? Главное, чтобы не такое генерилось https://youtu.be/RvAwB7ogkik
Moh : (3 недель назад) Мне, да привет? Ну привет )
Гость : (3 недель назад) И с Новым годом.
Гость : (3 недель назад) Шучу. От Крогота.
Гость : (3 недель назад) От Гостя.
Гость : (3 недель назад) Увидите моха передайте ему привет.
Yakim (Watco... : (3 недель назад) :lol: :P
lz : (3 недель назад) Лан, чё ты, нормально же общались, это нарицательное)
Yakim (Watco... : (4 недель назад) Еще и "Мехах" с маленькой буквы, бесстыжий :D
GranMinigun : (4 недель назад) Был.
lz : (4 недель назад) В мехах был такой рейтинг? Не помню уже.
lz : (4 недель назад) Опасный Яким)
Yakim (Watco... : (4 недель назад) За "маханойдов" и двор, стреляю в упор :D
GranMinigun : (4 недель назад) Я не это имел в виду!
Yakim (Watco... : (4 недель назад) :lol:
lz : (4 недель назад) За механойдов наверное.
lz : (4 недель назад) Всё, рубанул.
lz : (4 недель назад) Ща мы их.

Фотография
- - - - -

[GLT.hpp] - поддержка текстур в формате GLT

OpenGL texture image GLTexture

  • Авторизуйтесь для ответа в теме
В этой теме нет ответов

#1 OFFLINE   Yandersen

Yandersen

    Диванный теоретик

  • Админ
  • 454 сообщений
  • Откуда:Canada
  • Настоящее имя:Ян

Отправлено 28 Апрель 2015 - 19:51

Формат файла *.glt (OpenGL Texture) предназначен для сохранения и загрузки текстур (мипмапы и настройки) для OpenGL приложений.

GLT.hpp содержит описание структуры файлов *.glt и класс GLTexture, осуществляющий сохранение и загрузку *.glt файлов и работу с текстурами:

 

GLT.hpp
 

:!: Требуется наличие LoadGL.h.

:!: Некоторые функции используют OpenGL4.5.

 

Для создания файла текстуры нужно создать и настроить текстуру, загрузить мипмапы удобным способом, а затем средствами класса GLTexture сохранить готовую текстуру из контекста OpenGL в указанный *.glt файл. Альтернативно, можно создать *.glt файл из *.bmp с помощью специальной программы - GLT editor.

Пока что для работы с *.glt файлами использовался FileGLT.hpp, поддерживавший формат файла первой версии ('G','L','T',1). Первая версия позволяла хранить любое количество картинок в любом порядке, и в шапке файла размеры базовой картинки не указывались явно, так как загрузка мипмапов шла с помощью функции glTexImage*D. Но эта функция уже устарела - сегодня текстуры имеют immutable формат, т.е. аллоцируются лишь один раз (glTexStorage*D) и для этого необходимо знать размерность самой большой картинки и количество уровней мипмапов. Поэтому шапка второй версии файла ('G','L','T',2) включает размерность базовой картинки. Плюс добавлена поддержка бордеров и свиззл-настроек. Короче, вторая версия просто лучше. Хотя первая всё так же поддерживается - GLT.hpp умеет её грузить, но сохраняет уже в формате второй версии.
 
---
 
Структурно файл *.glt выглядит так:

  • первые 4 байта - это "подпись", определяющая тип файла и версию - 0x02544C47 для GLT второй версии (0x01544C47 было для GLT первой версии);
  • затем идёт заголовок с настройками и параметрами текстуры (у первой и второй версий шапки разные - 40 байт для GLT1 и 80 байт для GLT2);
  • массив картинок; каждая картинка имеет шапку (GLTMipmapHeader) и собсно данные (опционально); эта часть файла одинакова для обоих версий, хотя имеет разный оффсет, т.к. шапки разного размера.

Все структуры (GLT1Header, GLT2Header, GLTMipmapHeader) описаны и обкоменчены в GLT.hpp, хотя юзеру и не требуется с ними знакомиться, т.к. класс GLTexture умеет грузить и сохранять *.glt файлы.

 

Итак, включаем GLT.hpp в проект:

#include "GLT.hpp"

Класс GLTexture содержит лишь одну переменную - имя текстуры, т.к. большая часть интерфейса использует функции из расширения Direct State Access (OpenGL4.5). Если это расширение не поддерживается, доступными будут лишь загрузка и сохранение *.glt файлов. Узнать имя текстуры можно так:

//GLTexture Texture;
GLuint Name = Texture.Name();

Класс GLTexture автоматически кастается в GLuint при его использовании в OpenGL функциях там, где требуется имя текстуры. Например:

//GLTexture Texture;
glBindTexture(GL_TEXTURE_2D, Texture);

Это имеет смысл для работы с текстурами на аппаратуре, не поддерживающей DSA из OpenGL4.5, т.к. большинство функций класса GLTexture используют это расширение.

 

Чтобы создать новую текстуру определённого типа и размерности, пользуемся этими функциями:

void GLTexture::Create1D(GLenum internalFormat, GLsizei width, bool Mipmapped=true);

void GLTexture::Create1DArray(GLenum internalFormat, GLsizei width, GLsizei layers, bool Mipmapped=true);

void GLTexture::CreateRectangle(GLenum internalFormat, GLsizei width, GLsizei height);

void GLTexture::Create2D(GLenum internalFormat, GLsizei width, GLsizei height, bool Mipmapped=true);

void GLTexture::Create2DArray(GLenum internalFormat, GLsizei width, GLsizei height, GLsizei layers, bool Mipmapped=true);
 
void GLTexture::Create3D(GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, bool Mipmapped=true);
 
void GLTexture::CreateCubeMap(GLenum internalFormat, GLsizei width, bool Mipmapped=true);

void GLTexture::CreateCubeMapArray(GLenum internalFormat, GLsizei width, GLsizei layers, bool Mipmapped=true);

При создании текстуры требуется указать формат текселя (одна из OpenGLевских констант), размерность базовой картинки (и количество слоёв, если текстура слоёная, т.е. "layered"), а также будут ли у текстуры мипмапы (обычно да, поэтому последний параметр можно не указывать).

 

Сами же картинки загружаются этими функциями:

void GLTexture::SubImage1D(GLint level,
                           GLint xoffset,
                           GLsizei width,
                           GLenum format, GLenum type, const void *pixels);
 
void GLTexture::SubImage1DArray(GLint level,
                                GLint xoffset, GLint layerOffset,
                                GLsizei width, GLsizei layers,
                                GLenum format, GLenum type, const void *pixels);

void GLTexture::SubImageRectangle(GLint xoffset, GLint yoffset,
                                  GLsizei width, GLsizei height,
                                  GLenum format, GLenum type, const void *pixels);
 
void GLTexture::SubImage2D(GLint level,
                           GLint xoffset, GLint yoffset,
                           GLsizei width, GLsizei height,
                           GLenum format, GLenum type, const void *pixels);
 
void GLTexture::SubImage2DArray(GLint level,
                                GLint xoffset, GLint yoffset, GLint layerOffset,
                                GLsizei width, GLsizei height, GLsizei layers,
                                GLenum format, GLenum type, const void *pixels);
 
void GLTexture::SubImage3D(GLint level,
                           GLint xoffset, GLint yoffset, GLint zoffset,
                           GLsizei width, GLsizei height, GLsizei depth,
                           GLenum format, GLenum type, const void *pixels);
 
void GLTexture::SubImageCubeMap(GLint level,
                                GLint xoffset, GLint yoffset, GLint layerFaceOffset,
                                GLsizei width, GLsizei height, GLsizei layerFaces,
                                GLenum format, GLenum type, const void *pixels);

void GLTexture::SubImageCubeMapFace(GLenum targetFace, GLint level,
                                    GLint xoffset, GLint yoffset,
                                    GLsizei width, GLsizei height,
                                    GLenum format, GLenum type, const void *pixels);

void GLTexture::SubImageCubeMapArrayFace(GLenum targetFace, GLint layer, GLint level,
                                         GLint xoffset, GLint yoffset,
                                         GLsizei width, GLsizei height,
                                         GLenum format, GLenum type, const void *pixels);

Параметры следующие:

level - уровень мипмапы, для которой указывается картинка (у текстур типа GL_TEXTURE_RECTANGLE мипмапов нет, лишь базовая картинка).

xoffset, yoffset, zoffset - смещение в пикселах от левого нижнего переднего края картинки; обычно 0, если вся картинка загружается целиком, а не по частям.

layerOffset - для слоёных текстур это номер слоя, с которого начинается перезаписываемый регион картинок.

layerFaceOffset - то же, что и layerOffset, но для текстур типа GL_TEXTURE_CUBE_MAP и GL_TEXTURE_CUBE_MAP_ARRAY, для которых слои играют роль картинок для различных сторон куба. Чтобы не запутаться со сторонами и слоями, особенно для слоёных куб-мапов, где всё вперемежку и абы как, я ввёл несколько функций, позволяющих конкретно указывать сторону и номер слоя отдельно загружаемой картинки (функция SubImageCubeMapFace для обычных кубмапов и SubImageCubeMapArrayFace для слоёных кубмапов).

targetFace - для кубмапов этот параметр указывает на конкретную сторону куба (GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, ...).

width, height, depth, layers (layerFaces) - количество пикселей в передаваемой картинке и слоёв (если сразу несколько слоёв грузятся разом).

format, type, pixels - эти параметры описывают передаваемую картинку: format+type определяют формат пикселя, а pixels - собственно указатель на массив данных. Не забывайте о padding bytes - каждый ряд пикселей должен иметь длину, кратную 4 байтам. К примеру, если формат GL_BGR и тип - GL_UNSIGNED_BYTE (у стандартных bmp-шек так), и ширина картинки - 2 пикселя, то это 6 байт данных - непозволительный размер. Соответственно, каждый ряд должен иметь в конце 2 лишних байта, дотягивающих длину до 8 байт. В битмапах так и есть, так что их можно грузить как есть. Но если Вы создаёте текстуру процедурно, эту мелочь нужно учитывать.

 

Если Вы создали текстуру с мипмапами, но ограничились загрузкой лишь базовой картинки, автоматически мипмапы генерируются этой функцией:

inline void GLTexture::GenerateMipmaps();

Чтобы настроить параметры текстуры, используйте эти функции:

//Setup the minification filtering mode
inline void GLTexture::SetMinFilter(GLenum minFilter);

//Setup the magnification filtering mode
inline void GLTexture::SetMagFilter(GLenum magFilter);

//Set the wrapping parameter for s coordinate
inline void GLTexture::SetWrapS(GLenum wrap_s);

//Set the wrapping parameter for t coordinate
inline void GLTexture::SetWrapT(GLenum wrap_t);

//Set the wrapping parameter for r coordinate
inline void GLTexture::SetWrapR(GLenum wrap_r);

//Set the swizzling parameters
inline void GLTexture::SetSwizzle(GLenum swizzle_r=GL_RED,
                                  GLenum swizzle_g=GL_GREEN,
                                  GLenum swizzle_b=GL_BLUE,
                                  GLenum swizzle_a=GL_ALPHA);

//Set the border color
inline void GLTexture::SetBorderColor(const GLuint *ColorRGBA);

//Set the border color
inline void GLTexture::SetBorderColor(const GLint *ColorRGBA);

//Set the border color
inline void GLTexture::SetBorderColor(const GLfloat *ColorRGBA);

//Set GL_DEPTH_STENCIL_TEXTURE_MODE to GL_STENCIL_INDEX
inline void GLTexture::SelectStencilMode();

//Set GL_DEPTH_STENCIL_TEXTURE_MODE to GL_DEPTH_COMPONENT
inline void GLTexture::SelectDepthMode();

//Set GL_TEXTURE_COMPARE_MODE to GL_COMPARE_REF_TO_TEXTURE and then set a given
//value for GL_TEXTURE_COMPARE_FUNC; permissible values are: GL_LEQUAL,
//GL_GEQUAL, GL_LESS, GL_GREATER, GL_EQUAL, GL_NOTEQUAL, GL_ALWAYS, GL_NEVER
inline void GLTexture::ConfigureShadowmap(GLenum CompareFuncToUse);

//Set GL_TEXTURE_LOD_BIAS parameter
inline void GLTexture::SetLODBias(GLfloat Value);

//Set GL_TEXTURE_MIN_LOD parameter
inline void GLTexture::SetMinLOD(GLint Value);

//Set GL_TEXTURE_MAX_LOD parameter
inline void GLTexture::SetMaxLOD(GLint Value);

Учтите, что в *.glt файл сохраняются лишь filter, wrap, swizzle и border color параметры. Картинку карты тени или трафарета можно сохранить, но настройки в файл не пойдут - при сохранении и последующей загрузке эти параметры вернутся в дефолтное состояние.

 

Узнать параметры текстуры можно в любой момент (без биндинья) этими функциями:

//Return the value of the requested texture parameter
inline GLint GLTexture::GetParameteri(GLenum pname)const;

//Return the value of the requested texture parameter
inline GLfloat GLTexture::GetParameterf(GLenum pname)const;

//Return the value of the requested vector texture parameter
inline void GLTexture::GetParameterv(GLenum pname, GLint *params);

//Return the value of the requested vector texture parameter
inline void GLTexture::GetParameterv(GLenum pname, GLfloat *params)const;

//Return the value of the requested vector texture parameter
inline void GLTexture::GetParameterIv(GLenum pname, GLint *params);

//Return the value of the requested vector texture parameter
inline void GLTexture::GetParameterIv(GLenum pname, GLuint *params)const;

//Return the value of the requested parameter for the specified level
inline GLint GLTexture::GetLevelParameteri(GLint level, GLenum pname)const;

Вариант GetParameterIv отличается от GetParameterv тем, что используется лишь для возвращения цвета бордера текстур integer-формата.

 

Некоторые ширпотребные параметры удостоены чести иметь свои отдельные функции:

//Return the target type of the texture or 0 on failure
inline GLenum GLTexture::Target()const;

//Return internalFormat value for the mipmap of the specified level
inline GLenum GLTexture::InternalFormat(GLint level=0)const;

//Get texture's width
inline GLint GLTexture::Width(GLint level=0)const;

//Get texture's height (or number of layers if type is GL_TEXTURE_1D_ARRAY)
inline GLint GLTexture::Height(GLint level=0)const;

//Get texture's depth (or number of layers if it is one of 2D array textures)
inline GLint GLTexture::Depth(GLint level=0)const;

Тут нужно учесть, что для слоёных текстур Height или Depth будут возвращать количество слоёв, а не высоту или глубину картинки в пикселях, несмотря на название функции. Если не указывать уровень мипмапы, то по-умолчанию будут возвращаться параметры базовой картинки.

 

Привязать текстуру к указанному текстурному юниту можно так:

//GLTexture Texture;
Texture.Bind(GL_TEXTURE0);

Загрузка из файла *.glt:

//GLTexture Texture;
bool Success = Texture.LoadFromFile("Texture.glt");

Возвращённое значение (Success) будет true в случае успеха.

Если файл уже загружен в память (если, например, в один файл запихано несколько текстур, моделей и других данных), то текстуру можно загрузить и оттуда. Нужно лишь указать на то место, где начинается кусок, принадлежащий текстуре (начинается с 4хбайтной сигнатуры GLT1 или GLT2). Например, у нас есть файл, склееный из двух *.glt файлов, т.е. содержащий две текстуры. В таком случае грузим их так:

GLTexture Texture1, Texture2;
  
int Handle=-1; //File handle
_sopen_s(&Handle, "Textures.pak", _O_RDONLY|_O_BINARY,_SH_DENYWR,_S_IREAD);
int FileSize=_filelength(Handle);
char* Buffer=(char*)malloc(FileSize);
_read(Handle,Buffer,FileSize);
_close(Handle);

void* ptr1 = Buffer;
unsigned int BytesLoaded = Texture1.LoadFromBuffer(ptr1);

void* ptr2 = Buffer+BytesLoaded;
Texture2.LoadFromBuffer(ptr2);

free(Buffer);

Логичный вопрос - отчего стримовую загрузку не предоставить? А потому, что при загрузке отдельных мипмапов ОпенГЛ требует указатель на картинку, поэтому при стримовой загрузке пришлось бы лишний раз отводить память (и, возможно, не один раз) и копировать туда части файла с массивом пикселей.

 

А вот сохранение текстур может идти стримом:

//GLTexture Texture1, Texture2;
FILE* Stream = _fsopen("Textures.pak","wb",_SH_DENYWR);

bool Success1 = Texture1.SaveToStream(Stream);

bool Success2 = Texture2.SaveToStream(Stream);

fclose(Stream);

В отдельный файл сохраняется текстура так:

//GLTexture Texture;
bool Success = Texture.SaveToFile("Texture.glt");

Вотъ.  :)







Темы с аналогичным тегами OpenGL, texture, image, GLTexture

Количество пользователей, читающих эту тему: 0

0 пользователей, 0 гостей, 0 анонимных