Милютина Лабораторные работа 6.ppt
- Количество слайдов: 73
Лабораторная работа 6 «Растеризация изображения. Конвейер визуализации в Open. GL. Отображение пикселей, битовых карт, шрифтов изображений»
К О Н В Е Й Е Р В И З У А Л И З А Ц И И
Битовые карты и шрифты Битовая карта – это прямоугольный массив из нулей и единиц, который служит в качестве маски для прямоугольной части окна. . Предположим, что вы рисуете битовую карту и текущий цвет – красный.
Везде, где в битовой карте встречается 1, соответствующий пиксель в буфере кадра замещается красным (или комбинируется с красным в зависимости от того, какие пофрагментные операции производятся).
Там, где в битовой карте стоит 0, фрагменты не генерируются и пиксели не изменяются. Битовые карты наиболее часто используются для рисования символов на экране.
Open. GL предоставляет только низкоуровневую поддержку для рисования строк символов и манипуляций со шрифтами. Команды gl. Raster. Pos*() и gl. Bitmap() позиционируют и рисуют на экране одну битовую карту.
Пример 6. 1 Вывод изображения битовой карты символа
Битовая карта символа F и ее данные
На рисунке видимая часть символа F занимает 10 бит в ширину. Битовые карты всегда хранятся кусками, ширина которых кратна 8, но реальная ширина битовой карты не обязана быть кратной 8.
Биты, задающие битовую карту, выводятся, начиная с левого нижнего угла: сначала рисуется нижний ряд, затем ряд над ним и так далее.
В коде, битовая карта хранится в памяти именно в этом порядке – массив начинается с чисел 0 xc 0, 0 x 00, задающих два нижних ряда символа F и заканчивается числами 0 xff, 0 xc 0, задающими два верхних ряда.
GLubyte rasters[24]= { 0 x. C 0, 0 x 00, 0 x. C 0, 0 x 00, 0 x. FF, 0 x 00, 0 x. C 0, 0 x 00, 0 x. FF, 0 x. C 0 };
Пока проигнорируем команду gl. Pixel. Storei(); она указывает на то, как данные битовой карты хранятся в памяти компьютера.
Текущая позиция растра – это некоторое положение на экране, где будет нарисована следующая битовая карта. В примере текущая позиция растра была установлена командой gl. Raster. Pos*() с координатами (20, 20) в качестве параметров. Это то место, где был помещен нижний левый угол символа F.
Как только вы установили желаемую позицию растра, можете использовать команду gl. Bitmap(), чтобы вывести данные.
Битовая карта и ассоциированные с ней параметры
Выбор цвета для битовой карты Команды gl. Color*() и gl. Index*(), устанавливающие текущий цвет и текущий индекс для рисования геометрических примитивов используются для установки других переменных состояния GL_CURRENT_RASTER_COLOR и GL_CURRENT_RASTER_INDEX, для рисования битовых карт.
Переменная состояния, отвечающая за цвет растра устанавливается равной текущему цвету в момент вызова gl. Raster. Pos*().
Чтобы выяснить текущий цвет или индекс растра, вы можете использовать опросные команды gl. Get. Floatv() или gl. Get. Integerv() с аргументами GL_CURRENT_RASTER_COLOR или GL_CURRENT_RASTER_INDEX в качестве первого аргумента.
Пример 6. 2 Шаблонирование полигонов
По умолчанию, если полигон рисуется в виде закрашенной области, он закрашивается одинаково по всей своей площади, без просветов. Эту ситуацию можно изменить, определив шаблон заливки полигона в виде матрицы 32 x 32 бита и установив его командой gl. Polygon. Stipple().
void gl. Polygon. Stipple (const GLubyte *mask); Определяет текущий рисунок шаблона заливки полигона. Параметр mask – это указатель на битовую карту размером 32 x 32 бита, интерпретируемую в качестве маски, накладываемой на полигон при рисовании (и при необходимости повторяемой).
Шаблонирование полигонов включается и выключается с помощью аргумента GL_POLYGON_STIPPLE функций gl. Enable() и gl. Disable(). Интерпретация mask зависит от GL_UNPACK* параметров команды gl. Pixel. Store*().
Кроме того, вы должны включить шаблонирование полигонов: gl. Enable(GL_POLYGON_STIPPLE); Используйте gl. Disable() с аналогичным аргументом для выключения шаблонирования.
Шаблонированные полигоны
void init(void) { gl. Clear. Color(0. 0, 0. 0); gl. Shade. Model(GL_FLAT); }
void display(void) { GLubyte fly[]= { 0 x 00, 0 x 00, 0 x 03, 0 x 80, 0 x 01, 0 x. C 0, 0 x 06, 0 x. C 0, 0 x 03, 0 x 60, 0 x 04, 0 x 60, 0 x 06, 0 x 20, 0 x 04, 0 x 30, 0 x 0 C, 0 x 20, 0 x 04, 0 x 18, 0 x 20, 0 x 04, 0 x 0 C, 0 x 30, 0 x 20, 0 x 04, 0 x 06, 0 x 60, 0 x 20, 0 x 44, 0 x 03, 0 x. C 0, 0 x 22, 0 x 44, 0 x 01, 0 x 80, 0 x 22, 0 x 44, 0 x 01, 0 x 80, 0 x 22, 0 x 66, 0 x 01, 0 x 80, 0 x 66, 0 x 33, 0 x 01, 0 x 80, 0 x. CC, 0 x 19, 0 x 81, 0 x 98, 0 x 0 C, 0 x. C 1, 0 x 83, 0 x 30, 0 x 07, 0 x. E 1, 0 x 87, 0 x. E 0, 0 x 03, 0 x 3 F, 0 x. FC, 0 x. C 0, 0 x 03, 0 x 31, 0 x 8 C, 0 x. C 0, 0 x 03, 0 x 33, 0 x. CC, 0 x. C 0, 0 x 06, 0 x 64, 0 x 26, 0 x 60, 0 x 0 C, 0 x. CC, 0 x 33, 0 x 30, 0 x 18, 0 x. CC, 0 x 33, 0 x 18, 0 x 10, 0 x. C 4, 0 x 23, 0 x 08, 0 x 10, 0 x 63, 0 x. C 6, 0 x 08, 0 x 10, 0 x 30, 0 x 0 C, 0 x 08, 0 x 10, 0 x 18, 0 x 08, 0 x 10, 0 x 00, 0 x 08 };
GLubyte halftone[] = { 0 x. AA, 0 x. AA, 0 x 55, 0 x 55, 0 x 55, 0 x 55, 0 x. AA, 0 x 55, 0 x 55, 0 x 55, 0 x 55, 0 x. AA, 0 x 55, 0 x 55 };
gl. Clear(GL_COLOR_BUFFER_BIT); gl. Color 3 f(1. 0, 1. 0); //Рисуем один нешаблонированный прямоугольник //и два шаблоннированных gl. Rectf(25. 0, 125. 0); gl. Enable(GL_POLYGON_STIPPLE); gl. Polygon. Stipple(fly); gl. Rectf(125. 0, 225. 0, 125. 0); gl. Polygon. Stipple(halftone); gl. Rectf(225. 0, 325. 0, 125. 0); gl. Disable(GL_POLYGON_STIPPLE); gl. Flush(); }
void reshape(int w, int h) { gl. Viewport(0, 0, (GLsizei) w, (GLsizei) h); gl. Matrix. Mode(GL_PROJECTION); gl. Load. Identity(); glu. Ortho 2 D(0. 0, 350. 0, 150. 0) ; }
int main(int argc, char **argv) { glut. Init(&argc, argv); glut. Init. Display. Mode(GLUT_SINGLE|GLUT _RGB); glut. Init. Window. Size(350, 150); glut. Create. Window("Polygon Stipple Patterns"); init(); glut. Display. Func(display); glut. Reshape. Func(reshape); glut. Main. Loop(); return 0; }
Пример 6. 3 Отображение полного шрифта
Шрифт обычно состоит из набора символов, где каждый символ имеет идентификационный номер (как правило, свой ASCII код) и метод начертания.
В стандартном наборе символов ASCII заглавная буква A (в латинице) имеет номер 65, B – 66 и т. д. Строка «DAB» может быть представлена тремя индексами 68, 65 и 66. То есть для того, чтобы вывести строку из символов 68, 65, 66 просто вызовите к исполнению соответствующие списки отображения.
Можно использовать команду gl. Call. Lists() следующим образом: void gl. Call. Lists(GLsizei n, GLenum type, const Glvoid *lists); Аргумент, n, индицирует количество выводимых символов, type обычно равен GL_BYTE, а lists– это массив кодов символов.
Код примера 6. 2 похож на пример с символом F за исключением того, что здесь битовая карта каждого символа сохраняется в своем собственном списке отображения. Комбинирование идентификатора списка со смещением, возвращенным командой gl. Gen. Lists() равно ASCII коду символа.
GLubyte space[]= {0 x 00, 0 x 00, 0 x 00, 0 x 00}; GLubyte letters[][13]={ {{0 x 00, 0 xc 3, 0 xff, 0 xc 3, 0 x 66, 0 x 3 c, 0 x 18}, {0 x 00, 0 xfe, 0 xc 7, 0 xc 3, 0 xc 7, 0 xfe}, {0 x 00, 0 x 7 e, 0 xc 0, 0 xc 0, 0 xe 7, 0 x 7 e},
{0 x 00, 0 xfc, 0 xce, 0 xc 7, 0 xc 3, 0 xc 3, 0 xc 7, 0 xce, 0 xfc}, {0 x 00, 0 xff, 0 xc 0, 0 xfc, 0 xc 0, 0 xff}, {0 x 00, 0 xc 0, 0 xc 0, 0 xfc, 0 xc 0, 0 xff}, {0 x 00, 0 x 7 e, 0 xc 3, 0 xcf, 0 xc 0, 0 xe 7, 0 x 7 e}, {0 x 00, 0 xc 3, 0 xc 3, 0 xff, 0 xc 3, 0 xc 3}, {0 x 00, 0 x 7 e, 0 x 18, 0 x 18, 0 x 18, 0 x 7 e}, {0 x 00, 0 x 7 c, 0 xee, 0 xc 6, 0 x 06, 0 x 06, 0 x 06}, {0 x 00, 0 xc 3, 0 xc 6, 0 xcc, 0 xd 8, 0 xf 0, 0 xe 0, 0 xf 0, 0 xd 8, 0 xcc, 0 xc 6, 0 xc 3}, {0 x 00, 0 xff, 0 xc 0, 0 xc 0, 0 xc 0}, {0 x 00, 0 xc 3, 0 xc 3, 0 xdb, 0 xff, 0 xe 7, 0 xc 3}, {0 x 00, 0 xc 7, 0 xcf, 0 xdf, 0 xdb, 0 xf 3, 0 xe 3}, {0 x 00, 0 x 7 e, 0 xe 7, 0 xc 3, 0 xc 3, 0 xe 7, 0 x 7 e}, {0 x 00, 0 xc 0, 0 xc 0, 0 xfe, 0 xc 7, 0 xc 3, 0 xc 7, 0 xfe}, {0 x 00, 0 x 3 f, 0 x 6 e, 0 xdf, 0 xdb, 0 xc 3, 0 xc 3, 0 x 66, 0 x 3 c}, {0 x 00, 0 xc 3, 0 xc 6, 0 xcc, 0 xd 8, 0 xf 0, 0 xfe, 0 xc 7, 0 xc 3, 0 xc 7, 0 xfe}, {0 x 00, 0 x 7 e, 0 xe 7, 0 x 03, 0 x 07, 0 x 7 e, 0 xe 0, 0 xc 0, 0 xe 7, 0 x 7 e}, {0 x 00, 0 x 18, 0 x 18, 0 x 18, 0 xff}, {0 x 00, 0 x 7 e, 0 xe 7, 0 xc 3, 0 xc 3, 0 xc 3}, {0 x 00, 0 x 18, 0 x 3 c, 0 x 66, 0 xc 3, 0 xc 3}, {0 x 00, 0 xc 3, 0 xe 7, 0 xff, 0 xdb, 0 xc 3, 0 xc 3}, {0 x 00, 0 xc 3, 0 x 66, 0 x 3 c, 0 x 18, 0 x 3 c, 0 x 66, 0 xc 3}, {0 x 00, 0 x 18, 0 x 18, 0 x 3 c, 0 x 66, 0 xc 3}, {0 x 00, 0 xff, 0 xc 0, 0 x 60, 0 x 30, 0 x 7 e, 0 x 0 c, 0 x 06, 0 x 03, 0 xff} };
Пример 6. 4 Рисование, копирование и масштабирование пиксельных данных
Изображения Изображение похоже на битовую карту, но вместо одного бита на каждый пиксель прямоугольной области экрана, изображение может содержать значительно больше информации. Например, изображение может содержать информацию о полном цвете (R, G, B, A) для каждого пикселя.
Open. GL предоставляет три основные команды для манипуляции данными изображения: gl. Read. Pixels() – считывает прямоугольный массив пикселей из буфера кадра в процессорную память. gl. Draw. Pixels() – записывает прямоугольный массив пикселей из данных, хранящихся в процессорной памяти, в буфер кадра в текущую позицию растра, заданную командой gl. Raster. Pos*().
gl. Copy. Pixels() – копирует прямоугольный массив пикселей из одной части буфера кадра в другую. Эта команда ведет себя так же как пара вызовов gl. Read. Pixels() и gl. Draw. Pixels(), но данные никогда не попадают в процессорную память.
Чтение пикселей из буфера кадра в память процессора void gl. Read. Pixels (GLint x, GLint y, GLsizei width, GLsizei height, Glenum format, GLenum type, GLvoid *pixels);
Считывает пиксельные данные из прямоугольника буфера кадра, чей левый нижний угол находится в точке с оконными координатами (x, y), а ширина и высота равны width и height, и сохраняет его в массиве, на который указывает аргумент pixels.
Аргумент format задает характер элементов пиксельных данных, которые должны быть считаны (величина индекса или величины R, G, B или A в соответствии с таблицей 1), а type задает тип данных для каждого элемента (таблица 2).
Форматы пикселей для команд gl. Read. Pixels() и gl. Draw. Pixels() Таблица 1
Типы данных для gl. Read. Pixels() и gl. Draw. Pixels() Таблица 2
Запись пиксельных данных из процессорной памяти в буфер кадра void gl. Draw. Pixels (GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
Рисует прямоугольник пиксельных данных размерами width и height. Пиксельный прямоугольник рисуется таким образом, что его левый нижний угол находится в текущей позиции растра.
Аргументы format и type имеют то же значение, что и для команды gl. Read. Pixels(). (Смотрите таблицы 1 и 2. ) Массив, на который указывает pixels, должен содержать пиксельные данные для рисования. Если текущая позиция растра недопустима, ничего не рисуется, а позиция растра остается недопустимой.
Копирование пиксельных данных внутри буфера кадра void gl. Copy. Pixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum buffer);
Копирует пиксельные данные из прямоугольника в буфере кадра, чей левый нижний угол задается координатами (x, y), а размеры – аргументами width и height. Данные копируются в новую позицию, чей левый нижний угол задается текущей позицией растра.
Аргумент buffer может принимать значения GL_COLOR, GL_STENCIL или GL_DEPTH, задавая используемый буфер кадра. gl. Copy. Pixels() ведет себя так же как пара смежных вызовов gl. Read. Pixels() и gl. Draw. Pixels() со следующим отображением параметра buffer на значение параметра format:
Если buffer равен GL_DEPTH или GL_STENCIL, то format равен GL_DEPTH_COMPONENT или GL_STENCIL_INDEX, соответственно. · Если задан GL_COLOR, используется GL_RGBA или GL_COLOR_INDEX в зависимости от того, работает ли система в RGBA или индексном режиме.
#include <gl/glut. h> #include <windows. h> #include <stdio. h> #define check. Image. Width 64 #define check. Image. Height 64 GLubyte check. Image[check. Image. Height][che ck. Image. Width][3]; GLdouble zoom. Factor=1. 0; GLuint height;
void make. Check. Image() { int i, j, c; for (i=0; i<check. Image. Height; i++) { for (j=0; j<check. Image. Width; j++) { c=(((i&0 x 08)==0)^((j&0 x 8)==0))*255; check. Image[i][j][0]=(GLubyte)c; check. Image[i][j][1]=(GLubyte)c; check. Image[i][j][2]=(GLubyte)c; } } }
void init(void) { gl. Clear. Color(0. 0, 0. 0 ); gl. Shade. Model(GL_FLAT); make. Check. Image(); gl. Pixel. Storei(GL_UNPACK_ALIG NMENT, 1); }
void display(void) { gl. Clear(GL_COLOR_BUFFER_BIT); gl. Raster. Pos 2 i(0, 0); gl. Draw. Pixels(check. Image. Width, ch eck. Image. Height, GL_RGB, GL_UNSIGNED_BYTE, check. Im age); gl. Flush(); }
void reshape(int w, int h) { gl. Viewport(0, 0, (GLsizei) w, (GLsizei) h); height=(GLint)h; gl. Matrix. Mode(GL_PROJECTION); gl. Load. Identity(); glu. Ortho 2 D(0. 0, (GLdouble)w, 0. 0, (GLdouble)h); gl. Matrix. Mode(GL_MODELVIEW); gl. Load. Identity(); }
void motion(int x, int y) { static GLint screeny; screeny=height-(GLint)y; gl. Raster. Pos 2 i(x, screeny); gl. Pixel. Zoom(zoom. Factor, zoom. Factor ); gl. Copy. Pixels(0, 0, check. Image. Width, check. Image. Height, GL_COLOR); gl. Pixel. Zoom(1. 0, 1. 0); gl. Flush(); }
void keyboard(unsigned char key, int x, int y) { switch(key) { case 'r': case 'R': zoom. Factor=1. 0; glut. Post. Redisplay(); break; case 'z': zoom. Factor+=0. 5;
if (zoom. Factor>=3. 0) zoom. Factor=3. 0; break; case 'Z': zoom. Factor-=0. 5; if (zoom. Factor<=0. 5) zoom. Factor=0. 5; break; case 27: exit(0); break; } }
int main(int argc, char **argv) { glut. Init(&argc, argv); glut. Init. Display. Mode(GLUT_SINGLE|GLUT_RGB) ; glut. Init. Window. Size(250, 250); glut. Init. Window. Position(100, 100); glut. Create. Window("Drawing, Copying and Zooming Pixel Data"); init(); glut. Display. Func(display); glut. Reshape. Func(reshape); glut. Keyboard. Func(keyboard); glut. Motion. Func(motion); glut. Main. Loop(); return 0; }
Милютина Лабораторные работа 6.ppt