Войти
ПрограммированиеСтатьиГрафика

Работа с расширениями OpenGL с использованием NVIDIA OpenGL SDK 5.1. (Часть 6) (5 стр)

Автор:

Использование расширения EXT_texture_compression_s3tc

Перед тем как, начать использовать расширение EXT_texture_compression_s3tc, его надо проинициализировать. Но если вы захотите проинициализировать  это расширение командой glh_init_extensions("GL_EXT_texture_compression_s3tc"), то вас ждёт неприятный сюрприз - вы будите всё время получать сообщение о том, что это расширение не найдено. Мне кажется, что это связано с ошибкой в заголовочном файле glext.h в котором пропущены следующие строки:


#ifndef GL_EXT_texture_compression_s3tc
#define GL_EXT_texture_compression_s3tc 1

Это приводит к тому, что библиотека GLH считает, что текущая версия заголовочных файлов OpenGL не поддерживает это расширение.

Выход из этой ситуации - добавить строку "#define GL_EXT_texture_compression_s3tc 1" после директивы "#include <gl/glext.h>", но до подключения библиотеки GLH.

После этого, работа с этим расширением почти не отличается от ARB_texture_compression: у нас появляется 4 новых формата текстур (GL_COMPRESS_RGB_S3TC_DXT1_EXT, GL_COMPRESS_RGBA_S3TC_DXT1_EXT, GL_COMPRESS_RGBA_S3TC_DXT3_EXT, GL_COMPRESS_RGBA_S3TC_DXT5_EXT), которые используются аналогично форматам  GL_COMPRESSED_RGB_ARB или GL_COMPRESSED_RGBA_ARB расширения ARB_texture_compression.

Для демонстрации работы с расширением EXT_texture_compression_s3tc было написано простое приложение (Ex03), позволяющее циклически изменять тип сжатия текстур клавишей "n" и наблюдать за результатом. При этом в консоль выводится информация об успешной/неудачной компрессии текстур. С точки зрения программиста в этой программе нет ничего особенного. Единственное, что можно отметить -  это то, что в методе add() класса glut_console была исправлена ошибка: если в активную консоль вносились изменения командой add, то она не перерисовывалась.

С использованием этой программы было проведено небольшое исследование качества сжатия текстур различными методами. При этом использовался компьютер следующей конфигурации: GeForce2MX 32MB, Windows XP В качестве примеров текстур были выбраны 2 текстуры из 3DS MAX 3: текстура стены высокого разрешения (наиболее благоприятный случай) и текстура неба низкого разрешения (наименее благоприятный случай). Результаты изображены на рисунках 3-8.

Изображение
Рисунок 3. Несжатая текстура

Изображение
Рисунок 4. Текстура формата GL_COMPRESS_RGB_S3TC_DXT1_EXT

Изображение
Рисунок 5. Текстура формата GL_COMPRESS_RGBA_S3TC_DXT5_EXT

Изображение
Рисунок 6. Несжатая текстура

Изображение
Рисунок 7. Текстура формата GL_COMPRESS_RGB_S3TC_DXT1_EXT

Изображение
Рисунок 8. Текстура формата GL_COMPRESS_RGBA_S3TC_DXT5_EXT

Всё вроде бы согласуется с нашими теоретическими выводами: при сжатии монотонной текстуры стены качество практически не изменяется, а при сжатии текстуры неба, содержащей большое количество разных оттенков, наблюдается явная деградация качества, приводящая к сильном бандингу (резкому переходу между цветами). Но при внимательном рассмотрении рисунков мы заметим одну особенность, которая никак не стыкуется с нашими теоретическими  рассуждениями - качество форматов сжатия GL_COMPRESS_RGB_S3TC_DXT1_EXT и GL_COMPRESS_RGBA_S3TC_DXT5_EXT различаются, причём качество последнего значительно выше. Казалось бы, этого не может быть, так как эти форматы кодируют/декодируют RGB-составляющую текстуры по одинаковому алгоритму. А на видеокартах NVIDIA семейства GeForce2 (к другим видеокартами я пока не имею доступа, поэтому на счёт них я точно не уверен) разница в качестве видна невооруженным глазом.

Похоже, это связано с тем, видеокарты NVIDIA при распаковке текстур GL_COMPRESS_RGB_S3TC_DXT1_EXT работают с 16-битным текселем, выполняя все промежуточные операции с точностью 16-бит. А это поводит к накоплению погрешности (почти все коэффициенты в таблицах 2, 4 и 5  являются периодическими дробями), что в свою очередь приводит к бандингу. Для борьбы с этим явлением современные драйверы Detonator умеют форсировать использование формата сжатия GL_COMPRESS_RGBA_S3TC_DXT3_EXT вместо GL_COMPRESS_RGB_S3TC_DXT1_EXT. Если вы пользуетесь твикером NVMAX, то можете включить этот режим, включив переключатель "S3TC v3 compression" из раздела "OpenGL\Textures". Но здесь имеется маленький подвох - этот параметр действует только в том случае, если приложение явно использует формат сжатия GL_COMPRESS_RGB_S3TC_DXT1_EXT. Если же этот формат был самостоятельно выбран драйвером OpenGL, например, при использовании формата текстур GL_COMPRESSED_RGB_ARB, то приложение будет работать с текстурами формата GL_COMPRESS_RGB_S3TC_DXT1_EXT независимо от значения параметра "S3TC v3 compression". (Это утверждение верно для последней версии Detonator на момент написания статьи (29.42))

В итоге, мы получаем интересный вывод - если при разработке приложений вы ориентируетесь в первую очередь на видеокарты NVIDIA, то НИКОГДА не следует использовать автоматический выбор сжатия GL_RGB текстур канала (GL_COMPRESSED_RGB_ARB), т.к. в этом случае пользователь мощной видеокарты не сможет повысить качество изображения. Наилучший вариант - предоставить возможность пользователю самому выбирать формат сжатия текстур. При этом текстуры желательно разделить на несколько групп (текстуры пола/стен, неба, карты теней и т.д. ) и позволить пользователю настраивать сжатие каждой группы текстур по отдельности.

Для того, чтобы грамотно использовать мощный инструмент надо хорошо знать как его сильные, так и слабые стороны. Давайте попробуем составить требования к текстуре, которая сжималась бы с наихудшим качеством:
1. Текстура должна невысокого разрешения
2. Каждый соседний пиксель текстуры должен быть своего цвета
3. Цвета пикселей должны быть подобраны таким образом, чтобы не один из цветов внутри блока 4x4 не мог быть получен путём интерполяции двух соседних цветов.

В действительности, наихудшее качество будет получено при сжатии текстуры точек случайных цветов. Но дефекты сжатия такой текстуры не будут сильно заметны.

Остановимся на последнем пункте. Ранее уже указывалось, что в процессе компрессии текстуры видеокарта выбирает два цвета внутри текстуры, а остальные цвета вычисляется по формуле  C=C1*k1+*k2*C2. При этом можно заметить, что коэффициенты k1 и k2 связаны соотношением k2=1-k1, т.е. формулу вычисления цвета можно переписать следующим образом: C=C1*k1+*(1-k1)*C2. Но т.к. каждый цвет состоит из трёх компонентов, видеокарте приходится решать систему из трёх уравнений с одним неизвестным:

R=R1*k1+*(1-k1)*R2

G=G1*k1+*(1-k1)*C2
B=B1*k1+*(1-k1)*B2

А такая система, как известно не всегда имеет решение. Следовательно, нам необходимо подобрать цвета C, C1 и C2 таким образом, чтобы эта система уравнений не имела решения, т.е. не один из цветов внутри блока 4x4 не мог быть получен путём интерполяции двух соседних цветов.

Для того чтобы получить такую текстуру, я написал небольшую программу на Borland Delphi 6 (Ex04). Ниже приведён фрагмент кода, отвечающего за генерацию текстуры:

  for j:=0 to Image1.Picture.Graphic.Height-1 do
   for i:=0 to Image1.Picture.Graphic.Width-1 do
   begin
    Image1.Picture.Bitmap.Canvas.Pixels[i, j]:=
      RGB(Trunc(abs((1.0-2*i/Image1.Picture.Graphic.Width)*255)),
          0,
          Trunc(abs((2*j/Image1.Picture.Graphic.Height-1.0)*255)));
   End;

При помощи этой программы была создана текстура 64x64 (рисунок 9). Результат компрессии изображён на рисунке 10.

Изображение
Рисунок 9. Несжатая текстура

Изображение
Рисунок 10. Сжатая текстура формата GL_COMPRESS_RGBA_S3TC_DXT5_EXT

Как видно, при компрессии такой текстуры начинают "вырисовываться" блоки компрессии размером 4x4 текселя, но фильтрация текстур скрывает все остальные огрехи. Для оценки реальных искажений, отключим фильтрацию текстур (рисунок 11).

Изображение
Рисунок 11. Сжатая текстура формата GL_COMPRESS_RGBA_S3TC_DXT5_EXT с выключенной фильтрацией текстур

Изображение
Рисунок 12. Увеличенный фрагмент сжатой текстуры формата GL_COMPRESS_RGBA_S3TC_DXT5_EXT с выключенной фильтрацией текстур

Давайте внимательно посмотрим на эту сжатую текстуру. На рисунке 12 показан увеличенный фрагмент этой текстуры, на котором отчетливо видны "квадраты" размером 4x4 текселя, причём для закраски текселей  каждого "квадрата" используется только 4-ре цвета. Кроме того, на рисунке хорошо видно, что в этом фрагменте видеокарта "решила" пожертвовать красным цветом в пользу синего.

Обратите внимание, что мы используем максимальное качество компрессии текстур. При использовании формата  GL_COMPRESS_RGB_S3TC_DXT1_EXT NVIDIA-картах качество сжатия  будет ещё хуже.

Вот и всё на этот раз. В следующей части мы рассмотрим вопросы сохранения сжатых текстур на диске, добавим в наш интерактор консоли командную строку и многое другое.

Список использованной литературы
1. NVIDIA OpenGL Extension Specifications
2. Sebastien Domine "Using texture compression in OpenGL" (www.nvidia.com/developer).
3. Справочная система DirectX 8 SDK.
4. Алексей Берилло "Обзор форматов текстурного сжатия S3TC и FXT1 и сравнение с 16-битными текстурами" (www.ixbt.com)
5. 3DGiТоги - Влияние технологии S3TC (FXT1) на качество и скорость (www.ixbt.com)

Страницы: 1 2 3 4 5

#расширения OpenGL, #NVIDIA, #OpenGL

13 апреля 2003 (Обновление: 6 окт. 2009)