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

RedBook

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

Устанавливает текущую позицию растра. Аргументы x, y, z и w задают координаты позиции растра. Если используется векторная форма функции, массив coords содержит координаты позиции растра. Если используется версия glRasterPos2*(), то zпринимается равным 0, а w– 1; похожим же образом, если используется glRasterPos3*(), то w принимается равным 1.

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

Замечание: Если вы хотите задать позицию растра в экранных координатах, вам следует убедиться в том, что вы задали видовую и проекционную матрицу для простого 2D отображения. Для этого подойдет последовательность команд вроде следующей (width и height представляют собой размеры порта просмотра):

glMatrixMode(GL_PROJECTION); glLoadIdentity();

gluOrtho2D(0.0, (GLfloat) width, 0.0, (GLfloat) height); glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

Чтобы получить текущую позицию растра, вы можете использовать команду glGetFloatv() с GL_CURRENT_RASTER_POSITION в качестве первого аргумента. Второй аргумент должен быть указателем на массив, способный сохранить четверку (x, y, z, w) в виде чисел с плавающей точкой. Если вы хотите выяснить, является ли текущая позиция растра легальной (допустимой), вызывайте glGetBooleanv() с константой

GL_CURRENT_RASTER_POSITION_VALID в качестве первого аргумента.

8.1.2 Отображение битовой карты

Как только вы установили желаемую позицию растра, вы можете использовать команду glBitmap(), чтобы вывести данные.

void glBitmap (GLsizei width,GLsizei height,GLfloat

,GLfloat

,GLfloat

,GLfloat

,GLubyte *bitmap);

 

 

 

 

 

 

Рисует битовую карту, заданную аргументом bitmap, который представляет собой указатель на данные карты. Начальная точка битовой карты помещается в текущую позицию растра. Если текущая позиция растра недопустима, ничего не рисуется, а позиция растра остается недопустимой. Аргументы width и height индицируют ширину и высоту битовой карты в пикселях. Ширина должна быть кратной 8-ми, поскольку данные хранятся в беззнаковых символах по 8 бит каждый. (В примере с символом F не имеет значения, присутствует ли в данных за границами реальной карты какой-либо мусор, поскольку glBitmap() вызывается с аргументом width равным 10 и, как

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

текущей позиции растра, отрицательные вниз и влево). Аргументы и задают смещение по x и y, которое добавляется к текущей позиции растра после растеризации битовой карты (рисунок 8-2).

Рисунок 8-2. Битовая карта и ассоциированные с ней параметры

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

После того, как битовая карта нарисована, текущая позиция растра сдвигается на и

по x и y осям соответственно. (Если вы просто хотите сдвинуть позицию растра, ничего не рисуя, вызовите команду glBitmap() с аргументом bitmap установленным в NULL и параметрами width и height равными 0.) Для стандартных латинских шрифтов

обычно равно 0, а -- положительное число, так как последующие символы

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

выводятся вертикально в столбик, нужно использовать равное 0, а отличное от 0. На рисунке 8-2, каждый раз при рисовании F текущая позиция растра сдвигается на 11 пикселей, оставляя между соседними символами пространство в 1 пиксель.

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

он должен находиться. Например, если в примере с символом F сделать равным 11.5 вместо 12, и нарисовать больше символов, пространство между буквами было бы то 1, то 2 пикселя, давая наилучшее к запрошенному пространству в 1.5 пикселя.

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

8.1.3 Выбор цвета для битовой карты

Вы уже знакомы с использованием команд glColor*() и glIndex*(), устанавливающих текущий цвет и текущий индекса для рисования геометрических примитивов. Те же самые команды используются для установки других переменных состояния: GL_CURRENT_RASTER_COLOR и GL_CURRENT_RASTER_INDEX, для рисования битовых карт. Переменная состояния, отвечающая за цвет растра устанавливается равной текущему цвету в момент вызова glRasterPos*(). Это может сыграть злую шутку. Как вы думаете, каков будет цвет битовой карты после выполнения следующего кода?

glColor3f(1.0,1.0,1.0); /*белый*/ glRasterPos3fv(position); glColor3f(1.0,0.0,0.0); /*красный*/ glBitmap(...);

Вы удивлены, что битовая карта будет белой? Переменная GL_CURRENT_RASTER_COLOR устанавливается в белый цвет в момент вызова glRasterPos3fv(). Второй вызов glColor3f() меняет значение переменной GL_CURRENT_COLOR для визуализации будущих геометрических примитивов, но цвет, используемый для визуализации битовых карт, остается неизменным.

Чтобы выяснить текущий цвет или индекс растра, вы можете использовать опросные

команды glGetFloatv() или glGetIntegerv() с аргументами

GL_CURRENT_RASTER_COLOR или GL_CURRENT_RASTER_INDEX в качестве первого аргумента.

8.1.4 Шрифты и списки отображения

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

Шрифт обычно состоит из набора символов, где каждый символ имеет идентификационный номер (как правило, свой ASCII код) и метод начертания. В стандартном наборе символов ASCII заглавная буква A (в латинице) имеет номер 65, B

– 66 и так далее. Строка «DAB» может быть представлена тремя индексами 68, 65 и 66. В простейшем случае список отображения номер 65 рисует A, номер 66 – B и так далее. То есть для того, чтобы вывести строку из символов 68, 65, 66 просто вызовите к исполнению соответствующие списки отображения.

Вы можете использовать команду glCallLists() следующим образом:

void glCallLists(GLsizei n, GLenum type, const GLvoid *lists);

Первый аргумент, n, индицирует количество выводимых символов, type обычно равен GL_BYTE, а listsэто массив кодов символов.

Поскольку многим приложениям требуется отображать символы разных размеров и из разных шрифтов, простейший случай нас не устраивает. Было бы неплохо использовать 65 для символа Aнезависимо от того, какой шрифт является активным на данный момент. Вы могли бы в шрифте 1 закодировать A, B и Cномерами 1065, 1066 и 1067, а в шрифте 2 – номерами 2065, 2066 и 2067, но тогда любые номера больше 256 уже не будут укладываться в 8-ми битовый байт. Лучшее решение заключается в том, чтобы добавлять некоторое смещение к каждому вхождению в строку до того, как производится выбор списка отображения. В этом случае символы A, B и C будут представлены номерами 1065, 1066 и 1067 в шрифте 1, а в шрифте 2 они могут быть представлены числами 2065, 2066 и 2067. Тогда, чтобы нарисовать символы шрифтом 1, нужно установить смещение равным 1000 и вызвать к исполнению списки отображения 65, 66 и 67. Чтобы нарисовать ту же строку шрифтом 2, нужно установить смещение равным 2000 и вызвать к исполнению те же списки.

Для того, чтобы установить смещение, используйте команду glListBase(). Для предыдущих примеров она должна быть вызвана с 1000 и 2000 в качестве единственного аргумента. Теперь все, что вам нужно это непрерывный диапазон неиспользуемых индексов списков отображения, который может быть получен с помощью команды glGenLists():

GLuint glGenLists (GLsizei range);

Эта функция возвращает блок, состоящий из range идентификаторов списков отображения. Возвращенные списки маркируются как «используемые» даже несмотря на то, что они пусты, так что последующие вызовы glGenLists() никогда не возвращают те же номера списков (если только вы не удалили их перед этим). Таким образом, если вы используете 4 в качестве аргумента и glGenLists() возвращает 81, вы можете использовать идентификаторы списков отображения 81, 82, 83 и 84 для ваших символов. Если glGenLists() не может найти блок свободных индексов нужного размера, она возвращает 0. (Заметьте, что команда glDeleteLists() позволяет удалить все списки отображения, связанные со шрифтом, за один вызов.)

Большинство американских и европейских шрифтов включают небольшое число символов (менее 256), так что довольно легко представить каждый символ уникальным кодом, который может быть сохранен в одном байте. Азиатские шрифты (и некоторые другие) могут содержать намного большие наборы символов, и однобайтовой кодировки может быть недостаточно. OpenGL позволяет обрабатывать строки, состоящие из 1-, 2-, 3- и 4-ех байтовых символов с помощью параметра type команды glCallLists(). Этот параметр может иметь любое из следующих значений:

GL_BYTE GL_UNSIGNED_BYTE

GL_SHORT GL_UNSIGNED_SHORT

GL_INT GL_UNSIGNED_INT

GL_FLOAT GL_2_BYTES

GL_3_BYTES GL_4_BYTES

8.1.5 Описание и использование целого шрифта

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

программа выводит сообщение «THEQUICKBROWNFOXJUMPSOVERALAZYDOG.» (рисунок 8-3).

Код примера 8-2 похож на пример с символом F за исключением того, что здесь битовая карта каждого символа сохраняется в своем собственном списке отображения. Комбинирование идентификатора списка со смещением, возвращенным командой glGenLists() равно ASCII коду символа.

Рисунок 8-3. Фраза, написанная растровым шрифтом

Пример 8-2. Отображение полного шрифта: файл font.cpp

#include <glut.h> #include <string.h>

GLubyte space[]= {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; GLubyte letters[][13]={ {0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xff,0xc3,0xc3,0xc3,0x66,0x3c,0x18}, {0x00,0x00,0xfe,0xc7,0xc3,0xc3,0xc7,0xfe,0xc7,0xc3,0xc3,0xc7,0xfe}, {0x00,0x00,0x7e,0x7e,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xe7,0x7e},

{0x00,0x00,0xfc,0xce,0xc7,0xc3,0xc3,0xc3,0xc3,0xc3,0xc7,0xce,0xfc},

{0x00,0x00,0xff,0xc0,0xc0,0xc0,0xc0,0xfc,0xc0,0xc0,0xc0,0xc0,0xff},

{0x00,0x00,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xfc,0xc0,0xc0,0xc0,0xff},

{0x00,0x00,0x7e,0x7e,0xc3,0xc3,0xcf,0xc0,0xc0,0xc0,0xc0,0xe7,0x7e},

{0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,0xff,0xc3,0xc3,0xc3,0xc3,0xc3},

{0x00,0x00,0x7e,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7e},

{0x00,0x00,0x7c,0xee,0xc6,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06},

{0x00,0x00,0xc3,0xc6,0xcc,0xd8,0xf0,0xe0,0xf0,0xd8,0xcc,0xc6,0xc3},

{0x00,0x00,0xff,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0},

{0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xdb,0xff,0xff,0xe7,0xc3},

{0x00,0x00,0xc7,0xc7,0xcf,0xcf,0xdf,0xdb,0xfb,0xf3,0xf3,0xe3,0xe3},

{0x00,0x00,0x7e,0xe7,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xe7,0x7e},

{0x00,0x00,0xc0,0xc0,0xc0,0xc0,0xc0,0xfe,0xc7,0xc3,0xc3,0xc7,0xfe},

{0x00,0x00,0x3f,0x6e,0xdf,0xdb,0xc3,0xc3,0xc3,0xc3,0xc3,0x66,0x3c},

{0x00,0x00,0xc3,0xc6,0xcc,0xd8,0xf0,0xfe,0xc7,0xc3,0xc3,0xc7,0xfe},

{0x00,0x00,0x7e,0xe7,0x03,0x03,0x07,0x7e,0xe0,0xc0,0xc0,0xe7,0x7e},

{0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff},

{0x00,0x00,0x7e,0xe7,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3},

{0x00,0x00,0x18,0x3c,0x3c,0x66,0x66,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3},

{0x00,0x00,0xc3,0xe7,0xff,0xff,0xdb,0xdb,0xc3,0xc3,0xc3,0xc3,0xc3},

{0x00,0x00,0xc3,0x66,0x66,0x3c,0x3c,0x18,0x3c,0x3c,0x66,0x66,0xc3},

{0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x3c,0x66,0x66,0xc3},

{0x00,0x00,0xff,0xc0,0xc0,0x60,0x30,0x7e,0x0c,0x06,0x03,0x03,0xff}

};

GLuint fontOffset;

void makeRasterFont()

{

GLuint i,j;

glPixelStorei(GL_UNPACK_ALIGNMENT,1); fontOffset=glGenLists(128); for(i=0,j='A';i<26;i++,j++)

{

glNewList(fontOffset+j,GL_COMPILE); glBitmap(8,13,0.0,2.0,10.0,0.0,letters[i]);

glEndList();

}

glNewList(fontOffset+' ',GL_COMPILE); glBitmap(8,13,0.0,2.0,10.0,0.0,space);

glEndList();

}

void init(void)

{

glShadeModel(GL_FLAT); makeRasterFont();

}

void printString(char *s)

{

glPushAttrib(GL_LIST_BIT); glListBase(fontOffset);

glCallLists(strlen(s),GL_UNSIGNED_BYTE,(GLubyte*)s); glPopAttrib();

}

void display(void)

{

GLfloat white[3]={1.0,1.0,1.0};

glClear(GL_COLOR_BUFFER_BIT); glColor3fv(white); glRasterPos2i(20,60);

printString("THE QUICK BROWN FOX JUMPS"); glRasterPos2i(20,40);

printString("OVER A LAZY DOG"); glFlush();

}

void reshape(int w, int h)

{

glViewport(0,0,(GLsizei) 300, (GLsizei) 100); glMatrixMode(GL_PROJECTION);

glLoadIdentity(); glOrtho(0,w,0,h,-1.0,1.0); glMatrixMode(GL_MODELVIEW);

}

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

{

switch(key)

{

case 27: exit(0); break;

}

}

int main(int argc, char **argv)

{

glutInit(&argc,argv); glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); glutInitWindowSize(300,100); glutCreateWindow("Drawing a Complete Font"); init();

glutDisplayFunc(display);

glutReshapeFunc(reshape);

glutKeyboardFunc(keyboard);

glutMainLoop(); return 0;

}

8.2 Изображения

Изображение похоже на битовую карту, но вместо одного бита на каждый пиксель прямоугольной области экрана, изображение может содержать значительно больше информации. Например, изображение может содержать информацию о полном цвете (R, G, B, A) для каждого пикселя. Изображения могут быть получены из нескольких источников, таких как:

Оцифрованные сканером фотографии

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

считано в память пиксель за пикселем

Программа, которая генерирует изображение в памяти пиксель за пикселем.

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

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

8.2.1 Считывание, запись и копирование пиксельных данных

OpenGL предоставляет три основные команды для манипуляции данными изображения:

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

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

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

Порядок обработки пиксельных данных для вышеозначенных команд показан на рисунке 8-4.

Рисунок 8-4. Упрощенная диаграмма потоков пиксельных данных

Рисунок 8-4 отображает основной поток пикселей в процессе обработки. Координаты glRasterPos*(), которые задают текущую позицию растра и используются командами glDrawPixels() и glCopyPixels(), преобразуются геометрическим конвейером.

Растеризация и пофрагментные операции влияют и на glDrawPixels() и на glCopyPixels(). (Однако, когда рисуется или копируется прямоугольник пикселей, как правило, нет причин для использования тумана или текстуры.)

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

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

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

8.2.1.1Чтение пикселей из буфера кадра в память процессора

void glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);

Считывает пиксельные данные из прямоугольника буфера кадра, чей левый нижний угол находится в точке с оконными координатами (x, y), а ширина и высота равны width и height, и сохраняет его в массиве, на который указывает аргумент pixels. Аргумент format задает характер элементов пиксельных данных, которые должны быть считаны (величина индекса или величины R, G, B или A в соответствии с таблицей 8-1), а type задает тип данных для каждого элемента (таблица 8-2).

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

Таблица 8-1. Форматы пикселей для команд glReadPixels() и glDrawPixels()

Константа формата

Формат пикселей

GL_COLOR_INDEX

единственный цветовой индекс

GL_RGB

красный компонент цвета, затем зеленый и синий компоненты

GL_RGBA

красный компонент цвета, затем зеленый, синий и альфа компоненты

GL_BGR

синий компонент цвета, затем зеленый и красный компоненты

GL_BGRA

синий компонент цвета, затем зеленый, красный и альфа компоненты

GL_RED

только красный компонент цвета

GL_GREEN

только зеленый компонент цвета

GL_BLUE

только синий компонент цвета

GL_ALPHA

только альфа компонент цвета

GL_LUMINANCE

только светлота

GL_LUMINANCE_ALPHA

светлота, а затем альфа компонент

GL_STENCIL_INDEX

только индекс из буфера трафарета

GL_DEPTH_COMPONENT

только компонент глубины

 

 

Замечание: Форматы пикселей GL_BGR и GL_BGRA появились в OpenGL версии 1.2.

Таблица 8-2. Типы данных для glReadPixels() и glDrawPixels()

Константа типа

Тип данных

GL_UNSIGNED_BYTE

8-ми битовое беззнаковое целое

GL_BYTE

8-ми битовое знаковое целое

GL_BITMAP

по одному биту на пиксель, биты хранятся в 8-ми битовых целых (тот

же формат, что и для glBitmap())

 

GL_UNSIGNED_SHORT

16-ми битовое беззнаковое целое

GL_SHORT

16-ми битовое знаковое целое

GL_UNSIGNED_INT

32-ми битовое беззнаковое целое

GL_INT

32-ми битовое знаковое целое

GL_FLOAT

число с плавающей точкой одинарной точности

GL_UNSIGNED_BYTE_3_3_2

упакованный в 8-ми битовое беззнаковое целое

GL_UNSIGNED_BYTE_2_3_3_REV

упакованный в 8-ми битовое беззнаковое целое

GL_UNSIGNED_SHORT_5_6_5

упакованный в 16-ми битовое беззнаковое целое

GL_UNSIGNED_SHORT_5_6_5_REV

упакованный в 16-ми битовое беззнаковое целое

GL_UNSIGNED_SHORT_4_4_4_4

упакованный в 16-ми битовое беззнаковое целое

GL_UNSIGNED_SHORT_4_4_4_4_REV

упакованный в 16-ми битовое беззнаковое целое

GL_UNSIGNED_SHORT_5_5_5_1

упакованный в 16-ми битовое беззнаковое целое

GL_UNSIGNED_SHORT_1_5_5_5_REV

упакованный в 16-ми битовое беззнаковое целое

 

 

GL_UNSIGNED_INT_8_8_8_8

упакованный в 32-ми битовое беззнаковое целое

GL_UNSIGNED_INT_8_8_8_8_REV

упакованный в 32-ми битовое беззнаковое целое

GL_UNSIGNED_INT_10_10_10_2

упакованный в 32-ми битовое беззнаковое целое

GL_UNSIGNED_INT_2_10_10_10_REV упакованный в 32-ми битовое беззнаковое целое

Замечание: Пиксельные форматы GL_*_REV особенно удобны для применения в операционных системах MicrosoftWindows.

Помните, что в зависимости от формата, могут считываться ил записываться от одного до четырех элементов. Например, если формат равен GL_RGBA, и вы производите считывание в 32-х разрядные целые (то есть type равен GL_UNSIGNED_INT или GL_INT), то считывание данных для одного пикселя потребует 16 байт пространства в памяти (4 компонента * 4 байта на компонент).

Каждый элемент изображения сохраняется в памяти, как показано в таблице 8-2. Если элемент представляет собой длинную (точную) величину такую как значение красного, зеленого, синего или величину освещенности, каждая величина масштабируется имеющегося количества бит. Предположим, например, что изначально красный компонент был задан в виде числа с плавающей точкой между 0.0 и 1.0. Если требуется упаковать его в беззнаковый байт, то сохранятся только 8 бит точности, даже если для красного компонента в буфере кадра было выделено больше бит. GL_UNSIGNED_SHORT и GL_UNSIGNED_INT дадут 16 бит и 32 бита точности соответственно. Знаковые версии GL_BYTE, GL_SHORTи GL_INT дают 7, 15 и 31 бит точности, поскольку отрицательные величины, как правило, не используются.

Если элемент является индексом (цветовым индексом или индексом из буфера трафарета, например) и тип не равен GL_FLOAT, величина просто маскируется до доступного числа бит. Знаковые версии – GL_BYTE, GL_SHORT и GL_INT – имеют маски меньшие на 1 бит. Например, если цветовой индекс должен быть сохранен в знаковом 8-ми разрядном целом, он сначала маскируется с 0x7f. Если тип равен GL_FLOAT,

индекс просто конвертируется в число с плавающей точкой одинарной точности (например, индекс 17 будет преобразован к дробному числу 17.0).

Для упакованных типов данных (задаваемых константами, которые начинаются с

GL_UNSIGNED_BYTE_*, GL_UNSIGNED_SHORT_* или GL_UNSIGNED_INT_*), все цветовые компоненты каждого пикселя ужимаются в один элемент данных, заданного беззнакового типа: или в байт, или в короткое целое, или в стандартное целое. Для каждого типа данных допустимы определенные форматы, показанные в таблице 8-3. Если для упакованного типа данных используется нелегальный формат пикселей,

генерируется ошибка GL_INVALID_OPERATION.

Замечание: Упакованные форматы пикселей появились в OpenGL версии 1.2.

Таблица 8-3. Допустимые форматы пикселей для упакованных типов данных

Константа упакованного типа

Допустимые форматы пикселей

GL_UNSIGNED_BYTE_3_3_2

GL_RGB

GL_UNSIGNED_BYTE_2_3_3_REV

GL_RGB

GL_UNSIGNED_SHORT_5_6_5

GL_RGB

GL_UNSIGNED_SHORT_5_6_5_REV

GL_RGB

GL_UNSIGNED_SHORT_4_4_4_4

GL_RGBA, GL_BGRA

GL_UNSIGNED_SHORT_4_4_4_4_REV

GL_RGBA, GL_BGRA

GL_UNSIGNED_SHORT_5_5_5_1

GL_RGBA, GL_BGRA

GL_UNSIGNED_SHORT_1_5_5_5_REV

GL_RGBA, GL_BGRA

GL_UNSIGNED_INT_8_8_8_8

GL_RGBA, GL_BGRA

GL_UNSIGNED_INT_8_8_8_8_REV

GL_RGBA, GL_BGRA

GL_UNSIGNED_INT_10_10_10_2

GL_RGBA, GL_BGRA

 

 

GL_UNSIGNED_INT_2_10_10_10_REV GL_RGBA, GL_BGRA

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

Для иллюстрации этого, посмотрите на рисунок 8-5, который показывает порядок битовых полей для типов GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV

и 4 допустимые комбинации GL_UNSIGNED_SHORT_4_4_4_4 (и REV) типов данных и пиксельных форматов RGBA/BGRA. Организация битовых полей для других 14-ти

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

Рисунок 8-5. Порядок компонентов для нескольких типов данных и форматов пикселей

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

8.2.1.2 Запись пиксельных данных из процессорной памяти в буфер кадра

void glDrawPixels (GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);

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