Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

RedBook

.pdf
Скачиваний:
20
Добавлен:
11.06.2015
Размер:
7.43 Mб
Скачать

9.2.6.3 Управление уровнем детализации мипмапа

MIN_LOD и MAX_LOD представляют минимальное и максимальное значения для (фактора масштаба текстурного изображения к полигону) для минификации и неявно задают, какой из мипмапов следует использовать.

Если ваш полигон занимает 64xx64 пикселя, и MIN_LOD равно своему значению по умолчанию, то есть 0.0, то текстурная карта уровня 0 с разрешением 64x64 тэкселя может быть использована для минификации (заданный BASE_LEVEL=0; как правило, BASE_LEVEL <= MIN_LOD). Однако, если MIN_LOD равен 2.0, то самая большая текстура, которая может быть использована для минификации имеет разрешение 16x16

тэкселей, что соответствует .

MAX_LOD имеет влияние только в том случае, если он меньше максимального (которое равно либо MAX_LEVEL, либо уровню, на котором текстура имеет размер в 1

тэксель). В случае карты текстуры размером 64x64 тэкселя, соответствует мипмапу размером 1x1 тэксель. Если в той же ситуации MAX_LOD равен 4.0, то ни один мипмап меньше чем 4x4 тэкселя не будет использоваться для минификации.

Избирательное использование MIN_LOD может уменьшить количество визуальных артефактов на текстурах с высоким разрешением, а использование MAX_LOD – на текстурах с низким. Вы обнаружите, что использование MIN_LOD незначительно большего BASE_LEVEL и MAX_LOD незначительно меньшего MAX_LEVEL дает наилучшие результаты по сокращению визуальных эффектов, связанных с переходами между мипмапами.

Как и в случае с BASE_LEVEL и MIN_LOD применяется команда в таблице 9-2.

MAX_LEVEL, для управления параметрами MAX_LOD и glTexParameter*(). Возможные значения перечислены

Таблица 9-2. Параметры управления уровнями детализации мипмаппинга

Параметр

Описание

Значения

GL_TEXTURE_MIN_LOD

минимальная величина для

любое значение

 

 

GL_TEXTURE_MAX_LOD

максимальная величина для

любое значение

 

 

 

Следующий код иллюстрирует пример установки параметров управления уровнями детализации.

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_LOD,2.5); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAX_LOD,4.5);

9.2.6.4 Автоматическое создание подмножества мипмапов

При использовании описанного контроля над уровнями мипмапов, вам может понадобиться конструирование только некоторого их подмножества. (Например, вы возможно захотите остановиться на изображении размером 4x4 тэкселя, а не идти до наименьшего мипмапа размером 1x1). Чтобы сконструировать и загрузить подмножество мипмапов, вы можете использовать функцию gluBuild*DMipmapLevels().

int gluBuild1DMipmapLevels (GLenum target, GLint internalFormat, GLint width, GLenum format,

GLenum type, GLint level, GLint base, GLint max, void

*texels);

int gluBuild2DMipmapLevels (GLenum target, GLint internalFormat, GLint width, GLenum height, GLenum format,

GLenum type, GLint level, GLint base, GLint max, void

*texels);

int gluBuild3DMipmapLevels (GLenum target, GLint internalFormat, GLint width, GLenum height, GLenum depth,

GLenum format, GLenum type, GLint level, GLint base,

GLint max, void *texels);

Конструируют серию мипмапов и вызывают glTexImage*D() для загрузки изображений. level индицирует уровень мипмапа изображения, заданного в аргументе texels. Аргументы base и max задают нижнюю и верхнюю границы диапазона уровней мипмапов, которые будут произведены из изображения, заданного аргументом texels.

Остальные аргументы target, internalFormat, width, height, depth, format и type

имеют то же значение, что и для команд glTexImage1D(), glTexImage2D() и glTexImage3D(). В случае успешного выполнения функции, она возвращает 0. Функция возвращает код ошибки GLU в случае неудачи.

Замечание: В GLU версии 1.3 функции gluBuild*DMipmaps() и gluBuild*DMipmapLevels() поддерживают упакованные форматы пикселей (и связанные с ними типы данных), представленные в OpenGL 1.2.

9.3 Фильтрация

Текстурные карты бывают квадратными или прямоугольными, но после наложения на полигон или поверхность и трансформации в экранные координаты, индивидуальные тэксели текстуры редко соответствуют индивидуальным пикселям на экране. В

зависимости от используемых преобразований и параметров текстурирования один пиксель на экране может соответствовать чему угодно от части тэкселя (увеличение) до большой группы тэкселей (уменьшение), как показано на рисунке 9-9. В любом случае не совсем понятно, какие тэксели будут использоваться и как они должны интерполироваться. OpenGL позволяет вам выбирать одну из нескольких опций фильтрации, определяющих процесс означенных вычислений. Эти опции весьма варьируются по соотношениям скорость/качество изображения. Вы можете задавать режимы фильтрации отдельно и независимо для увеличения и уменьшения.

Рисунок 9-9. Увеличение и уменьшение текстуры

В некоторых случаях ответ на вопрос о том, что использовать: увеличение или уменьшение, не является очевидным. Если текстурная карта должна быть растянута или сжата в обоих направлениях (x и y), то требуется увеличение или уменьшение

соответственно. Если же карту текстуры требуется растянуть в одном направлении и сжать в другом, OpenGL делает свой выбор между увеличением и уменьшением, и этот выбор в большинстве случаев дает наилучший результат. Однако лучше избегать ситуаций, используя координаты текстуры, позволяющие наложить ее на объект без подобных искажений.

Следующие строки являются примерами того, как использовать команду glTexParameter*() для выбора методов увеличивающей и уменьшающей фильтрации:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

Первый аргумент команды должен быть установлен в GL_TEXTURE_1D, GL_TEXTURE_2D или GL_TEXTURE_3D в зависимости от вашей текстуры. Для данного обсуждения второй аргумент должен быть установлен либо в GL_TEXTURE_MAG_FILTER, либо в GL_TEXTURE_MIN_FILTER, определяя, задаете ли вы метод фильтрации для увеличения или для уменьшения. Третий аргумент задает метод фильтрации. Все возможные методы перечислены в таблице 9-3.

Таблица 9-3. Методы фильтрации при увеличении и уменьшении

Параметр

Значения

GL_TEXTURE_MAG_FILTER GL_NEAREST, GL_LINEAR

GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST, GL_TEXTURE_MIN_FILTER GL_NEAREST_MIPMAP_LINEAR,

GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR

Если вы выберите GL_NEAREST, то для увеличения и уменьшения будет использоваться тэксель с ближайшими к центру пикселя координатами. Это может привести к нежелательным визуальным эффектам (иногда серьезным). Если же вы выберите GL_LINEAR, то для увеличения или уменьшения будет использоваться взвешенная сумма массива тэкселей 2x2, которые находятся ближе всего к центру пикселя. (В случае трехмерных текстур используется массив размерностью 2x2x2, а в случае одномерных используются два соседних пикселя.) Когда координаты текстуры близки к границе текстурной карты, в массив ближайших тэкселей могут попасть те из них, которые находятся все карты. В таких случаях величины используемых тэкселей зависят от того, какой из режимов GL_REPEAT, GL_CLAMP или GL_CLAMP_TO_EDGE

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

При увеличении, независимо от того, предоставили ли вы мипмапы, всегда используется текстура базового уровня. При уменьшении вы можете выбрать метод фильтрации, который использует один или два наиболее подходящих мипмапа, как описано в следующем абзаце. (Если для уменьшения заданы методы GL_NEAREST или GL_LINEAR, то опять таки будет использована только текстура базового уровня.)

Как показано в таблице 9-3, для уменьшения с применением мипмапов доступно 4 дополнительных метода фильтрации. Внутри индивидуального мипмапа вы можете выбрать ближайший тэксель (GL_NEAREST_MIPMAP_NEAREST) или линейную интерполяцию (GL_LINEAR_MIPMAP_NEAREST). Использование ближайших тэкселей быстрее, но приводит к недостаточно качественным результатам. Выбор того, какой конкретный мипмап использовать зависит от того, какое количество уменьшения требуется; существуют граничные значения, на которых производится переход от одного мипмапа к другому. Чтобы избежать неожиданных переходов, используйте

GL_NEAREST_MIPMAP_LINEAR или GL_LINEAR_MIPMAP_LINEAR для линейной интерполяции величин тэкселей из двух ближайших мипмапов. GL_NEAREST_MIPMAP_LINEAR выбирает ближайшие тэксели в обоих мипмапах, а затем

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

Замечание: Если вы выберите один из фильтров, использующих мипмапы, но забудете загрузить один из необходимых мипмапов, OpenGL не выдаст никаких ошибок, но деактивирует текстурирование. Если не работают ни мипмаппинг, ни просто текстурирование, проверьте загрузили ли вы все нужные мипмапы.

Некоторые из описанных фильтров известны под более популярными именами. GL_NEAREST часто называется точечной фильтрацией (point sampling). GL_LINEAR

известен как билинейная фильтрация (bilinear sampling), поскольку для двумерных текстур используется массив тэкселей размерности 2x2. GL_LINEAR_MIPMAP_LINEAR иногда называют трилинейной фильтрацией (trilinear sampling), поскольку используется линейное среднее между двумя билинейно фильтрованными мипмапами.

9.4 Текстурные объекты

Текстурные объекты хранят данные текстуры и позволяют ими управлять. Вы можете контролировать одновременно несколько текстур и возвращаться к текстурам, которые были загружены ранее. Использование текстурных объектов обычно быстрейший способ работы с текстурами, что выражается в большом выигрыше по производительности, поскольку переключиться на существующую текстуру (повторно использовать ее) можно гораздо быстрее, чем загружать ее заново командой glTexImage*D().

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

Чтобы использовать объекты текстуры для данных текстуры выполните следующие шаги.

Сгенерируйте имена текстур.

Привяжите объекты текстуры к данным текстуры (в частности к массивам изображений и свойствам).

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

Выбирайте (повторно связывайте) ваши текстурные объекты, делая их текущими для визуализации текстурированных моделей.

Замечание: Текстурные объекты появились в OpenGL версии 1.1.

9.4.1 Именование текстурных объектов

В качестве имени текстуры может быть использовано любое ненулевое беззнаковое целое. Чтобы избежать случайного повторного использования имен, постоянно используйте команду glGenTextures() для получения неиспользуемых имен текстур.

void glGenTextures (GLsizei n, GLuint *textureNmes);

Возвращает n неиспользуемых имен текстурных объектов в массиве textureNames. Имена, возвращаемые в массиве textureNames, не обязаны составлять один непрерывный интервал. Возвращенные имена помечаются как используемые, однако следует помнить, что привязка имени к состоянию и размерности текстуры (1D, 2D или 3D) осуществляется только в момент его первой выдачи. Ноль это зарезервированное имя текстуры, и оно никогда не возвращается командой glGenTextures().

Команда glIsTexture() определяет, используется ли конкретное имя текстуры в данный момент. Если имя текстуры было возвращено командой glGenTextures(), но еще не было связано с данными (хотя бы однократным вызовом команды glBindTexture()), команда glIsTexture() возвратит GL_FALSE.

void glIsTexture (GLuint textureName);

Возвращает GL_TRUE, если textureName является именем текстуры, которое было связано и впоследствии не было удалено. Возвращает GL_FALSE в случае, если textureName равно 0, или если оно не равно 0, но не является именем существующей текстуры.

9.4.2Создание и использование текстурных объектов

Одна и та же команда glBindTexture() используется и при создании, и при использовании текстурных объектов. При начальном связывании (с использованием glBindTexture()) создается новый текстурный объект с величинами по умолчанию для изображения текстуры и ее свойств. Последующие обращения к командам glTexImage*(), glTexSubImage*(), glCopyTexImage*(), glCopyTexSubImage*(), glTexParameter*() и glPrioritizeTextures() сохраняются данные в текстурном объекте. Объект текстуры может содержать изображение текстуры и ассоциированные с ним мипмапы (если они присутствуют), а также ассоциированные с текстурой данные, такие как ширина, высота, ширина границы, внутренний формат, разрешение компонент и свойства текстуры. Сохраняемые свойства текстуры включают уменьшающий и увеличивающий фильтры, режим наложения, цвет границы и приоритет.

Когда объект текстуры связывается впоследствии, данные, содержащиеся в нем, становятся текущим состоянием текстуры, замещая предыдущее состояние.

void glBindTexture (GLenum target, GLuint textureName);

glBindTexture() делает три вещи. При использовании в качестве textureName беззнакового целого неравного 0 в первый раз, создается новый объект текстуры, и переданное имя текстуры ассоциируется с ним. Если привязка осуществляется к предварительно созданному объекту текстуры, то этот объект становится текущим. Когда связывание производится при textureName равном 0, OpenGL перестает использовать объекты текстуры и возвращается к безымянной текстуре по умолчанию. При начальном связывании текстурного объекта (то есть при его создании) с ним ассоциируется размерность текстуры, то есть GL_TEXTURE_1D, GL_TEXTURE_2D или GL_TEXTURE_3D, задаваемая в аргументе target. Сразу после начального связывания состояние текстурного объекта совпадает с состоянием GL_TEXTURE_1D, GL_TEXTURE_2D или GL_TEXTURE_3D (в зависимости от размерности текстуры) по умолчанию при инициализации OpenGL. В начальном состоянии свойства текстуры, такие как уменьшающий и увеличивающий фильтры, режим наложения, цвет границы и приоритет установлены в свои значения по умолчанию.

В примере 9-7 в функции init() создаются 2 текстурных объекта. В функции display()

каждый из объектов используется для визуализации одного четырехстороннего полигона. Результат работы программы изображен на рисунке 9-10.

Рисунок 9-10. Два полигона текстурированных с помощью объектов текстуры

#include <glut.h>

#define checkImageWidth 64 #define checkImageHeight 64

GLubyte checkImage[checkImageHeight][checkImageWidth][4]; GLubyte otherImage[checkImageHeight][checkImageWidth][4];

GLuint texName[2];

//Создание изображения текстуры void makeCheckImage()

{

int i,j,c;

for(i=0;i<checkImageHeight;i++)

{

for(j=0;j<checkImageWidth;j++)

{

c=(((i&0x8)==0)^((j&0x8)==0))*255;

checkImage[i][j][0]=(GLubyte)c;

checkImage[i][j][1]=(GLubyte)0;

checkImage[i][j][2]=(GLubyte)0;

checkImage[i][j][3]=(GLubyte)1.0;

c=(((i&0x10)==0)^((j&0x10)==0))*255;

otherImage[i][j][0]=(GLubyte)0;

otherImage[i][j][1]=(GLubyte)c;

otherImage[i][j][2]=(GLubyte)0;

otherImage[i][j][3]=(GLubyte)1.0;

}

}

}

void init(void)

{

glClearColor(1.0,1.0,1.0,0.0); glShadeModel(GL_FLAT); glEnable(GL_DEPTH_TEST);

makeCheckImage(); glPixelStorei(GL_UNPACK_ALIGNMENT,1);

glGenTextures(2,texName);

glBindTexture(GL_TEXTURE_2D,texName[0]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,checkImageWidth,checkImageHeight, 0,GL_RGBA,GL_UNSIGNED_BYTE,checkImage);

glBindTexture(GL_TEXTURE_2D,texName[1]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,checkImageWidth,checkImageHeight, 0,GL_RGBA,GL_UNSIGNED_BYTE,otherImage);

glEnable(GL_TEXTURE_2D);

}

void display(void)

{

glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glBindTexture(GL_TEXTURE_2D,texName[0]); glBegin(GL_QUADS);

glTexCoord2f(0.0,0.0); glVertex3f(-2.0,-1.0,0.0); glTexCoord2f(0.0,1.0); glVertex3f(-2.0,1.0,0.0); glTexCoord2f(1.0,1.0); glVertex3f(0.0,1.0,0.0); glTexCoord2f(1.0,0.0); glVertex3f(0.0,-1.0,0.0); glEnd();

glBindTexture(GL_TEXTURE_2D,texName[1]); glBegin(GL_QUADS);

glTexCoord2f(0.0,0.0); glVertex3f(1.0,-1.0,0.0); glTexCoord2f(0.0,1.0); glVertex3f(1.0,1.0,0.0); glTexCoord2f(1.0,1.0); glVertex3f(2.41421,1.0,-1.41421); glTexCoord2f(1.0,0.0); glVertex3f(2.41421,-1.0,-1.41421); glEnd();

glFlush();

}

void reshape(int w, int h)

{

glViewport(0,0,(GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity();

if (w<=h) glOrtho(-3.0,3.0,-3.0*(GLfloat)h/(GLfloat)w, 3.0*(GLfloat)h/(GLfloat)w,-10.0,10.0);

else glOrtho(-3.0*(GLfloat)w/(GLfloat)h,

3.0*(GLfloat)w/(GLfloat)h,-3.0,3.0,-10.0,10.0); glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

int main(int argc, char **argv)

{

glutInit(&argc,argv); glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH); glutInitWindowSize(620,620); glutInitWindowPosition(100,100); glutCreateWindow("Binding Texture Objects");

init();

glutDisplayFunc(display);

glutReshapeFunc(reshape);

glutMainLoop(); return 0;

}

Если текстурный объект становится активным (то есть вторично связывается), вы можете редактировать его содержимое. Любые вызываемые вами команды, изменяющие изображение текстуры или ее свойства, будут изменять содержимое текущего текстурного объекта.

В примере 9-7 после завершения функции display() вы все еще связаны с текстурой имеющей имя texName[1]. Будьте осторожны: если вы спонтанно вызовите какую-либо команду, изменяющую текущее состояние текстуры, она также изменит и содержимое текущего текстурного объекта.

При использовании мипмапов, все мипмапы, связанные с одним текстурным изображением, должны быть помещены в один текстурный объект. В примере 9-5 уровни мипмапов 0-5 помещаются в один текстурный объект именуемый texName.

9.4.3Очистка текстурных объектов

В то время как вы производите первичное или вторичное связывание текстурных объектов, их данные по-прежнему находятся где-то в текстурных ресурсах. Если эти ресурсы ограничены, удаление текстур является единственным способом освобождения памяти.

void glDeleteTextures (GLsizei n, const GLuint *textureNames);

Удаляет nтекстурных объектов, чьи имена переданы в аргументе textureNames. Освобожденные имена могут быть повторно использованы (например, возвращены командой glGenTextures()). Если удаляется текущая текстура, состояние переходит к текстуре по умолчанию, как если бы была вызвана команда glBindTextures() с аргументом textureName равным 0. Попытки удаления имен несуществующих текстур игнорируются без генерации каких-либо ошибок.

9.4.4Рабочее подмножество резидентных текстур

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

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

Если все текстуры, требуемые приложению, превышают размер кэша, некоторые из них не могут быть резидентными. Если вам нужно выяснить, является ли конкретная текстура резидентной, сделайте ее объект текущим, а затем используйте команду glGetTexParameter*v(), чтобы выяснить значение величины, связанной с переменной состояния GL_TEXTURE_RESIDENT. Если вам нужно выяснить резидентность состояния нескольких текстур, используйте команду glAreTexturesResident().

GLboolean glAreTexturesResident (GLsizei n, const GLuint *textureNames, GLboolean *residences);

Запрашивает текстурный статус резидентности nтекстурных объектов, чьи имена передаются в массиве textureNames. residences это массив, в котором статусы

резидентности возвращаются для соответствующих текстурных объектов в массиве textureNames. Если все текстуры, переданные в массиве textureNames, являются резидентными, команда возвращает значение GL_TRUE, а содержимое массива residences не изменяется. Если хотя бы одна из текстур в textureNamesне является резидентной, команда возвращает GL_FALSE, и элементы массива residences, соответствующие нерезидентным текстурам из массива textureNames, также устанавливаются в GL_FALSE.

Обратите внимание на то, что glAreTexturesResident() возвращает текущий резидентный статус. Текстурные ресурсы очень динамичны, и этот статус может изменяться в любое время. Некоторые реализации кэшируют текстуры в момент их первого использования. Возможно, понадобится нарисовать хотя бы один текстурированный объект, а уже затем проверять резидентность его текстуры.

Если ваша реализация OpenGL не поддерживает рабочего подмножества текстур, то все текстурные объекты всегда считаются резидентными. В этом случае glAreTexturesResident()всегда будет возвращать GL_TRUE.

9.4.4.1Стратегии резидентности текстур

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

ваших текстур или использовать glTexSubImage*() для повторного использования одной и той же текстурной памяти.

Замечание: Если у вас есть несколько текстур одинакового размера, которые нужны лишь на короткий период, вы можете использовать glTexSubImage*() для загрузки новых данных в существующие объекты текстуры. Эта техника может работать быстрее, чем удаление и создание новых текстур.

Для приложений, которые создают текстуры «на лету», избежание нерезидентных текстур может быть трудной задачей. Если определенные текстуры используются чаще, чем другие, вы можете присвоить их текстурным объектам более высокий приоритет, что повысит их шансы на резидентность. Удаление текстурных объектов также освобождает пространство. Говоря коротко, присвоение текстурному объекту низкого

приоритета может сделать его первым в очереди на удаление из рабочего подмножества. Для назначения приоритетов используется команда glPrioritizeTextures().

void glPrioritizeTextures (GLsizei n, const GLuint *textureNames, const GLclampf *priorities);

Команда назначает n приоритетов из массива priorities для n соответствующих текстурных объектов из массива textureNames. перед назначением величины приоритетов приводятся к диапазону [0; 1]. 0 означает низший приоритет (такие текстуры вряд ли будут резидентными), а 1 – наивысший. glPrioritizeTextures() не требует, чтобы какие-либо имена из textureNames были связаны с существующими текстурами. Однако приоритет не имеет никакого действия на объект до тех пор, пока он не связан.

Для назначения приоритета одной текстуре также может быть использована команда glTexParameter*(), но только в том случае, если имя текстуры уже связано. Кроме того, использование glTexParameter*() это единственный способ назначить приоритет текстуре по умолчанию.

Если текстурные объекты имеют одинаковый приоритет, типичная реализация OpenGL при принятии решения о том, какую текстуру следует переместить из рабочего подмножества, применяет стратегию наиболее давно использованного элемента (least recently used -- LRU). Если вы уверены, что в вашей реализации действует именно этот алгоритм, тогда назначение одинаковых приоритетов всем объектам текстуры, создает разумную LRU систему по распределению текстурных ресурсов.

Если ваша реализация OpenGL не использует стратегию LRU для текстурных объектов с одинаковыми приоритетами (или если вы не знаете, какую стратегию она использует), вы можете разработать свою собственную стратегию LRU, аккуратно управляя приоритетами текстурных объектов. Когда текстура находится в использовании (когда

она связывается), вы можете установить максимальный приоритет, что соответствует наиболее недавнему использованию. Затем через регулярные промежутки времени вы можете уменьшать приоритеты всех объектов текстуры.

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

9.4.55Функции текстурирования

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

объект был бы нарисован без текстурирования или комбинировать цвет в карте текстуры с оригинальным цветом поверхности. Вы выбираете одну из 4 функций текстурирования, передавая нужные аргументы команде glTexEnv*().

void glTexEnv{if} (GLenum target, GLenum pname, TYPE param); void glTexEnv{if}v (GLenum target, GLenum pname, TYPE *params);

Устанавливает текущую функцию текстурирования. Аргумент target должен быть установлен в значения GL_TEXTURE_1D, GL_TEXTURE_2D или GL_TEXTURE_3D. Если pname равен GL_TEXTURE_ENV_MODE, то param должен быть равен GL_DECAL, GL_REPLACE, GL_MODULATE или GL_BLEND, задавая метод, которым величины текстуры должны комбинироваться с обрабатываемыми фрагментами. Если pname равен GL_TEXTURE_ENV_COLOR, param представляет собой массив из 4 чисел с плавающей точкой, являющихся компонентами R, G, B и A. Эти величины используются только если текущей функцией текстурирования является GL_BLEND.

Комбинация функции текстурирования и базового внутреннего формата определяет, как применяется текстура для каждого ее компонента. Функции текстурирования оперируют выбранными компонентами текстуры и цветовыми величинами, которые использовались бы без текстурирования. (Заметьте, что этот выбор осуществляется после выполнения операций передачи пикселей.) Вспомните, что при создании ваших текстурных карт командой glTexImage*D(), вы передаете спецификатор внутреннего формата в третьем аргументе.

В таблицах 9-4 и 9-5 перечислены формулы текстурирования, используемые для каждого компонента текстуры. Существует 6 базовых внутренних форматов (буквы в скобках показывают, как они обозначены в таблице): GL_ALPHA (A), GL_LUMINANCE (L), GL_LUMINANCE_ALPHA (L и A), GL_INTENSITY (I), GL_RGB (C) и GL_RGBA (C и A).

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

Замечание: В таблице 9-4 нижний индекс t означает величину текстуры, f – величину входящего фрагмента, c – величину, присвоенную переменной состояния GL_TEXTURE_ENV_COLOR, а отсутствие нижнего индекса – означает финальную вычисленную величину. Также в этих таблицах умножение цветовой тройки на скаляр означает умножение каждого из трех компонент R, G и B на этот скаляр; умножение (или суммирование) двух цветовых троек означает попарное умножение (или суммирование) соответствующих компонентов из каждой тройки.

Таблица 9-4. Текстурные функции GL_REPLACE и GL_MODULATE

Базовый

Функция

Функция

Функция GL_DECAL

Функция GL_BLEND

внутренний

GL_REPLA

GL_MODULA

 

 

 

 

 

 

 

Соседние файлы в предмете Компьютерная Графика