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

RedBook

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

9.2 Создание текстуры

Команда glTexImage2D() определяет двумерную текстуру. Она принимает несколько аргументов, которые кратко описаны здесь и более подробно в последующих разделах. Аналогичные команды для одномерных и трехмерных текстур glTexImage1D() и glTexImage3D() описаны в соответствующих разделах.

void glTexImage2D (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height,

GLint border, GLenum format, GLenum type, const GLvoid

*texels);

Определяет двумерную текстуру. Аргумент target должен быть установлен в

GL_TEXTURE_2D или GL_PROXY_TEXTURE_2D. Параметр level используется в том случае, если вы создаете несколько разрешений текстурной карты, в случае одного разрешения, level должен быть равен 0. Следующий аргумент internalFormat определяет, какие величины – R, G, B, A, светлота или интенсивность выбраны для использования в описании тэкселей изображения. Значение для internalFormatэто число от 1 до 4 или одна из 38 символических констант. Далее приводится список 38

допустимых констант: GL_ALPHA, GL_ALPHA4, GL_ALPHA8, GL_ALPHA12, GL_ALPHA16, GL_LUMINANCE, GL_LUMINANCE4, GL_LUMINANCE8, GL_LUMINANCE12, GL_LUMINANCE16, GL_LUMINANCE_ALPHA, GL_LUMINANCE4_ALPHA4, GL_LUMINANCE6_ALPHA2, GL_LUMINANCE8_ALPHA8, GL_LUMINANCE12_ALPHA4, GL_LUMINANCE12_ALPHA12, GL_LUMINANCE16_ALPHA16, GL_INTENSITY, GL_INTENSITY4, GL_INTENSITY8, GL_INTENSITY12, GL_INTENSITY16, GL_RGB, GL_R3_G3_B2, GL_RGB4, GL_RGB5, GL_RGB8, GL_RGB10, GL_RGB12, GL_RGB16, GL_RGBA, GL_RGBA2, GL_RGBA4, GL_RGB5_A1, GL_RGBA8, GL_RGB10_A2, GL_RGBA12, GL_RGBA16. Если значение internalFormat равно одной из 38 символических констант, это значит, что вы запрашиваете конкретные компоненты и, возможно, разрешение этих компонент. Например, если internalFormat равен GL_R3_G3_B2, вы требуете, чтобы в каждом тэкселе было 3 бита на красный компонент, 3 бита на зеленый и 2 бита на синий, однако OpenGL не гарантирует, что все будет именно так. Вместо этого, OpenGL попытается выбрать внутреннее представление данных, которое наиболее точно подходит к тому, что вы запросили. Точное совпадение обычно не требуется.

Внутренние форматы GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGBи GL_RGBA по определению являются обобщенными, поскольку в них отсутствует запрос на конкретное разрешение. (Из-за требований совместимости с OpenGLверсии 1.0 числовые величины для internalFormat– 1, 2, 3 и 4 – являются эквивалентами символических констант GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB и GL_RGBA

соответственно.) Аргументы width и height задают размеры изображения текстуры; border задает толщину границы и должно быть равно либо 0 (граница отсутствует),

либо 1. И width, и height должны иметь форму , где m – неотрицательное целое (которое может иметь разное значение для width и height), а bравно аргументу border. Максимальный размер текстуры зависит от реализации OpenGL, но он должен быть как минимум 64x64 (то есть 66x66 вместе с границами). Аргументы format и type описывают формат и тип данных изображения текстуры. Они имеют то же значение, что и для команды glDrawPixels(). Вообще говоря, данные текстуры имеют тот же формат, что и данные, используемые glDrawPixels(), таким образом, имеют значение установки команд glPixelStore*() и glPixelTransfer*(). (В примере 9-1 вызов

glPixelsStorei(GL_UNPACK_ALIGNMENT,1);

производится потому, что данные не выравниваются специальным образом в конце каждого ряда тэкселей.) Аргумент format может принимать значения GL_COLOR_INDEX, GL_RGB, GL_RGBA, GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA– то есть форматы могут быть такими же, как и у команды glDrawPixels() за исключением GL_STENCIL_INDEX и GLL_DEPTH_COMPONENT.

Похожим образом аргумент type может принимать значения GL_BYTE,

GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT, GL_FLOAT, GL_BITMAP или одно из значений, означающих упакованный тип данных. Наконец, аргумент texels является указателем на данные изображения текстуры. Эти данные описывают само изображение и его границы.

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

Внутренний формат изображения текстуры также определяет то, сколько памяти поглощается этим изображением. Например, текстура с внутренним форматом GL_RGB8 использует 32 бита на тэксель, а текстура с внутренним форматом GL_R3_G3_B2 использует только 8 бит на тэксель. Конечно, существует определенное противоречие между объемом поглощаемой памяти и цветовым разрешением.

Несмотря на то, что результат текстурирования в индексном режиме не определен, вы все-таки можете создать текстуру из изображения в формате GL_COLOR_INDEX. В этом

случае до создания текстуры применяются операции пиксельного переноса для табличной конверсии индексов в RGBA величины.

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

Число тэкселей в каждом ряду и каждом столбце изображения текстуры без опциональной границы должно быть степенью 2. Если ваше исходное изображение не соответствует этому ограничению, вы можете использовать функцию gluScaleImage() из библиотеки утилит GLU, чтобы изменить размер ваших текстур.

int gluScaleImage (GLenum format, GLint widthin, GLint heightin, GLenum typein, const *datain,

GLint widthout, GLint heightout, GLenum typeout, void

*dataout);

Масштабирует изображения, используя установленный режим хранения пикселей для распаковки данных из datain. Аргументы format, typein и typeout могут иметь любые значения форматов и типов данных, поддерживаемые командой glDrawPixels(). Масштабирование от размеров widthin x heightin до размеров widthout x heightout производится с использованием линейной интерполяции. Результирующее изображение записывается в dataoutс использованием текущих режимов хранения пикселей GL_PACK*. Ответственность за выделение достаточного количества памяти для хранения результирующего изображения лежит на программисте. В случае успеха функция возвращает 0, в случае неудачи код ошибки GLU.

Замечание: В GLU версии 1.3 gluScaleImage() поддерживает упакованные пиксельные форматы (и связанные с ними типы данных), появившиеся в OpenGL 1.2.

Буфер кадра также может быть использован в качестве источника данных для текстуры. Команда glCopyTexImage2D() считывает прямоугольник пикселей из буфера кадра и использует его в качестве тэкселей новой текстуры.

void glCopyTexImage2D (GLenum target, GLint level, GLint internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);

Создает двумерную текстуру, используя в качестве тэкселей данные из буфера кадра. Пиксели считываются из текущего буфера для чтения (GL_READ_BUFFER) и обрабатываются точно так же, как в случае вызова glCopyPixels(), однако вместо перемещения в буфер кадра, пиксели помещаются в текстурную память. Во время

обработки применяются установки команды glPixelTransfer*() и другие операции переноса пикселей. Аргумент target должен быть установлен в значение GL_TEXTURE_2D. Аргументы level, internalFormat и border имеют тот же эффект, что и для команды glTexImage2D(). Текстурный массив извлекается из экранного прямоугольника пикселей с нижним левым углом в точке (x, y). Аргументы width и height задают размеры этого прямоугольника. И width, и height должны иметь форму

, где m – неотрицательное целое (которое может иметь разное значение для widthи height), а b равно аргументу border.

В следующих разделах детали текстурирования, в том числе использование параметров target, border и level, излагаются более подробно. Параметр target может использоваться для запроса точного размера текстуры (для этого нужно создать текстурное прокси командой glTexImage*D()), а также для выяснения того, может ли конкретная текстура использоваться с учетом объема ресурсов реализации OpenGL. Существует возможность переопределения части текстуры. Детализируется использование границы текстуры. Параметр level может использоваться для создания текстур с различным разрешением, он также связан с техникой мипмаппинга, который в свою очередь требует понимания фильтрации текстур.

9.2.1 Текстурное прокси

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

Команда glGetIntegerv(GL_MAX_TEXTURE_SIZE, ...); выдаст вам нижнюю границу (ширину или высоту) максимально большой текстуры (без учета границы текстуры). Обычно наибольшая текстура бывает квадратной. Константа GL_MAX_3D_TEXTURE_SIZE может быть использована для получения максимально допустимого измерения 3D текстуры (ширины, высоты или глубины, без учета границ).

Однако ни GL_MAX_TEXTURE_SIZE, ни GL_MAX_3D_TEXTURE_SIZE не заботится о внутреннем формате изображения или таких аспектах, как мипмаппинг. Изображение текстуры, сохраненное в формате GL_RGB16 занимает 64 бита памяти под каждый тэксель, тогда как в формате GL_LUMINANCE4 оно занимало бы в 16 раз меньше. (Кроме того, изображения, для которых требуется граница или мипмапы, могут еще быстрее сокращать объем доступной памяти.)

Специальный механизм прокси изображения текстуры позволяет программе более точно выяснить может ли OpenGL принять текстуру желаемого внутреннего формата.

Для использования текстурного прокси вы должны вызвать команду glTexImage2D() с аргументом target, установленным в значение GL_PROXY_TEXTURE_2D и желаемыми аргументами level, internalFormat, width, height, border, format и type. (Для одномерных и трехмерных текстур используйте соответствующие 1D и 2D команды и константы.) При работе с прокси в качестве аргумента texelsвы должны передать NULL.

Чтобы выяснить, достаточно ли свободных ресурсов присутствует в системе для вашей текстуры, после создания прокси опросите переменные состояния текстуры с помощью команды glGetTexLevelParameter*(). Если ресурсов недостаточно, такие параметры как ширина и высота текстуры, ширина ее границы и разрешение ее компонентов будут равны 0.

void glGetTexLevelParameter{if}v (GLenum target, GLint level, GLenum pname, TYPE *params);

В аргументе params команда возвращает значения параметров текстуры для заданного с помощью аргумента level уровня детализации. Аргумент target задает целевую текстуру и может быть равен GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D, GL_PROXY_TEXTURE_3D.

Допустимыми значениями для аргумента pname являются: GL_TEXTURE_WIDTH, GL_TEXTURE_HEIGHT, GL_TEXTURE_DEPTH, GL_TEXTURE_BORDER, GL_TEXTURE_INTERNAL_FORMAT, GL_TEXTURE_RED_SIZE, GL_TEXTURE_GREEN_SIZE, GL_TEXTURE_BLUE_SIZE, GL_TEXTURE_ALPHA_SIZE, GL_TEXTURE_LUMANANCE_SIZE, GL_TEXTURE_INTENSITY_SIZE. Для аргумента pname также доступно значение GL_TEXTURE_COMPONENTS, но только из-за необходимости совместимости с версией OpenGL 1.0. Для последующих версий рекомендуется использовать константу

GL_TEXTURE_INTERNAL_FORMAT.

Пример 9-2 демонстрирует технику использования текстурного прокси для того, чтобы выяснить достаточно ли в системе ресурсов под создание текстуры размером 64 x 64 тэкселя в формате RGBA с 8 битами на компонент. Если ресурсов достаточно, glGetTexLevelParameteriv() сохраняет внутренний формат (в данном случае GL_RGBA8) в переменной format.

Пример 9-2. Опрос текстурных ресурсов с помощью текстурного прокси

GLint width;

glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA8, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);

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

9.2.2 Замена всего изображения текстуры или его части

Создание новой текстуры с точки зрения вычислений может быть значительно дороже, чем модификация существующей. Начиная с OpenGL версии 1.1, были введены

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

текстуру и затем использовать команду glTexSubImage2D() для многократной замены данных текстуры новыми видеоизображениями. Кроме того, для команды glTexSubImage2D() нет ограничений на ширину или высоту они не обязаны быть степенью 2. (Обычно это полезно для обработки видеоизображений, размеры которых обычно не являются степенью 2. Однако вы должны загружать изображения в первоначальную большую текстуру, размеры которой и по ширине, и по высоте должны

быть , а также вам нужно настраивать координаты текстуры под новое изображение.)

void glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,

GLenum format, GLenum type, const GLvoid *texels);

Задает двумерное текстурное изображение, которое заменяет непрерывный подрегион (в 2D это просто прямоугольник) текущего существующего текстурного изображения. Аргумент target должен быть установлен в значение GL_TEXTURE_2D. Аргументы level, format и type имеют тот же смысл, что и аналогичные аргументы команды glTexImage2D(). levelэто номер уровня детализации. Указание параметров width и height установленных в 0 не является ошибкой, но в этом случае команда не имеет эффекта. format и type описывают формат и тип данных в изображении текстуры. на новое изображение также влияют установки команд glPixelStore*(), glPixelTransfer*() и другие операции передачи пикселей. texels содержит данные для подтекстуры. width и height являются размерами подрегиона, который заменяет все или часть текущего изображения текстуры. xoffset и yoffset задают смещение от левого нижнего угла текстуры в пикселях по x и y осям соответственно, то есть они задают, где в исходном изображении должны быть помещены новые данные. Подрегион не может включать тэксели вне оригинального изображения текстуры.

Пример 9-3 представляет собой модификацию примера 9-1. Нажатие на клавишу ‘s’ заменяет часть изображения текстуры новым изображением. (Результирующее изображение приведено на рисунке 9-3.) Нажатие на клавишу ‘r’ восстанавливает исходное изображение. В примере 9-3 были добавлены функции makeCheckImages()

и keyboard()).

Рисунок 9-3. Текстура с частично измененным изображением

Пример 9-3. Замещение части текстуры: файл texsub.cpp

//Параметры текстуры шахматной доски

#define checkImageWidth 64 #define checkImageHeight 64 #define subImageWidth 16 #define subImageHeight 16

GLubyte checkImage[checkImageHeight][checkImageWidth][4]; GLubyte subImage[subImageHeight][subImageWidth][4];

void makeCheckImages()

{

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)c;

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

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

}

}

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

{

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

{

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

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

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

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

subImage[i][j][3]=(GLubyte)255;

}

}

}

void keyboard(unsigned char key, int x, int y)

{

switch (key)

{

case 's': case 'S':

glBindTexture(GL_TEXTURE_2D,texName); glTexSubImage2D(GL_TEXTURE_2D,0,12,44,subImageWidth,subImageHeight,GL_RGBA,GL _UNSIGNED_BYTE,subImage);

glutPostRedisplay();

break; case 'r': case 'R':

glBindTexture(GL_TEXTURE_2D,texName); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,checkImageWidth,checkImageHeight,0,GL_RG BA,GL_UNSIGNED_BYTE,checkImage);

glutPostRedisplay();

break;

}

}

Буфер кадра также может использоваться в качестве источника текстурных данных на этот раз в качестве источника данных для подтекстуры. Команда glCopyTexSubImage2D() считывает прямоугольник пикселей из буфера кадра и замещает ими часть массива существующей текстуры. (glCopyTexSubImage2D() это что-то среднее между glCopyTexImage2D()и glTexSubImage2D().)

void glCopyTexSubImage2D (GLenum target, GLint level, GLine xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);

Использует данные изображения из буфера кадра для замещения целого или части непрерывного подрегиона текущей существующей двумерной текстуры. Пиксели считываются из текущего буфера для чтения (GL_READ_BUFFER) и обрабатываются так же как в случае glCopyPixels(), но вместо переноса в буфер кадра, пиксели помещаются в текстурную память. На переносимые пиксели влияют установки команд glPixelStore*(), glPixelTransfer*() и другие операции передачи пикселей. Аргумент target должен быть установлен в значение GL_TEXTURE_2D. level представляет собой уровень детализации мипмапа. xoffset и yoffset задают смещение от левого нижнего угла текстуры в пикселях по осям абсцисс и ординат соответственно, то есть они задают, где в исходном изображении должны быть помещены новые данные.

Подизображение извлекается из экранного прямоугольника пикселей с левым нижним углом в точке (x, y). Аргументы width и height задают размер этого прямоугольника.

9.2.3 Одномерные текстуры

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

void glTexImage1D (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLint border,

GLenum format, GLenum type, const GLvoid *texels);

Создает одномерную текстуру. Все параметры имеют то же назначение, что и аналогичные параметры glTexImage2D() за тем исключением, что аргумент texels в данном случае является одномерным массивом. Как и раньше значение width должно

быть равно (или , если присутствует граница), где m – неотрицательное целое. Вы можете использовать мипмаппинг и текстурное прокси (для этого нужно вызвать команду с аргументом target, установленным в GL_PROXY_TEXTURE_1D), также присутствуют аналогичные варианты фильтрации.

В качестве примера программы, использующей одномерную текстуру, обратитесь к примеру 9-8.

Если ваша реализация OpenGL поддерживает подмножество обработки изображений и активизирована одномерная фильтрация (GL_CONVOLUTION_1D), то изображение фильтруется. (Фильтрация может изменить ширину изображения текстуры.) Также могут применяться и другие пиксельные операции.

Чтобы заменить все или часть тэкселей одномерной текстуры, используйте команду glTexSubImage1D().

void glTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *texels);

Создает одномерный текстурный массив, который заменяет весь или часть региона (то есть в 1D – ряда) текущего существующего изображения одномерной текстуры. Аргумент target должен быть установлен в значение GL_TEXTURE_1D. Аргументы level, format и type имеют то же значение, что и для команды glTexImage1D(). level это уровень детализации мипмапа. format и type описывают формат и тип данных изображения текстуры. Частичное изображение подвержено влиянию режимов, установленных командами glPixelsStore*(), glPixelsTransfer*() и другим операциям пиксельного переноса. Аргумент texels содержит данные изображения частичной текстуры. width это количество тэкселей, которые заменяют все изображение текущей текстуры или его часть. xoffset задает смещение в тэкселях от начала массива существующей текстуры, индицируя то место, с которого будут начинаться новые данные.

Для использования буфера кадра в качестве источника данных для новой одномерной текстуры или частичного изображения одномерной текстуры, которое заместит существующее, используйте команды glCopyTexImage1D() или glCopyTexSubImage1D() соответственно.

void glCopyTexImage1D (GLenum target, GLint level, GLint internalFormat, GLint x, GLint y, GLsizei width, GLint border);

Создает одномерную текстуру, используя данные из буфера кадра в качестве тэкселей. Пиксели считываются из текущего буфера для чтения (GL_READ_BUFFER) и обрабатываются точно так же, как в случае вызова glCopyPixels(), однако вместо перемещения в буфер кадра, пиксели помещаются в текстурную память. Во время

обработки применяются установки команды glPixelTransfer*() и другие операции переноса пикселей. Аргумент target должен быть установлен в значение GL_TEXTURE_1D. Аргументы level, internalFormat и border имеют тот же эффект, что и для команды glCopyTexImage2D(). Текстурный массив извлекается из экранного ряда

пикселей с нижним левым углом в точке (x, y). Значение width должно быть равно (или , если присутствует граница), где m – неотрицательное целое.

void glCopyTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width, GLint border);

Использует данные изображения из буфера кадра для замещения целого или части непрерывного подрегиона текущей существующей одномерной текстуры. Пиксели считываются из текущего буфера для чтения (GL_READ_BUFFER) и обрабатываются так же как в случае glCopyPixels(), но вместо переноса в буфер кадра, пиксели помещаются в текстурную память. На переносимые пиксели влияют установки команд glPixelStore*(), glPixelTransfer*() и другие операции передачи пикселей. Аргумент target должен быть установлен в значение GL_TEXTURE_1D. level представляет собой уровень детализации мипмапа. xoffset задает смещение внутри массива существующей текстуры, то есть оно задает, где в исходном изображении должны быть помещены новые данные. Подизображение извлекается из экранного ряда пикселей с левым нижним углом в точке (x, y). Аргумент width задает число пикселей в этом ряду.

9.2.4Трехмерные текстуры

Трехмерные текстуры чаще всего используются в медицинских и геологических приложениях. В медицинских приложениях трехмерная текстура может представлять многослойную компьютерную томографию или визуализацию магнитного резонанса. Для исследователей, связанных с нефтью и газом, трехмерная текстура может применяться для моделирования слоев камня. (Трехмерные текстуры являются неотъемлемой частью определенного класса приложений, связанных с визуализацией объема – volume rendering applications. Наиболее продвинутые из этих приложений работают с вокселями voxels, которые представляют данные в виде сущностей, зависимых от объема.)

Из-за своего размера трехмерные текстуры могут поглощать большой объем текстурных ресурсов системы. Даже самая простая трехмерная текстура может занимать в 16 или даже 32 раза больше памяти, чем одна двумерная.

До версии 1.2 трехмерные текстуры были довольно распространенным расширением от нескольких производителей реализаций OpenGL. В версии 1.2 поддержка трехмерных текстур была включена в ядро OpenGL. Большинство команд для работы с двумерными текстурами и подтекстурами имеют свои аналоги для трехмерного варианта.

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

void glTexImage3D (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height,

GLsizei depth, GLint border, GLenum format, GLenum type, const

GLvoid *texels);

Создает трехмерную текстуру. Все параметры имеют то же значение, что и для команды glTexImage2D(), за исключением того, что здесь texels представляет собой трехмерный массив. Кроме того, добавился параметр depth. Величина depth должна

иметь форму (или , если присутствует граница), где m – неотрицательное целое. Вы можете использовать мипмаппинг и текстурное прокси (для этого нужно вызвать команду с аргументом target, установленным в GL_PROXY_TEXTURE_3D), также присутствуют аналогичные варианты фильтрации.

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

Пример 9-4 является частью программы, использующей трехмерные текстуры.

Пример 9-4. Трехмерное текстурирование: файл texture3d.cpp

#define iwidth 16 #define iheight 16 #define idepth 16

GLubyte image [idepth][iheight][iwidth][3];

GLuint texName;

//Функция создает массив размерности 16x16x16x3, с различными цветовыми

//величинами [r, g, b] в каждом элементе. Значения величин лежат в диапазоне

//от 0 до 255

void makeImage(void)

{

int s, t, r;

for(s=0;s<16;s++)

for(t=0;t<16;t++)

for(r=0;r<16;r++)

{

image[r][t][s][0]=s*17;

image[r][t][s][1]=t*17;

image[r][t][s][2]=r*17;

}

}

//Инициализировать состояние: объект 3D текстуры и ее изображение void init(void)

{

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

makeImage(); glPixelStorei(GL_UNPACK_ALIGNMENT,1);

glGenTextures(1, &texName); glBindTexture(GL_TEXTURE_3D,texName);

glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP);

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

glTexImage3D(GL_TEXTURE_3D,0,GL_RGB,iWidth,iHeight,iDepth, 0,GL_RGB,GL_UNSIGNED_BYTE,image);

}

Чтобы заменить все или часть тэкселей трехмерной текстуры, используйте команду glTexSubImage3D().

void glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,

GLsizei width, GLsizei height, GLsizei depth, GLenum

format,

GLenum type, const GLvoid *texels);

Создает трехмерный текстурный массив, который заменяет весь или часть подрегиона текущего существующего изображения трехмерной текстуры. Аргумент target должен быть установлен в значение GL_TEXTURE_3D. Аргументы level, format и type имеют то же значение, что и для команды glTexImage3D(). levelэто уровень детализации мипмапа. format и type описывают формат и тип данных изображения текстуры. Частичное изображение подвержено влиянию режимов, установленных командами glPixelsStore*(), glPixelsTransfer*() и другим операциям пиксельного переноса.

Аргумент texels содержит данные изображения частичной текстуры. width, height и depth представляют собой размеры подизображения в тэкселях. xoffset, yoffset и zoffset задают смещение в тэкселях от начала массива существующей текстуры, индицируя то место, индицируя то место, куда нужно поместить новые данные.

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

void glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,

GLint x, GLint y, GLsizei width, GLint border);

Использует данные изображения из буфера кадра для замещения целого или части непрерывного подрегиона текущей существующей трехмерной текстуры. Пиксели считываются из текущего буфера для чтения (GL_READ_BUFFER) и обрабатываются так же как в случае glCopyPixels(), но вместо переноса в буфер кадра, пиксели помещаются в текстурную память. На переносимые пиксели влияют установки команд glPixelStore*(), glPixelTransfer*() и другие операции передачи пикселей. Аргумент target должен быть установлен в значение GL_TEXTURE_3D. level представляет собой уровень детализации мипмапа. Подизображение извлекается из экранного прямоугольника пикселей с левым нижним углом в точке (x, y). Аргументы width и height задают размеры этого прямоугольника. xoffset, yoffset и zoffset задают смещение внутри массива существующей текстуры, то есть они определяют место, куда следует поместить извлеченные данные. Поскольку подизображение является двумерным, оно может заместить только часть или целое изображение в одном срезе (срезе со смещением zoffset).

9.2.4.1Режимы хранения пикселей для трехмерных текстур

Режимы хранения пикселей контролируют пропуски между рядами каждого слоя (иными словами, одного двумерного прямоугольника). Команда glPixelStore*() устанавливает режимы хранения пикселей с такими параметрами, как *ROW_LENGTH, *ALIGNMENT, *SKIP_PIXELS и *SKIP_ROWS (где * означает или GL_PACK или

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

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