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

RedBook

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

Рисует прямоугольник пиксельных данных размерами width и height. Пиксельный прямоугольник рисуется таким образом, что его левый нижний угол находится в текущей позиции растра. Аргументы format и type имеют то же значение, что и для команды glReadPixels(). (Смотрите таблицы 8-1 и 8-2.) Массив, на который указывает pixels, должен содержать пиксельные данные для рисования. Если текущая позиция растра недопустима, ничего не рисуется, а позиция растра остается недопустимой.

Пример 8-3это часть программы, которая использует glDrawPixels() для рисования прямоугольника пикселей в левом нижнем углу окна. Функция makeCheckImage() создает RGB массив 64x64, содержащий изображение шахматной доски. Команда glRasterPos2i(0,0) позиционирует левый нижний угол изображения. Пока игнорируйте вызов glPixelStorei().

Пример 8-3. Использование glDrawPixels(): файл image.cpp

#define checkImageWidth 64 #define checkImageHeight 64

GLubyte checkImage[checkImageHeight][checkImageWidth][3];

void makeCheckImage()

{

int i,j,c;

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

{

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

{

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

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

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

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

}

}

}

void init(void)

{

glClearColor(0.0,0.0,0.0,0.0); glShadeModel(GL_FLAT); makeCheckImage(); glPixelStorei(GL_UNPACK_ALIGNMENT,1);

}

void display(void)

{

glClear(GL_COLOR_BUFFER_BIT); glRasterPos2i(0,0);

glDrawPixels(checkImageWidth,checkImageHeight,GL_RGB,GL_UNSIGNED_BYTE,checkImage); glFlush();

}

При использовании glDrawPixels() для записи RGBA или цвето-индексной информации, вам может потребоваться управлять тем, какой буфер используется для рисования с помощью команды glDrawBuffer().

8.2.1.3Копирование пиксельных данных внутри буфера кадра

void glCopyPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum buffer);

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

копируются в новую позицию, чей левый нижний угол задается текущей позицией растра. Аргумент buffer может принимать значения GL_COLOR, GL_STENCIL или GL_DEPTH, задавая используемый буфер кадра. glCopyPixels() ведет себя так же как

пара смежных вызовов glReadPixels() и glDrawPixels() со следующим отображением параметра buffer на значение параметра format:

Если buffer равен GL_DEPTH или GL_STENCIL, то format равен

GL_DEPTH_COMPONENT или GL_STENCIL_INDEX, соответственно.

Если задан GL_COLOR, используется GL_RGBA или GL_COLOR_INDEX в

зависимости от того, работает ли система в RGBA или индексном режиме.

Заметьте, что для команды glCopyPixels() нет нужды в параметрах format или type, поскольку данные не копируются в процессорную память. Буфер источник и буфер

приемник для команды glCopyPixels() задаются командами glReadBuffer() и glDrawBuffer() соответственно.

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

8.2.2 Конвейер обработки изображений

В этом разделе обсуждается конвейер обработки изображений: режимы хранения пикселей и операции по передаче пикселей, которые включают конверсию пиксельных данных. Вы также можете увеличивать или уменьшать пиксельный прямоугольник до его рисования, применяя команду glPixelZoom(). Порядок операций показан на рисунке 8-6.

Рисунок 8-6. Конвейер обработки изображений

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

Когда вызывается команда glReadPixels(), данные считываются из буфера кадра, над ними производятся операции пиксельного переноса, и результирующие данные упаковываются в процессорную память.

glCopyPixels() производит все операции пиксельного переноса так же, как это делает glReadPixels(). Затем получившиеся данные записываются так же как в случае glDrawPixels(), но преобразования второй раз не производятся.

На рисунке 8-7 изображен процесс перемещения данных командой glCopyPixels() (процесс начинается с буфера кадра).

Рисунок 8-7. Путь пикселей при вызове команды glCopyPixels()

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

Рисунок 8-8. Путь пикселей при вызове команды glBitmap()

Обратите внимание, режимы хранения пикселей и операции пиксельного переноса также применяются к текстурам, во время того, как они считываются из текстурной памяти или записываются в текстурную память. Рисунок 8-9 демонстрирует эффект от команд glTexImage*(), glTexSubImage*() и glGenTexImage*().

Рисунок 8-9. Путь пикселей при вызове команд glTexImage*(), glTexSubImage*() и glGenTexImage*()

Как показано на рисунке 8-10, когда данные из буфера кадра копируются в текстурную память (командами glCopyTexImage*() или glCopyTexSubImage()), производятся только операции пиксельного переноса.

Рисунок 8-10. Путь пикселей при вызове команд glCopyTexImage*() и glCopyTexSubImage*()

8.2.2.1Упаковка и распаковка пикселей

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

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

Некоторые элементы (такие как цветовой индекс или индекс трафарета) являются целыми, а другие (такие как красный, зеленый, синий и альфа компоненты) – числами с плавающей точкой, обычно варьируясь между 0.0 и 1.0. Дробные компоненты обычно сохраняются в буфере кадра с меньшим разрешением, чем требуется для сохранения полного числа с плавающей точкой (цветовые компоненты, например, могут храниться в 8-ми битах). Точное число битов, используемых для представления компонентов, зависит от конкретной используемой аппаратуры. Таким образом, часто бессмысленно хранить компоненты в виде 32-разрядных чисел с плавающей точкой, тем более, что изображение может состоять из миллионов пикселей.

Элементы могут храниться в памяти в виде различных типов данных от 8-разрядных байтов до 32-разрядных целых чисел или чисел с плавающей точкой. OpenGL

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

8.2.2.2Управление режимами хранения пикселей

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

вданном абзаце, решаются путем использования режимов хранения пикселей. Вы задаете эти режимы, используя команду glPixelStore*(), которая уже использовалась

внескольких примерах.

Все режимы хранения пикселей, поддерживаемые OpenGL, управляются glPixelStore*(). Обычно производится несколько последовательных вызовов данной команды для установки значений различных параметров.

void glPixelStore{if} (GLenum pname, TYPE param);

Устанавливает режимы хранения пикселей, которые влияют на работу команд glDrawPixels()), glReadPixels(), glBitmap(), glPolygonStipple(), glTexImage1D(), glTexImage2D(), glTexImage3D(), glTexSubImage1D(), glTexSubImage2D(), glTexSubImage3D(), glGetTexImage(), а также, если присутствует подмножество команд обработки изображений glGetColorTable(), glGetConvolutionFilter(), glGetSeparableFilter(), glGetHistogram(), glGetMinmax(). Возможные имена параметров для pname перечислены в таблице 8-4. Параметры GL_UNPACK_* управляют тем, как данные распаковываются из памяти командами glDrawPixels(), glBitmap(), glPolygonStipple(), glTexImage1D(), glTexImage2D(), glTexImage3D(), glTexSubImage1D(), glTexSubImage2D() и glTexSubImage3D(). Параметры GL_PACK_* управляют тем, как данные упаковываются в память командами glReadPixels(), glGenTexImage(), а также, если присутствует подмножество команд обработки изображений glGetColorTable(), glGetConvolutionFilter(), glGetSeparableFilter(), glGetHistogram(), glGetMinmax(). Параметры GL_UNPACK_IMAGE_HEIGHT, GL_PACK_IMAGE_HEIGHT, GL_UNPACK_SKIP_IMAGES, GL_PACK_SKIP_IMAGES влияют только на 3D

текстурирование (glTexImage3D(), glTexSubImage3D(), glGenTexImage(GL_TEXTURE_3D,...)).

Таблица 8-4. Параметры glPixelStore()

Имя параметра

Тип

Начальное

Допустимые величины

значение

 

 

 

GL_UNPACK_SWAP_BYTES,

GLboolean

FALSE

TRUE / FALSE

GL_PACK_SWAP_BYTES

 

 

 

GL_UNPACK_LSB_FIRST, GL_PACK_ LSB_FIRST

GLboolean

FALSE

TRUE / FALSE

GL_UNPACK_ROW_LENGTH,

GLint

0

любое неотрицательное

GL_PACK_ROW_LENGTH

целое

 

 

GL_UNPACK_SKIP_ROWS,

GLint

0

любое неотрицательное

GL_PACK_SKIP_ROWS

целое

 

 

GL_UNPACK_SKIP_PIXELS,

GLint

0

любое неотрицательное

GL_PACK_SKIP_PIXELS

целое

 

 

GL_UNPACK_ALIGNMENT, GL_PACK_ALIGNMENT

GLint

4

1, 2, 4, 8

GL_UNPACK_IMAGE_HEIGHT,

GLint

0

любое неотрицательное

GL_PACK_IMAGE_HEIGHT

целое

 

 

GL_UNPACK_SKIP_IMAGES,

GLint

0

любое неотрицательное

GL_PACK_SKIP_IMAGES

целое

 

 

 

 

 

 

Поскольку соответствующие параметры для упаковки и распаковки имеют одинаковый смысл, они обсуждаются вместе в оставшейся части этого раздела и ссылки на них производятся без префикса GL_PACK или GL_UNPACK. Например, *SWAP_BYTES

относится и к GL_UNPACK_SWAP_BYTES, и к GL_PACK_SWAP_BYTES.

Если параметр *SWAP_BYTES равен FALSE (значение по умолчанию), то порядок байтов в памяти такой же, как естественный порядок байтов для клиента OpenGL; если параметр равен TRUE– байты расположены в обратном порядке. Реверс байтов применяется для элементов любого размера, но имеет смысл только для элементов, состоящих из нескольких байт.

Эффект от реверса байтов может различаться в разных реализациях OpenGL. Рисунок 8-10 иллюстрирует эффект от байтового реверса для различных типов данных для реализации, в которой GLubyte состоит из 8 бит, GLushort – из 16, а GLuint – из 32. Заметьте, что обратный порядок байт не сказывается на однобайтовых данных.

Рисунок 8-11. Обратный порядок байт для данных типа Byte, Short и Integer

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

Параметр *LSB_FIRST имеет значение только при рисовании или считывании однобитовых изображений или битовых карт, для которых на каждый пиксель сохраняется или восстанавливается по одному биту данных. Если *LSB_FIRST равен FALSE (значение по умолчанию) биты берутся из байтов начиная со старшего, иначе они забираются в обратном порядке. Например, если *LSB_FIRSTравен FALSE, а интересующий нас байт – 0x31, битами по порядку будут {0, 0, 1, 1, 0, 0, 0, 1}. Если же *LSB_FIRST равен TRUE – порядок будет следующим {1, 0, 0, 0, 1, 1, 0, 0}.

Иногда вам нужно нарисовать или считать только часть прямоугольника данных изображения (также прямоугольную), сохраненного в памяти. Если прямоугольник в памяти больше, чем прямоугольник, который нужно нарисовать или считать, вам нужно задать реальную длину (в пикселях) большего прямоугольник с помощью *ROW_LENGTH. Если *ROW_LENGTH равен 0 (значение по умолчанию) длина ряда принимается такой же, как и ширина, задаваемая в командах glReadPixels(), glDrawPixels() или glCopyPixels(). Вам также нужно задать количество рядов и пикселей, которые нужно пропустить до начала копирования данных для меньшего прямоугольника. Эти числа задаются при помощи параметров *SKIP_ROWS и *SKIP_PIXELS, как показано на рисунке 8-12. По умолчанию оба параметра равны 0, так что копирование начинается с нижнего левого угла.

Рисунок 8-12. Параметры *SKIP_ROWS, *SKIP_PIXELS и *ROW_LENGTH

Часто аппаратура оптимизирована для перемещения пиксельных данных в память и из памяти, если данные сохранены в памяти с определенным выравниваем. Например, в машине с 32-х разрядными словами, аппаратура часто намного быстрее извлекает данные, если они изначально выровнены по границе 32-разрядов, что обычно означает адрес кратный 4. Похожим образом, 64-битовые архитектуры могут работать лучше, когда данные выровнены по границам в 8 байт.

Для примера, предположим, что ваша машина лучше работает, когда пиксельные данные выровнены по 4-ех байтовым границам. Изображения могут быть сохранены более эффективно, если сделать так, чтобы данные для каждого ряда изображения начинались на 4-ех байтовой границе. Если изображение имеет ширину в 5 пикселей, и каждый пиксель состоит из 1 байта на красный, 1 на зеленый и 1 на синий компоненты, для одного ряда требуется 5x3=15 байт данных. Максимальная эффективность может быть достигнута, если первый и последующие ряды будут начинаться с 4-ех байтовой границы, то есть на каждый ряд будет тратиться 1 дополнительный байт памяти. Если ваши данные сохранены подобным образом, верно установите значение параметра *ALIGNMENT (в данном случае в значение 4).

Если *ALIGNMENT равен 1, используется следующий доступный байт. Если он равен 2, в конце каждого ряда если это необходимо будет пропущен дополнительный байт, чтобы первый байт следующего ряда начинался с адреса кратного 2-ум. В случае битовых карт (или 1-битовый изображений), где для каждого пикселя хранится один бит, байтовое смещение также работает, но вам нужно подсчитывать отдельные биты. Например, если вы сохраняете по одному биту на пиксель, длина ряда составляет 75 пикселей, а выравнивание равно 4, то каждый ряд потребует 75/8 или 9 3/8 байт. Поскольку число 12 – это наименьшее число кратное 4 большее 9 3/8, для каждого ряда будет использоваться 12 байт памяти. Если выравнивание равно 1, то будет использовано 10 байт, то есть 9 3/8 округленное до целого числа байт.

Замечание: Значением по умолчанию для *ALIGNMENT является 4. Предположение о том, что данные изображения плотно упакованы в памяти (то есть *ALIGNMENT равно 1) является частой ошибкой.

Параметры *IMAGE_HEIGHT и *SKIP_IMAGES влияют только на определение и опрос трехмерных текстур.

8.2.2.3Операции перемещения пикселей

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

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

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

Некоторые из характеристик функционирования операций пиксельного переноса задаются с помощью команды glPixelTransfer*(). Другие характеристики задаются с помощью glPixelMap*(), описанной в следующем разделе.

void glPixelTransfer{if} (GLenum pname, TYPE param);

Устанавливает режимы пиксельной передачи, которые влияют на функционирование команд glDrawPixels()), glReadPixels(), glCopyPixels(), glTexImage1D(), glTexImage2D(), glTexImage3D(), glCopyTexImage1D(), glCopyTexImage2D(), glTexSubImage1D(), glTexSubImage2D(), glTexSubImage3D(), glCopyTexSubImage1D(), glCopyTexSubImage2D(), glCopyTexSubImage3D(), glGetTexImage(). Аргумент pname должен принимать одно из значений, приведенных в первой колонке таблицы 8-5, а paramодно из допустимых для соответствующего параметра значений.

Таблица 8-5. Параметры команды glPixelTransfer*()

Имя параметра

Тип

Начальное значение

Допустимый диапазон

GL_MAP_COLOR

GLboolean

FALSE

TRUE/FALSE

GL_MAP_STENCIL

GLboolean

FALSE

TRUE/FALSE

GL_INDEX_SHIFT

GLint

0

 

GL_INDEX_OFFSET

GLint

0

 

GL_RED_SCALE

GLfloat

1.0

 

GL_GREEN_SCALE

GLfloat

1.0

 

GL_BLUE_SCALE

GLfloat

1.0

 

GL_ALPHA_SCALE

GLfloat

1.0

 

GL_DEPTH_SCALE

GLfloat

1.0

 

GL_RED_BIAS

GLfloat

0.0

 

GL_GREEN_BIAS

GLfloat

0.0

 

 

 

 

 

GL_BLUE_BIAS

GLfloat

0.0

GL_ALPHA_BIAS

GLfloat

0.0

GL_DEPTH_BIAS

GLfloat

0.0

GL_POST_CONVOLUTION_RED_SCALE

GLfloat

1.0

GL_POST_CONVOLUTION_GREEN_SCALE

GLfloat

1.0

GL_POST_CONVOLUTION_BLUE_SCALE

GLfloat

1.0

GL_POST_CONVOLUTION_ALPHA_SCALE

GLfloat

1.0

GL_POST_CONVOLUTION_RED_BIAS

GLfloat

0.0

GL_POST_CONVOLUTION_GREEN_BIAS

GLfloat

0.0

GL_POST_CONVOLUTION_BLUE_BIAS

GLfloat

0.0

GL_POST_CONVOLUTION_ALPHA_BIAS

GLfloat

0.0

GL_POST_COLOR_MATRIX_RED_SCALE

GLfloat

1.0

GL_POST_COLOR_MATRIX_GREEN_SCALE

GLfloat

1.0

GL_POST_COLOR_MATRIX_BLUE_SCALE

GLfloat

1.0

GL_POST_COLOR_MATRIX_ALPHA_SCALE

GLfloat

1.0

GL_POST_COLOR_MATRIX_RED_BIAS

GLfloat

0.0

GL_POST_COLOR_MATRIX_GREEN_BIAS

GLfloat

0.0

GL_POST_COLOR_MATRIX_BLUE_BIAS

GLfloat

0.0

 

 

 

Замечание: Параметры GL_POST_CONVOLUTION_* и GL_POST_COLOR_MATRIX_*

присутствуют только в том случае, если ваша реализация OpenGL поддерживает подмножество команд обработки изображений.

Если параметр GL_MAP_COLOR или GL_MAP_STENCIL равны TRUE, активизировано отображение (mapping) пикселей. Все остальные параметры непосредственно влияют на величины цветовых компонент пикселей.

Масштаб (scale) и скос (bias) могут быть применены к красному, зеленому, синему, альфа и глубинному компонентам. Например, вам нужно масштабировать красный, зеленый и синий компоненты, считанные из буфера кадра, перед конверсией их к формату светлоты в процессорной памяти. Светлота (luminance) вычисляется как сумма красного, зеленого и синего компонентов, то есть если вы используете значения по умолчанию для GL_RED_SCALE, GL_GREEN_SCALE и GL_BLUE_SCALE, все компоненты

будут вносить одинаковый вклад в результирующую величину интенсивности или светлоты. Если вам нужно конвертировать RGB в светлоту в соответствии со стандартом

NTSC, установите GL_RED_SCALE в 0.30, GL_GREEN_SCALE в 0.59, а GL_BLUE_SCALE в 0.11.

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

8.2.2.4Отображение пикселей

Все цветовые компоненты, цветовые индексы и трафаретные индексы могут быть изменены с помощью ссылочной таблицы до помещения в экранную память. Это делается при помощи команды glPixelMap*().

void glPixelMap{ui us f}v (GLenum map, GLint mapsize, const TYPE *values);

Загружает пиксельную карту, заданную аргументом map, с числом вхождений mapsize, на величины которой указывает аргумент values. Таблица 8-6 отображает все имена и

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