-
Для чего используются уровни детализации текстуры (mip-mapping)?
-
Глава 6.Операции с пикселями
После проведения всех операций по преобразованию координат вершин, вычисления цвета и т.п., OpenGL переходит к этапу растеризации, на котором происходит растеризация всех примитивов, наложение текстуры, наложение эффекта тумана. Для каждого примитива результатом этого процесса является занимаемая им в буфере кадра область, каждому пикселю этой области приписывается цвет и значение глубины.
OpenGL использует эту информацию, чтобы записать обновленные данные в буфер кадра. Для этого OpenGL имеет не только отдельный конвейер обработки пикселей, но и несколько дополнительных буферов различного назначения. Это позволяет программисту гибко контролировать процесс визуализации на самом низком уровне.
Графическая библиотека OpenGL поддерживает работу со следующими буферами:
-
несколько буферов цвета
-
буфер глубины
-
буфер-накопитель (аккумулятор)
-
буфер маски
Группа буферов цвета включает буфер кадра, но таких буферов может быть несколько. При использовании двойной буферизации говорят о рабочем (front) и фоновом (back) буферах. Как правило, в фоновом буфере программа создает изображение, которое затем разом копируется в рабочий буфер. На экране может появиться информация только из буферов цвета.
Буфер глубины используется для удаления невидимых поверхностей и прямая работа с ним требуется крайне редко.
Буфер-накопитель можно применять для различных операций. Более подробно работа с ним описана в разделе 6.2.
Буфер маски используется для формирования пиксельных масок (трафаретов), служащих для вырезания из общего массива тех пикселей, которые следует вывести на экран. Буфер маски и работа с ним более подробно рассмотрены в разделах 6.3, 7.2 и 7.3.
6.1.Смешивание изображений. Прозрачность
Разнообразные прозрачные объекты – стекла, прозрачная посуда и т.д. часто встречаются в реальности, поэтому важно уметь создавать такие объекты в интерактивной графике. OpenGL предоставляет программисту механизм работы с полупрозрачными объектами, который и будет кратко описан в этом разделе.
Прозрачность реализуется с помощью специального режима смешения цветов (blending). Алгоритм смешения комбинирует цвета так называемых входящих пикселей (т.е. «кандидатов» на помещение в буфер кадра) с цветами соответствующих пикселей, уже хранящихся в буфере. Для смешения используется четвертая компонента цвета – альфа-компонента, поэтому этот режим называют еще альфа-смешиванием. Программа может управлять интенсивностью альфа-компоненты точно так же, как и интенсивностью основных цветов, т.е. задавать значение интенсивности для каждого пикселя или каждой вершины примитива.
Режим включается с помощью команды glEnable(GL_BLEND).
Определить параметры смешения можно с помощью команды:
void glBlendFunc(enum src,enum dst)
Параметр src определяет, как получить коэффициент k1 исходного цвета пикселя, a dst задает способ получения коэффициента k2 для цвета в буфере кадра. Для получения результирующего цвета используется следующая формула: res=сsrc*k1+cdst*k2, где сsrc – цвет исходного пикселя, cdst – цвет пикселя в буфере кадра (res, k1, k1, сsrc, cdst – четырехкомпонентные RGBA-векторы).
Приведем наиболее часто используемые значения агрументов src и dst.
GL_SRC_ALPHA k=(As,As,As,As)
GL_SRC_ONE_MINUS_ALPHA k=(1,1,1,1)-(As,As,As,As)
GL_DST_COLOR k=(Rd,Gd,Bd)
GL_ONE_MINUS_DST_COLOR k=(1,1,1,1)- (Rd,Gd,Bd,Аd)
GL_DST_ALPHA k=(Ad,Ad,Ad,Ad)
GL_DST_ONE_MINUS_ALPHA k=(1,1,1,1)-(Ad,Ad,Ad,Ad)
GL_SRC_COLOR k=(Rs,Gs,Bs)
GL_ONE_MINUS_SRC_COLOR k=(1,1,1,1)- (Rs,Gs,Bs,As)
Пример:
Предположим, мы хотим реализовать вывод прозрачных объектов. Коэффициент прозрачности задается альфа-компонентой цвета. Пусть 1 – непрозрачный объект; 0 – абсолютно прозрачный, т.е. невидимый. Для реализации служит следующий код:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_SRC_ONE_MINUS_ALPHA);
Например, полупрозрачный треугольник можно задать следующим образом:
glColor3f(1.0, 0.0, 0.0, 0.5);
glBegin(GL_TRIANGLES);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(1.0, 0.0, 0.0);
glVertex3f(1.0, 1.0, 0.0);
glEnd();
Если в сцене есть несколько прозрачных объектов, которые могут перекрывать друг друга, корректный вывод можно гарантировать только в случае выполнения следующих условий:
-
Все прозрачные объекты выводятся после непрозрачных.
-
При выводе объекты с прозрачностью должны быть упорядочены по уменьшению глубины, т.е. выводиться, начиная с наиболее отдаленных от наблюдателя.
В OpenGL команды обрабатываются в порядке их поступления, поэтому для реализации перечисленных требований достаточно расставить в соответствующем порядке вызовы команд glVertex*(), но и это в общем случае нетривиально.
6.2.Буфер-накопитель
Буфер-накопитель (accumulation buffer) – это один из дополнительных буферов OpenGL. В нем можно сохранять визуализированное изображение, применяя при этом попиксельно специальные операции. Буфер-накопитель широко используется для создания различных спецэффектов.
Изображение берется из буфера, выбранного на чтение командой
void glReadBuffer(enum buf)
Аргумент buf определяет буфер для чтения. Значения buf, равные GL_BACK, GL_FRONT, определяют соответствующие буферы цвета для чтения. GL_BACK задает в качестве источника пикселей внеэкранный буфер; GL_FRONT – текущее содержимое окна вывода. Команда имеет значение, если используется дублирующая буферизация. В противном случае используется только один буфер, соответствующий окну вывода (строго говоря, OpenGL имеет набор дополнительных буферов, используемых, в частности, для работы со стерео изображениями, но здесь мы их рассматривать не будем).
Буфер-накопитель является дополнительным буфером цвета. Он не используется непосредственно для вывода образов, но они добавляются в него после вывода в один из буферов цвета. Применяя различные операции, описанные ниже, можно понемногу «накапливать» изображение в буфере.
Затем полученное изображение переносится из буфера-накопителя в один из буферов цвета, выбранный на запись командой
void glDrawBuffer(enum buf)
Значение buf аналогично значению соответствующего аргумента в команде glReadBuffer.
Все операции с буфером-накопителем контролируются командой
void glAccum(enum op,GLfloat value)
Аргумент op задает операцию над пикселями и может принимать следующие значения:
GL_LOAD Пиксель берется из буфера, выбранного на чтение, его значение умножается на value и заносится в буфер-накопитель.
GL_ACCUM Аналогично предыдущему, но полученное после умножения значение складывается с уже имеющимся в буфере.
GL_MULT Эта операция умножает значение каждого пикселя в буфере накопления на value .
GL_ADD Аналогично предыдущему, только вместо умножения используется сложение.
GL_RETURN Изображение переносится из буфера накопителя в буфер, выбранный для записи. Перед этим значение каждого пикселя умножается на value.
Следует отметить, что для использования буфера-накопителя нет необходимости вызывать какие-либо команды glEnable. Достаточно инициализировать только сам буфер.
Пример использования буфера-накопителя для устранения погрешностей растеризации (ступенчатости) приведен в разделе 7.1
Достарыңызбен бөлісу: |