Работа с расширениями OpenGL с использованием NVIDIA OpenGL SDK 5.1. (Часть 7) (3 стр)
Автор: Сергей Гайдуков
Загрузка сжатых текстур из файлов формата DDS.
Большинство программ для хранения сжатых текстур используют формат DDS (Direct Draw Surface). Как видно из названия, этот формат предназначен для приложений, использующих API DirectDraw и Direct3D. Формат DDS обладает следующими преимуществами по сравнению с другими распространёнными форматами: возможность хранения текстуры вместе со всеми MipMap-уровнями в одном файле, возможность сохранения 6-ти двухмерных текстур кубической текстуры в одном файле и, наконец, поддержка форматов сжатых текстур S3TC (DXT1, DXT2, DXT3, DXT4 и DXT5). Причём, не смотря на то, что этот формат был разработан для API DirectX, его можно довольно легко "подружить" и с OpenGL.
Существует множество утилит для создания DDS файлов: плагины для Photoshop, 3DS MAX и т.д. Для создания DDS файлов для этой статьи я использовал утилиту nvdxt, которую можно скачать либо с сайта NVIDIA Developer (http://developer.nvidia.com/), либо в составе примеров с этого сайта (www.gamedev.ru). Хотя данная утилита и предназначена для работы в командной строке, ей очень просто пользоваться. Создавая примеры для этой статьи, я использовал команды следующего формата:
nvdxt.exe -file "имя файла" {-формат сжатия=dxt1/dxt3/dxt5}.
Т.е. если нам необходимо сжать файл wood.tga в wood.dds используя формат DXT5, то можно воспользоваться командой
nvdxt.exe -file WOOD.TGA -dxt5.
Мы рассмотрим работу с файлами формата DDS с использование класса CTexture из состава NVIDIA OpenGL SDK. Конечно, с файлами формата DDS можно работать и напрямую, как мы поступили с форматом SCI, но это лишь усложнит программу и увеличит вероятность появления ошибок. Но если вам всё таки необходимо работать с DDS-файлами напрямую, то можно посоветовать посмотреть исходники класса CTexture.
Перед использованием этого класса в каталог с проектом программы следует скопировать файлы nv_dds.h и nv_dds.cpp, которые находятся в каталогах ":\include\shared" и ":\src\shared" соответственно. После этого первый файл подключается к программе директивой #include, второй - через меню Visual Studio (Project -> Add New Item ..., см. рис. 5).
Рисунок 5.
Использование этого класса проще всего показать на примере - модификации программы Ex03 из предыдущей части статьи, в которую добавлена поддержка чтения текстур из DDS-файлов (Ex04):
//Создание объекта для работы с файлами формата DDS CDDSImage image; //Загрузка файла в память if (!image.load( filename)) { console.add( "Bad file or file not found"); return; } //Загрузка текстуры в видеопамять glCompressedTexImage2DARB( texture0.target, 0, image.format, image[0].width, image[0].height, 0, image[0].size, image[0]); char str[200]; sprintf( &str[0], "loading %d mipmaps...", image[0].mipmaps.size( )); console.add( str); //Загрузка остальных MipMap-уровней в видеопамять for ( int i=0; i<image[0].mipmaps.size( ); i++) { glCompressedTexImage2DARB( texture0.target, i+1, image.format, image[0].mipmaps[i].width, image[0].mipmaps[i].height, 0, image[0].mipmaps[i].size, image[0].mipmaps[i]); }
Как видно, работа с файлами формата DDS осуществляется при помощи объекта класса CDDSImage. Загрузка текстуры осуществляется методом load(), который в случае успешной загрузки возвращает ненулевое значение. Обратите внимание, что на самом деле метод load() принимает ещё и второй аргумент flipImage, который по умолчанию равен true. Если этот параметр равен true, то текстура переворачивается при загрузке. Загруженные текстуры сохраняются в объектах класса CTexture, которые находиться поле-векторе images класса CDDSImage, доступ которому возможен и использованием перегруженного оператора []. Однако, если вы не используете кубических текстур, в поле images будет храниться всего одна текстура. Ширина, высота, формат пикселей и размер текстуры хранятся в полях width, height, format и size соответственно. Указатель на образ сжатой текстуры хранится в поле pixels подобъекта image, имеющего класс CSurface, причём доступ к полю pixels может быть осуществлен при помощи перегруженного оператора operator char* класса CTexture, т.е. вместо ссылки на образ сжатой текстуры можно просто указывать экземпляр класса CDDSImage.
Если DDS-файл содержит MipMap-уровни, то они будут размещены в объектах класса CSurface, которые находятся в поле-векторе image соответствующих объектов класса CTexture. Класс CSurface так же имеет поля width, height, format и size, которые аналогичны полям класса CTexture.
Как указывалось выше, файлы формата DDS могут содержать и образа несжатых текстур. Поэтому реальное приложение должно сначала определить формат пикселей текстуры, а затем использовать команды glTexImage() и glCompressedTexImage() для загрузки соответственно несжатых и сжатых текстур.
Стоит так же отметить небольшую модификацию интерактора консоли glut_console, в которую была добавлена поддержка истории команд.
Загрузку DDS файлов можно ещё упростить, воспользовавшись методом upload_texture_2D класса CDDSImage, использование которого продемонстрировано в следующем примере (Ex05):
CDDSImage image; if (!image.load( filename)) { console.add( "Bad file or file not found"); return; } //При использовании обычных (не кубических) текстур, первый параметр всегда равен 0. if ( !image.upload_texture2D( 0, texture0.target)) { console.add( "Unsupported type of texture"); return; }
Кроме того, в этот пример добавлена поддержка работы с файлами tga. Это сделано для более точного анализа потери качества текстур при S3TC-компрессии, т.к. JPG-текстуры даже максимального качества всё равно проигрывают в качестве оригинальным текстурам.
В заключение обзора работы со сжатыми текстурами я хотел обратить ваше внимание на то, что хранение текстур на диске в сжатом виде связано с потенциальной опасностью. Дело в том, что если приложение запустится на видеокарте, которая не поддерживает сжатие текстур, то использовать эти текстуры будет невозможно. Кроме того, возможна ещё более неприятная ситуация - видеокарта поддерживает работу со сжатыми текстурами, но не поддерживает формат сжатия, в который использует сжатая текстура. Поэтому, если вы рассчитываете, что вашу программу будут использовать на ускорителях 4-х летней давности и ваше приложение очень критично к занимаемому месту на диске, то сжатые текстуры лучше всего хранить в JPG-файлах, а при загрузке в видеопамять использовать автокомпрессию текстур.
Расширения ARB_texture_compression и EXT_texture_compression_s3tc поддерживаются всеми видеокартами NVIDIA начиная с GeForce256.
На этом всё.
Исходный код примеров: ExNV_7.rar.
#расширения OpenGL, #NVIDIA, #OpenGL, #компрессия, #текстуры
7 июня 2003 (Обновление: 13 ноя 2009)