RedBook
.pdf∙Сглаженный текст – Создайте для каждого символа карту текстуры с
относительно большим разрешением и наложите их на меньшие области (полигоны) с использованием текстурной фильтрации. Такой метод позволяет преобразовывать текст (поворачивать, масштабировать или искажать другими способами).
∙Сглаженные линии – Метод работает так же, как и для текста: сделайте линии на текстуре шириной в несколько пикселей и используйте фильтрацию.
∙Масштабирование и поворот изображений – Если вы поместите изображение в текстуру, а текстуру – на полигон, преобразования полигона будут отражаться и на изображении.
∙Изгибание изображений – Сохраните изображение в карте текстуры, но наложите ее не на полигон, а на сплайновую поверхность (используйте вычислители). Изменение контрольных точек поверхности приведет к изменениям в изображении.
∙Проектирование изображений – Поместите изображение в карту текстуры и спроецируйте его как прожектор, создав небольшой прожекторный эффект.
14.18 Рисование изображений, буферизованных по глубине
Для сложных статических изображений заднего плана время, требуемое на полную визуализацию из геометрических данных, может значительно превосходить время, необходимое для простого копирования того же плана, но в виде изображений. Если у
вас фиксированный задний план и относительно простой изменяющийся передний план, вы можете решить, что стоит отобразить задний план и его величины глубины в виде изображения, а не просчитывать его из геометрических данных. Передний план также может состоять из элементов, которые долго просчитывать, но изображение и величины глубины которых известны. Вы можете визуализировать эти элементы в окружении с буфером глубины, используя двухпроходный алгоритм.
Например, если вы рисуете молекулярную модель, созданную из сфер, у вас может быть припасено изображение великолепно просчитанной сферы (и ассоциированные с ним значения глубины), вычисленной с использованием закраски Фонга или трассировки лучей или с помощью какого-либо другого метода не поддерживаемого OpenGL непосредственно. Чтобы нарисовать сложную сцену, вам могут потребоваться сотни таких сфер, совместно буферизуемых по глубине.
Чтобы добавить глубинированное изображение к сцене, сначала запишите его значения глубины в буфер глубины с помощью команды glDrawPixels(). Затем активизируйте тест глубины, установите маску записи в 0, чтобы рисования не происходило, и активизируйте трафарет таким образом, чтобы рисование в буфер трафарета происходило всегда, когда происходит запись в буфер глубины.
Затем нарисуйте изображение в цветовом буфере, маскированном буфером трафарета (в который вы только что записали) таким образом, чтобы рисование происходило только в тех областях, где в буфере трафарета стоит 1. Во время этого рисования установите функцию трафарета на обнуление буфера трафарета, чтобы он автоматически очищался к моменту добавления следующего изображения. Если объекты нужно придвинуть к наблюдателю или отодвинуть от него, нужно использовать ортографическую проекцию; в подобных случаях для перемещения глубинированного изображения используйте GL_DEPTH_BIAS и команду glPixelTransfer*().
14.19 Многоугольники Вороного
Если взять множество S точек плоскости, многоугольником Вороного (или территорией Диричлета) для произвольной точки A из S будет множество всех точек плоскости, находящихся ближе к точке A, чем к любой другой точке из S. Множество
получившихся точек представляет собой решение многих проблем вычислительной геометрии. Многоугольники Вороного для набора точек показаны на рисунке 14-3.
Рисунок 14-3. Многоугольники Вороного
Если для каждой точки из S вы нарисуете глубинированный конус с вершиной в этой точке и цветом, отличающимся от цвета каждой из точек в S, территория Диричлета буфет нарисована этим цветом. Простейший путь сделать это заключается в
предварительном расчете глубины конуса в виде изображения и использование этого изображения в качестве величин глубины, как описано в предыдущем разделе. Однако для рисования в буфер кадра изображение (в отличие от случая со сферами) вам не требуется. Пока вы рисуете в буфер глубины, используйте буфер трафарета для запоминания пикселей, на которых нужно рисовать: сначала очистите буфер, а затем записывайте ненулевые значения в тех местах, где тест глубины прошел. Чтобы нарисовать границы территорий Диричлета нарисуйте полигон размером со все окно, но разрешите рисование только там, где величины трафарета имеют ненулевое значение.
Вы можете сделать то же самое значительно проще, визуализировав конусы одного и того же цвета с простым буфером глубины, но хорошие конусы потребуют тысяч полигонов. Техника, описанная в этом разделе, позволяет визуализировать изображения высокого качества значительно быстрее.
14.20 «Жизнь» в буфере трафарета
«Игра в жизнь» («Game of Life») изобретенная Джоном Конвейем, проходит на прямоугольной сетке, где каждая клетка может быть «жива» или «мертва». Чтобы вычислить следующее поколение из текущего, сосчитайте количество живых соседей для каждой клетки (соседями каждой клетки являются 8 смежных клеток). Клетка жива в поколении n+1, если она была жива в поколении n и имеет двух или трех живых соседей. Клетка также жива в поколении n+1, если она была мертва в поколении n и имеет точно живых соседей. Во всех остальных случаях клетка мертва в поколении n+1. В зависимости от начальной конфигурации эта игра генерирует потрясающе интересные рисунки. Рисунок 14-4 демонстрирует 6 поколений игры.
Рисунок 14-4. 6 поколений из «Игры в жизнь»
Одним из способов создания этой игры с помощью OpenGL является использование многопроходного алгоритма. Данные содержатся в цветовом буфере – по одному пикселю на клетку игровой сетки. Предположим, что цвет фона – черный (все нули), и, что цвет всех живых клеток – не черный (отличный от нуля). Очистите буферы глубины и трафарета в нули, установите маску записи буфера глубины в 0, а функцию сравнения так, чтобы тест глубины проходили пиксели, имеющие значение глубины не равное хранимому в буфере. Для итерирования считайте изображение с экрана, разрешите запись в буфер глубины и установите функцию сравнения, чтобы она увеличивала значение в буфере трафарета везде, где проходит тест глубины, а иначе оставляла содержимое буфера трафарета неизменным. Запретите рисование в цветовой буфер.
Далее, нарисуйте изображение 8 раз, смещая его на один пиксель в каждом вертикальном, горизонтальном и диагональном направлениях. Когда вы закончите, буфер трафарета будет содержать числа, равные количеству живых соседей для каждого пикселя. Разрешите рисование в цветовой буфер, установите текущий цвет равным цвету живых клеток, а функцию трафарета установите таким образом, чтобы рисование происходило только там, где значение трафарета равно 3 (три живых соседа). Кроме того, если рисование происходит, уменьшайте величину в буфере трафарета. Затем нарисуйте прямоугольник, покрывающий все изображение – это окрасит каждую клетку, имеющую точно 3 живых соседа «живым» цветом.
На данный момент буфер трафарета содержит числа 0, 1, 2, 4, 5, 6, 7 и 8. Клетки со значениями трафарета 0, 1, 4, 5, 6, 7 и 8 должны быть очищены «мертвым» цветом. Установите функцию трафарета таким образом, чтобы рисование происходило только там, где значение трафарета не равно 2, а операцию трафарета – на обнуление
В дополнение к основным командам, позволяющим получить простые значения переменных состояния (таким как glGetIntegerv() или glIsEnabled()), существуют более специализированные команды для возврата более сложных значений. Ниже перечислены прототипы этих команд.
Для выяснения того, когда вы должны использовать эти команды и с какими константами, воспользуйтесь таблицами в следующем разделе.
void glGetClipPlane (GLenum plane, GLdouble *equation);
void glGetColorTable (GLenum target, GLenum pname, GLenum type, GLvoid *table);
void glGetColorTableParameter{if}v (GLenum target, GLenum pname, TYPE *params);
void glGetConvolutionFilter (GLenum target, GLenum format, GLenum type, GLvoid *image);
void glGetConvolutionParameter{if}v (GLenum target, GLenum pname, TYPE *params);
GLenum glGetError (void);
void glGetHistogram (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
void glGetHistogramParameter{if}v (GLenum target, GLenum pname, TYPE *params);
void glGetLight{if}v (GLenum light, GLenum pname, TYPE *params); void glGetMap{ifd}v (GLenum target, GLenum query, TYPE *v);
void glGetMaterial{if}v (GLenum face, GLenum pname, TYPE *params); void glGetMinmax (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
void glGetMinmaxParameter{if}v (GLenum target, GLenum pname, TYPE **params);
void glGetPixelMap {f ui us}v (GLenum map, TYPE *values); void glGetPolygonStipple (GLubyte *mask);
void glGetSeparableFilter (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span);
const GLubyte* glGetString (GLenum name);
void glGetTexEnv{if}v (GLenum target, GLenum pname, TYPE *params); void glGetTexGen{ifd}v (GLenum coord, GLenum pname, TYPE *params); void glGetTexImage (GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
void glGetTexLevelParameter{if}v (GLenum target, GLint level, GLenum pname, TYPE *params);
void glGetTexParameter{if}v (GLenum target, GLenum pname, TYPE *params);
GLboolean glIsList (GLuint list); GLboolean glIsTexture (GLuint texObject);
void gluGetNurbsProperty (GLUnurbsObj *nobj, GLenum property, GLfloat *value);
const GLubyte* gluGetString (GLenum name);
void gluGetTessProperty (GLUtesselator *tess, GLenum which, GLdouble *data);
Переменные состояния OpenGL
Следующие страницы содержат таблицы, в которых перечислены имена переменных состояния. Для каждой переменной в таблице есть описание, группа атрибутов, к которой она принадлежит, начальное или минимальное значение, а также рекомендуемая для получения значения переменной команда glGet*(). Для переменных состояния, значения которых могут быть получены с помощью команд glGetBooleanv(), glGetIntegerv(), glGetFloatv() или glDoublev() в таблице приводится только одна из этих команд – та, которая более всего подходит в соответствии с типом возвращаемого значения. (Некоторые переменные, связанные с вершинными массивами могут опрашиваться только с помощью glGetPointerv().) Эти
переменные состояния не могут быть получены с помощью команды glIsEnabled(). Однако переменные, для которых glIsEnabled() указано в качестве команды опроса, могут быть получены так же и с помощью команды glBooleanv(), glGetIntegerv(), glGetFloatv() или glDoublev(). Переменные состояния, для которых в таблице указана любая другая опросная команда, могут быть получены только с помощью этой команды.
Замечание: Когда вы опрашиваете состояние текстуры, например, GL_TEXTURE_MATRIX, в реализации OpenGL, поддерживающей расширение GL_ARB_multitexture, будут возвращены величины, относящиеся только к активному в данный момент текстурному блоку.
Если в таблице приводится одна или более групп атрибутов, это значит, что переменная состояния относится к этой группе или группам. Если группа атрибутов не указана – переменная не принадлежит ни к одной группе. Для сохранения и восстановления значений всех переменных состояния, относящихся к определенной группе или группам атрибутов, можно использовать команды glPushAttrib(), glPopAttrib(), glPushClientAttrib() и glPopClientAttrib().
Все опрашиваемые переменные состояния имеют начальное значение, однако, для переменных, зависящих от реализации, начальные значения могут не приводиться.
Таблица A-1. Текущие величины и связанные с ними данные
Переменная состояния |
Описание |
Группа |
Начальное |
Опросная |
|
атрибутов |
значение |
команда |
|||
|
|
||||
GL_CURRENT_COLOR |
Текущий цвет |
текущие |
(1,1,1,1) |
glGetIntegerv(), |
|
glGetFloatv() |
|||||
|
|
|
|
||
GL_CURRENT_INDEX |
Текущий цветовой |
текущие |
1 |
glGetIntegerv(), |
|
индекс |
glGetFloatv() |
||||
|
|
|
|||
|
Текущие |
|
|
|
|
GL_CURRENT_TEXTURE_COORDS |
координаты |
текущие |
(0,0,0,1) |
glGetFloatv() |
|
|
текстуры |
|
|
|
|
GL_CURRENT_NORMAL |
Текущая нормаль |
текущие |
(0,0,1) |
glGetFloatv() |
|
GL_CURRENT_RASTER_POSITION |
Текущая позиция |
текущие |
(0,0,0,1) |
glGetFloatv() |
|
растра |
|||||
|
|
|
|
||
GL_CURRENT_RASTER_DISTANCE |
Текущая дистанция |
текущие |
0 |
glGetFloatv() |
|
растра |
|||||
|
|
|
|
||
|
Цвет, |
|
|
|
|
GL_CURRENT_RASTER_COLOR |
ассоциированный с |
текущие |
(1,1,1,1) |
glGetIntegerv(), |
|
текущей позицией |
glGetFloatv() |
||||
|
|
|
|||
|
растра |
|
|
|
|
|
Цветовой индекс, |
|
|
|
|
GL_CURRENT_RASTER_INDEX |
ассоциированный с |
текущие |
1 |
glGetIntegerv(), |
|
текущей позицией |
glGetFloatv() |
||||
|
|
|
|||
|
растра |
|
|
|
|
|
Координаты |
|
|
|
|
|
текстуры, |
|
|
|
|
GL_CURRENT_RASTER_TEXTURE_COORDS ассоциированные с |
текущие |
(0,0,0,1) |
glGetFloatv() |
||
|
текущей позицией |
|
|
|
|
|
растра |
|
|
|
|
GL_CURRENT_RASTER_POSITION_VALID |
Бит допустимости |
текущие |
GL_TRUE |
glGetBooleanv() |
|
позиции растра |
|||||
|
|
|
|
||
GL_EDGE_FLAG |
Флаг ребра (флаг |
текущие |
GL_TRUE |
glGetBooleanv() |
|
границы) |
|||||
|
|
|
|
||
|
|
|
|
||
Таблица A-2. Вершинные массивы |
|
|
|
||
|
|
|
|
|
|
Переменная состояния |
Описание |
Группа |
Начальное |
Опросная |
|
атрибутов |
значение |
команда |
|||
|
|
||||
GL_VERTEX_ARRAY |
Активность массива |
вершинные |
GL_FALSE |
glIsEnabled() |
|
координат вершин |
массивы |
||||
|
|
|
|||
|
|
|
|
|
GL_PROJECTION_MATRIX |
Стек проекционных |
- |
Единичная |
glGetFloatv() |
|
матриц |
|||||
|
|
|
|
||
GL_TEXTURE_MATRIX |
Стек текстурных |
- |
Единичная |
glGetFloatv() |
|
матриц |
|||||
|
|
|
|
||
|
Начальная точка и |
|
|
|
|
GL_VIEWPORT |
размеры порта |
порт просмотра |
- |
glGetIntegerv() |
|
|
просмотра |
|
|
|
|
GL_DEPTH_RANGE |
Разброс глубин |
порт просмотра |
0, 1 |
glGetFloatv() |
|
GL_COLOR_STACK_DEPTH |
Указатель стека |
- |
1 |
glGetIntegerv() |
|
цветовых матриц |
|||||
|
|
|
|
||
GL_MODELVIEW_STACK_DEPTH |
Указатель стека |
- |
1 |
glGetIntegerv() |
|
видовых матриц |
|||||
|
Указатель стека |
|
|
|
|
GL_PROJECTION_STACK_DEPTH |
проекционных |
- |
1 |
glGetIntegerv() |
|
|
матриц |
|
|
|
|
GL_TEXTURE_STACK_DEPTH |
Указатель стека |
- |
1 |
glGetIntegerv() |
|
текстурных матриц |
|||||
|
|
|
|
||
GL_MATRIX_MODE |
Текущий матричный |
трансформация |
GL_MODELVIEW |
glGetIntegerv() |
|
режим |
|||||
|
|
|
|
||
|
Активность режима |
трансформация/ |
|
|
|
GL_NORMALIZE |
нормализации |
GL_FALSE |
glIsEnabled() |
||
включенные |
|||||
|
нормалей |
|
|
||
|
|
|
|
||
|
Активность режима |
трансформация/ |
|
|
|
GL_RESCALE_NORMAL |
масштабирования |
GL_FALSE |
glIsEnabled() |
||
включенные |
|||||
|
нормалей |
|
|
||
|
|
|
|
||
|
Коэффициенты i-ой |
|
|
|
|
GL_GET_CLIP_PLANEi |
пользовательской |
трансформация |
(0,0,0,0) |
glGetClipPlane() |
|
отсекающей |
|||||
|
|
|
|
||
|
плоскости |
|
|
|
|
|
Активность i-ой |
|
|
|
|
GL_GET_CLIP_PLANEi |
пользовательской |
трансформация/ |
GL_FALSE |
glIsEnabled() |
|
отсекающей |
включенные |
||||
|
|
|
|||
|
плоскости |
|
|
|
|
|
|
|
|
|
Таблица A-4. Цвет
Переменная |
Описание |
Группа |
Начальное |
Опросная |
|
состояния |
атрибутов |
значение |
команда |
||
|
|||||
GL_FOG_COLOR |
Цвет тумана |
туман |
(0,0,0,0) |
glGetFloatv() |
|
GL_FOG_INDEX |
Цветовой индекс тумана |
туман |
0 |
glGetFloatv() |
|
GL_FOG_DENSITY |
Плотность |
туман |
1.0 |
glGetFloatv() |
|
экспоненциальная тумана |
|||||
|
|
|
|
||
GL_FOG_START |
Начало линейного тумана |
туман |
0.0 |
glGetFloatv() |
|
GL_FOG_END |
Конец линейного тумана |
туман |
1.0 |
glGetFloatv() |
|
GL_FOG_MODE |
Режим тумана |
туман |
GL_EXP |
glGetIntegerv() |
|
GL_FOG |
Активность тумана |
туман/ |
GL_FALSE |
glIsEnabled() |
|
включенные |
|||||
|
|
|
|
||
GL_SHADE_MODEL |
Режим закраски |
освещение |
GL_SMOOTH |
glGetIntegerv() |
|
|
|
|
|
|
Таблица A-5. Освещение
Переменная состояния |
Описание |
Группа |
Начальное |
Опросная |
|
атрибутов |
значение |
команда |
|||
|
|
||||
|
Активность |
освещение/ |
|
|
|
GL_LIGHTING |
расчета |
GL_FALSE |
glIsEnabled() |
||
включенные |
|||||
|
освещенности |
|
|
||
|
|
|
|
||
GL_COLOR_MATERIAL |
Активность режима |
освещение |
GL_FALSE |
glIsEnabled() |
|
|
цвета материала |
|
|
|
|
|
Параметр, |
|
|
|
|
|
совпадающий с |
|
GL_AMBIENT_ |
|
|
GL_COLOR_MATERIAL_PARAMETER |
текущим цветом |
освещение |
glGetIntegerv() |
||
AND_DIFFUSE |
|||||
|
для режима цвета |
|
|
||
|
|
|
|
||
|
материала |
|
|
|
|
|
|
|
|
|