Работа с расширениями OpenGL с использованием NVIDIA OpenGL SDK 5.1. (Часть 1) (2 стр)
Автор: Сергей Гайдуков
Расширение NV_texture_rectangle
При разработке OpenGL-приложений непрофессиональные разработчики часто используют готовые текстуры сторонних производителей. Однако часто они имеют разрешение, не кратное степени 2, а OpenGL не поддерживает работу с такими текстурами. Попросить художников рисовать текстуры с нужным разрешением не всегда возможно, и в итоге программисту приходится искусственно повышать разрешение текстуры до степени, кратной 2, а это приводит к двум проблемам:
1. Избыточные затраты памяти. Например, текстуру 640x480:32 придется увеличить до 1024x512:32, т.е. объем необходимой видеопамяти увеличится на 868KB (41%).
2. Размер текстуры увеличивается в нецелое число раз, а это негативно сказывается на качестве изображения.
К счастью, видеокарты NVIDIA поддерживают расширение GL_texture_rectangle, которое позволяет использовать текстуры размера, не кратного степени 2. Наложение этого типа текстур включается командой glEnable с параметром GL_TEXTURE_RECTANGLE_NV. Но при работе с текстурами этого типа надо учитывать одно важное отличие: текстурные координаты измеряются не в относительных, а в абсолютных величинах (от 0 до ширины или высоты текстуры минус 1). Кроме того, максимальный размер текстуры этого типа на GeForce2 MX равен 2046x2046, а не 2048x2048. Рассмотрим небольшой пример, выводящий на экран плоскость с наложенной текстурой дерева 512x768, взятой из 3DS MAX 4 (рис. 3).
Рисунок 3.
Программа очень простая: после инициализации расширения мы включаем режим наложения текстур, не кратных степени 2, и настраиваем параметры наложения:
glEnable(GL_TEXTURE_RECTANGLE_NV); glPixelStorei( GL_UNPACK_ALIGNMENT, 1); ... glBindTexture( GL_TEXTURE_RECTANGLE_NV, Texture0); glTexParameterf( GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST); //Установка параметров фильтрации glTexParameterf( GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D( GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA, pTexture0->width, pTexture0->height, 0, pTexture0->format, GL_UNSIGNED_BYTE, pTexture0->pixels); glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
Обратите внимание на команду glPixelStorei, включающую побайтное выравнивание строк текстуры, т.е. следующая строка начинается сразу после предыдущей (по умолчанию строки текстуры выравниваются по границе двойного слова). Если этого не сделать, то при использовании текстур, шириной не кратной 4, могут возникнуть искажения (см. рис. 4).
Рисунок 4.
После этого создается плоскость, на которую будет нанесена текстура, причем текстурные координаты задаются в абсолютных величинах:
glBegin(GL_QUADS); glTexCoord2f( 0, 0); glVertex3f( -1, -1, 0); glTexCoord2f( 0, pTexture0->height-1); glVertex3f( -1, 1, 0); glTexCoord2f( pTexture0->width-1, pTexture0->height-1); glVertex3f( 1, 1, 0); glTexCoord2f( pTexture0->width-1, 0); glVertex3f( 1, -1, 0); glEnd( )
Этот подход работает только в том случае, если мы задаем координаты текстур вручную. Если же мы используем готовые объекты библиотек GLU/GLUT или включаем режим автоматической генерации текстурных координат (сферических и т.д.), то текстурные координаты будут автоматически нормализованы (приведены к диапазону 0..1). Следовательно, нам надо как-нибудь привести их к диапазону 0..[ширина или высота текстуры]-1. Это можно сделать путем масштабирования матрицы текстуры, что демонстрируется в следующем проекте (рис. 5).
Перед рисованием чайника происходит масштабирование матрицы текстуры, причем коэффициент масштабирования вдоль каждой оси меньше размера текстуры по этой оси на 1:
glMatrixMode(GL_TEXTURE); glScalef( pTexture0->width-1, pTexture0->height-1, 1); glMatrixMode( GL_MODELVIEW); //... glutSolidTeapot( 1);
Хотя расширение NV_texture_rectangle и позволяет работать с текстурами произвольного размера, этой возможностью не стоит злоупотреблять. Дело в том, что при использовании этих текстур не может применяться MipMap-фильтрация, эти текстуры не могут использоваться в качестве кубических текстур и т.д. Применение этих текстур может привести к ощутимому снижению быстродействия.
Для приближенной оценки падения быстродействия я модифицировал пример с чайником с белыми бликами, заменив текстуры GL_TEXTURE_2D текстурами GL_TEXTURE_RECTANGLE_NV. Тестирование проводилось на компьютере следующей конфигурации: PIII-800EB, GeForce2MX 32MБ, Windows XP, Detonator 28.32. Результаты измерений приведены в таблице ниже:
Разрешение экрана
(ширина* высота :бит на пиксель) | Параметры текстуры | Тип текстуры | Производительность (FPS) |
640x480:32 | 2048x2048:32 | GL_TEXTURE_2D | 21 |
640x480:32 | 2046x2046:32 | GL_TEXTURE_RECTANGLE_NV | 17 |
640x480:32 | 640x480:32 | GL_TEXTURE_RECTANGLE_NV | 43 |
640x480:32 | 1024x512:32 | GL_TEXTURE_2D | 43 |
Из этой таблицы можно сделать вывод, что текстуры GL_TEXTURE_RECTANGLE_NV медленнее, чем обычные текстуры примерно на 20% при одинаковом разрешении. При оценке производительности я исходил из реальной задачи. Пусть у нас имеется текстура 640x480:32 и ее надо использовать в OpenGL. В этом случае мы можем либо увеличить ее размер до 1024x512:32, либо использовать расширение NV_texture_rectangle. Как видно, в этом случае производительность примерно равна, но текстура GL_TEXTURE_RECTANGLE_NV обеспечивает лучшее качество, а GL_TEXTURE_2D - поддержку Mipmap-фильтрации.
Мне не удалось найти точное соотношение между производительностью текстур GL_TEXTURE_2D и GL_TEXTURE_RECTANGLE_NV. Как мне кажется, оно зависит от многих факторов. Например, если в примерах Ex04 и Ex07 использовать текстуры 2048x1024:32 и 2046x1024:32 соответственно, то разность в производительности будет около 1%. Если же чайник увеличить с 2 единиц до 2.5, то в примере с текстурой GL_TEXTURE_2D скорость почти не изменится, а в случае GL_TEXTURE_RECTANGLE_NV - упадет почти на 50%. В других случаях геометрические размеры объектов почти не влияют на производительность.
Расширение GL_NV_texture_rectangle поддерживается всеми видеокартами NVIDIA, начиная с GeForce256. Обратите внимание, что название этого расширения начинается с NV, т.е. это расширение не является стандартным расширением OpenGL. В итоге большинство не-NVIDIA акселераторов его не поддерживает. Например, если верить списку расширений, его не поддерживают все видеокарты ATI, включая Radeon 8500 (правда, я сам лично в руках Radeon не держал, поэтому точно в этой информации не уверен).
На этом пока все. Во второй части статьи будут рассмотрено использование расширения GL_ARB_multitexture, без которого в настоящее время не обходится не одна серьезная программа.
Исходный код примеров: ExNV_1.rar (756 kB).
#расширения OpenGL, #NVIDIA, #OpenGL, #SDK, #текстурирование, #текстуры
22 февраля 2002 (Обновление: 17 сен 2009)
Комментарии [3]