Главная > Документ


Преобразования объектов

В OpenGL используются как основные три системы координат: левосторонняя, правосторонняя и оконная. Первые две системы являются трехмерными и отличаются друг от друга направлением оси z: в правосторонней она направлена на наблюдателя, в левосторонней – в глубину экрана. Ось x направлена вправо относительно наблюдателя, ось y – вверх.

Л

y

евосторонняя система используется для задания значений параметрам команды gluPerspective(), glOrtho(), которые будут рассмотрены в пункте . Правосторонняя система координат используется во всех остальных случаях. Отображение трехмерной информации происходит в двумерную оконную систему координат.

Рис. 3 Системы координат в OpenGL



Строго говоря, OpenGL позволяет путем манипуляций с матрицами моделировать как правую, так и левую систему координат. Но на данном этапе лучше пойти простым путем и запомнить: основной системой координат OpenGL является правосторонняя система.

Работа с матрицами

Для задания различных преобразований объектов сцены в OpenGL используются операции над матрицами, при этом различают три типа матриц: модельно-видовая, матрица проекций и матрица текстуры. Все они имеют размер 4x4. Видовая матрица определяет преобразования объекта в мировых координатах, такие как параллельный перенос, изменение масштаба и поворот. Матрица проекций определяет, как будут проецироваться трехмерные объекты на плоскость экрана (в оконные координаты), а матрица текстуры определяет наложение текстуры на объект.

Умножение координат на матрицы происходит в момент вызова соответствующей команды OpenGL, определяющей координату (как правило, это команда glVertex*)

Для того чтобы выбрать, какую матрицу надо изменить, используется команда:

void glMatrixMode (GLenum mode)

вызов которой со значением параметра mode равным GL_MODELVIEW, GL_PROJECTION, или GL_TEXTURE включает режим работы с модельно-видовой матрицей, матрицей проекций, или матрицей текстуры соответственно. Для вызова команд, задающих матрицы того или иного типа, необходимо сначала установить соответствующий режим.

Для определения элементов матрицы текущего типа вызывается команда

void glLoadMatrix[f d] (GLtype *m)

где m указывает на массив из 16 элементов типа float или double в соответствии с названием команды, при этом сначала в нем должен быть записан первый столбец матрицы, затем второй, третий и четвертый. Еще раз обратим внимание: в массиве mматрица записана по столбцам.

Команда

void glLoadIdentity (void)

заменяет текущую матрицу на единичную.

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

void glPushMatrix (void)

void glPopMatrix (void)

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

Для умножения текущей матрицы на другую матрицу используется команда

void glMultMatrix[f d] (GLtype *m)

где параметр m должен задавать матрицу размером 4x4. Если обозначить текущую матрицу за М, передаваемую матрицу за T, то в результате выполнения команды glMultMatrix текущей становится матрица M * T. Однако обычно для изменения матрицы того или иного типа удобно использовать специальные команды, которые по значениям своих параметров создают нужную матрицу и умножают ее на текущую.

В целом, для отображения трехмерных объектов сцены в окно приложения используется последовательность, показанная на рисунке.

Мировые координаты


Модельно-видовое
преобразование

Модельно-видовая матрица


Рис. 4. Преобразования координат в OpenGL

Видовые координаты


Преобразование проекции и нормализация

Матрица
проекции


Нормализованные координаты

Параметры области вывода (glViewport)


Преобразование к области вывода


Оконные координаты


Запомните: все преобразования объектов и камеры в OpenGL производятся с помощью умножения векторов координат на матрицы. Причем умножение происходит на текущую матрицу в момент определения координаты командой glVertex* и некоторыми другими.

Модельно-Видовые преобразования

К модельно-видовым преобразованиям будем относить перенос, поворот и изменение масштаба вдоль координатных осей. Для проведения этих операций достаточно умножить на соответствующую матрицу каждую вершину объекта и получить измененные координаты этой вершины:

(x’, y’, z’, 1)T = M * (x, y, z, 1)T

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

void glTranslate[f d] (GLtype x, GLtype y, GLtype z)

void glRotate[f d] (GLtype angle, GLtype x, GLtype y,
GLtype z)

void glScale[f d] (GLtype x, GLtype y, GLtype z)

glTranlsate*() производит перенос объекта, прибавляя к координатам его вершин значения своих параметров.

glRotate*() производит поворот объекта против часовой стрелки на угол angle (измеряется в градусах) вокруг вектора (x,y,z).

glScale*() производит масштабирование объекта (сжатие или растяжение) вдоль вектора (x,y,z), умножая соответствующие координаты его вершин на значения своих параметров.

Все эти преобразования изменяют текущую матрицу, а поэтому применяются к примитивам, которые определяются позже. В случае, если надо, например, повернуть один объект сцены, а другой оставить неподвижным, удобно сначала сохранить текущую видовую матрицу в стеке командой glPushMatrix(), затем вызвать glRotate*() с нужными параметрами, описать примитивы, из которых состоит этот объект, а затем восстановить текущую матрицу командой glPopMatrix().

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

void gluLookAt(GLdouble eyex, GLdouble eyey,
GLdouble eyez, GLdouble centerx,
GLdouble centery, GLdouble centerz,
GLdouble upx, GLdouble upy,
GLdouble upz)

где точка (eyex,eyey,eyez) определяет точку наблюдения, (centerx, centery, centerz) задает центр сцены, который будет проектироваться в центр области вывода, а вектор (upx,upy,upz) задает положительное направление оси у, определяя поворот камеры. Если, например, камеру не надо поворачивать, то задается значение (0,1,0), а со значением (0,-1,0) сцена будет перевернута.

Строго говоря, эта команда совершает перенос и поворот объектов сцены, но в таком виде задавать параметры бывает удобнее. Следует отметить, что вызывать команду gluLookAt() имеет смысл перед определением преобразований объектов, когда модельно-видовая матрица равна единичной.

Запомните: В общем случае матричные преобразования в OpenGL нужно записывать в обратном порядке. Например, если вы хотите сначала повернуть объект, а затем передвинуть его, сначала вызовите команду glTranslate(), а только потом – glRotate(). Ну а после этого определяйте сам объект.

Проекции

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

void glOrtho(GLdouble left, GLdouble right,
GLdouble bottom, GLdouble top,
GLdouble near, GLdouble far)

void gluOrtho2D (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top)

Рис. 5 Ортографическая проекция



Первая команда создает матрицу проекции в усеченный объем видимости (параллелепипед видимости) в левосторонней системе координат. Параметры команды задают точки (left, bottom, znear) и (right, top, zfar), которые отвечают левому нижнему и правому верхнему углам окна вывода. Параметры near и far задают расстояние до ближней и дальней плоскостей отсечения по удалению от точки (0,0,0) и могут быть отрицательными.

Во второй команде, в отличие от первой, значения near и far устанавливаются равными –1 и 1 соответственно. Это удобно, если OpenGL используется для рисования двумерных объектов. В этом случае положение вершин можно задавать, используя команды glVertex2*()

Перспективная проекция определяется командой

void gluPerspective (GLdouble angley, GLdouble aspect,
GLdouble znear, GLdouble zfar)

которая задает усеченный конус видимости в левосторонней системе координат. Параметр angley определяет угол видимости в градусах по оси у и должен находиться в диапазоне от 0 до 180. Угол видимости вдоль оси x задается параметром aspect, который обычно задается как отношение сторон области вывода (как правило, размеров окна) Параметры zfar и znear задают расстояние от наблюдателя до плоскостей отсечения по глубине и должны быть положительными. Чем больше отношение zfar/znear, тем хуже в буфере глубины будут различаться расположенные рядом поверхности, так как по умолчанию в него будет записываться ‘сжатая’ глубина в диапазоне от 0 до 1 (см. п. .).

Рис. 6 Перспективная проекция



Прежде чем задавать матрицы проекций, не забудьте включить режим работы с нужной матрицей командой glMatrixMode(GL_PROJECTION) исбросить текущую, вызвавglLoadIdentity().

Например:

/* ортографическая проекция */

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

glOrtho(0, w, 0, h, -1.0, 1.0);

Область вывода

После применения матрицы проекций на вход следующего преобразования подаются так называемые усеченные (clipped) координаты. Затем находятся нормализованные координаты вершин по формуле:

(xn, yn, zn)T = (xc/wc , yc/wc, zc/wc)T

Область вывода представляет собой прямоугольник в оконной системе координат, размеры которого задаются командой:

void glViewPort (GLint x, GLint y, GLint width,
GLint height)

Значения всех параметров задаются в пикселах и определяют ширину и высоту области вывода с координатами левого нижнего угла (x,y) в оконной системе координат. Размеры оконной системы координат определяются текущими размерами окна приложения, точка (0,0) находится в левом нижнем углу окна.

Используя параметры команды glViewPort(), OpenGL вычисляет оконные координаты центра области вывода (ox,oy) по формулам ox=x+width/2, oy=y+height/2.

Пусть px=width, py=height, тогда можно найти оконные координаты каждой вершины:

(xw, yw, zw)T = ( (px/2) xn+ ox , (py/2) yn+ oy , [(f-n)/2] zn+(n+f)/2 )T

При этом целые положительные величины n и f задают минимальную и максимальную глубину точки в окне и по умолчанию равны 0 и 1 соответственно. Глубина каждой точки записывается в специальный буфер глубины (z-буфер), который используется для удаления невидимых линий и поверхностей. Установить значения n и f можно вызовом функции

void glDepthRange (GLclampd n, GLclampd f)

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

Модель освещения

В OpenGL используется модель освещения, в соответствии с которой цвет точки определяется несколькими факторами: свойствами материала и текстуры, величиной нормали в этой точке, а также положением источника света и наблюдателя. Для корректного расчета освещенности в точке надо использовать единичные нормали, однако команды типа glScale*(), могут изменять длину нормалей. Чтобы это учитывать, используйте уже упоминавшийся в пункте режим нормализации нормалей, который включается вызовом команды glEnable(GL_NORMALIZE).

Для задания глобальных параметров освещения используются команды

void glLightModel[i f] (GLenum pname, GLenum param)

void glLightModel[i f]v (GLenum pname,
const GLtype *params)

Аргумент pname определяет, какой параметр модели освещения будет настраиваться и может принимать следующие значения:

GL_LIGHT_MODEL_LOCAL_VIEWER параметр param должен быть булевым и задает положение наблюдателя. Если он равен GL_FALSE, то направление обзора считается параллельным оси –z, вне зависимости от положения в видовыx координатах. Если же он равен GL_TRUE, то наблюдатель находится в начале видовой системы координат. Это может улучшить качество освещения, но усложняет его расчет. Значение по умолчанию: GL_FALSE.

GL_LIGHT_MODEL_TWO_SIDE параметр param должен быть булевым и управляет режимом расчета освещенности, как для лицевых, так и для обратных граней. Если он равен GL_FALSE, то освещенность рассчитывается только для лицевых граней. Если же он равен GL_TRUE, расчет проводится и для обратных граней. Значение по умолчанию: GL_FALSE.

GL_LIGHT_MODEL_AMBIENT параметр params должен содержать четыре целых или вещественных числа, которые определяют цвет фонового освещения даже в случае отсутствия определенных источников света. Значение по умолчанию: (0.2, 0.2, 0.2,1.0).

Спецификация материалов

Для задания параметров текущего материала используются команды

void glMaterial[i f] (GLenum face, GLenum pname,
GLtype param)

void glMaterial[i f]v (GLenum face, GLenum pname,
GLtype *params)

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

GL_AMBIENT параметр params должен содержать четыре целых или вещественных значения цветов RGBA, которые определяют рассеянный цвет материала (цвет материала в тени). Значение по умолчанию: (0.2, 0.2, 0.2, 1.0).

GL_DIFFUSE параметр params должен содержать четыре целых или вещественных значения цветов RGBA, которые определяют диффузный цвет материала. Значение по умолчанию: (0.8, 0.8, 0.8, 1.0).

GL_SPECULAR параметр params должен содержать четыре целых или вещественных значения цветов RGBA, которые определяют зеркальный цвет материала. Значение по умолчанию: (0.0, 0.0, 0.0, 1.0).

GL_SHININESS параметр params должен содержать одно целое или вещественное значение в диапазоне от 0 до 128, которое определяет степень зеркального отражения материала. Значение по умолчанию: 0.

GL_EMISSION параметр params должен содержать четыре целых или вещественных значения цветов RGBA, которые определяют интенсивность излучаемого света материала. Значение по умолчанию: (0.0, 0.0, 0.0, 1.0).

GL_AMBIENT_AND_DIFFUSE эквивалентно двум вызовам команды glMaterial*() со значением pname GL_AMBIENT и GL_DIFFUSE и одинаковыми значениями params.

Из этого следует, что вызов команды glMaterial[i f]() возможен только для установки степени зеркального отражения материала (shininess). Команда glMaterial[i f]v() используется для задания остальных параметров.

Параметр face определяет тип граней, для которых задается этот материал и может принимать значения GL_FRONT, GL_BACK или GL_FRONT_AND_BACK.

Если в сцене материалы объектов различаются лишь одним параметром, рекомендуется сначала установить нужный режим, вызвав glEnable() c параметром GL_COLOR_MATERIAL, а затем использовать команду

void glColorMaterial(GLenum face, GLenum pname)

где параметр face имеет аналогичный смысл, а параметр pname может принимать все перечисленные значения. После этого значения выбранного с помощью pname свойства материала для конкретного объекта (или вершины) устанавливаются вызовом команды glColor*(), что позволяет избежать вызовов более ресурсоемкой команды glMaterial*() и повышает эффективность программы. Другие методы оптимизации приведены в п. Error: Reference source not found.

Пример определения свойств материала:

float mat_dif[]={0.8,0.8,0.8};

float mat_amb[] = {0.2, 0.2, 0.2};

float mat_spec[] = {0.6, 0.6, 0.6};

float shininess = 0.7 * 128;

glMaterialfv (GL_FRONT_AND_BACK,GL_AMBIENT, mat_amb);

glMaterialfv (GL_FRONT_AND_BACK,GL_DIFFUSE, mat_dif);

glMaterialfv (GL_FRONT_AND_BACK,GL_SPECULAR, mat_spec);

glMaterialf (GL_FRONT,GL_SHININESS, shininess);

Описание источников света

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

void glLight[i f] (GLenum light, GLenum pname,
GLfloat param)

void glLight[i f] (GLenum light, GLenum pname,
GLfloat *params)

Параметр light однозначно определяет источник света. Он выбирается из набора специальных символических имен вида GL_LIGHTi , где i должно лежать в диапазоне от 0 до константы GL_MAX_LIGHT, которая обычно не превосходит восьми.

Параметры pnameи params имеют смысл, аналогичный команде glMaterial*(). Рассмотрим значения параметра pname:

GL_SPOT_EXPONENT параметр param должен содержать целое или вещественное число от 0 до 128, задающее распределение интенсивности света. Этот параметр описывает уровень сфокусированности источника света. Значение по умолчанию: 0 (рассеянный свет).

GL_SPOT_CUTOFF параметр param должен содержать целое или вещественное число между 0 и 90 или равное 180, которое определяет максимальный угол разброса света. Значение этого параметра есть половина угла в вершине конусовидного светового потока, создаваемого источником. Значение по умолчанию: 180 (рассеянный свет).

GL_AMBIENT параметр params должен содержать четыре целых или вещественных значения цветов RGBA, которые определяют цвет фонового освещения. Значение по умолчанию: (0.0, 0.0, 0.0, 1.0).

GL_DIFFUSE параметр params должен содержать четыре целых или вещественных значения цветов RGBA, которые определяют цвет диффузного освещения. Значение по умолчанию: (1.0, 1.0, 1.0, 1.0) для GL_LIGHT0 и (0.0, 0.0, 0.0, 1.0) для остальных.

GL_SPECULAR параметр params должен содержать четыре целых или вещественных значения цветов RGBA, которые определяют цвет зеркального отражения. Значение по умолчанию: (1.0, 1.0, 1.0, 1.0) для GL_LIGHT0 и (0.0, 0.0, 0.0, 1.0) для остальных.

GL_POSITION параметр params должен содержать четыре целых или вещественных числа, которые определяют положение источника света. Если значение компоненты w равно 0.0, то источник считается бесконечно удаленным и при расчете освещенности учитывается только направление на точку (x,y,z), в противном случае считается, что источник расположен в точке (x,y,z,w). В первом случае ослабления света при удалении от источника не происходит, т.е. источник считается бесконечно удаленным. Значение по умолчанию: (0.0, 0.0, 1.0, 0.0).

GL_SPOT_DIRECTION параметр params должен содержать четыре целых или вещественных числа, которые определяют направление света. Значение по умолчанию: (0.0, 0.0, -1.0, 1.0). Эта характеристика источника имеет смысл, если значение GL_SPOT_CUTOFF отлично от 180 (которое, кстати, задано по умолчанию).

GL_CONSTANT_ATTENUATION,

GL_LINEAR_ATTENUATION,

GL_QUADRATIC_ATTENUATION

параметр params задает значение одного из трех коэффициентов, определяющих ослабление интенсивности света при удалении от источника. Допускаются только неотрицательные значения. Если источник не является направленным (см. GL_POSITION), то ослабление обратно пропорционально сумме:

attconstant+attlinear*d+ attquadratic *d2,

где d – расстояние между источником света и освещаемой им вершиной, attconstant, attlinear и attquadratic равны параметрам, заданным с помощью констант GL_CONSTANT_ATTENUATION, GL_LINEAR_ATTENUATION и GL_QUADRATIC_ATTENUATION соответственно. По умолчанию эти параметры задаются тройкой (1, 0, 0), и фактически ослабления не происходит.

При изменении положения источника света следует учитывать следующий факт: в OpenGL источники света являются объектами, во многом такими же, как многоугольники и точки. На них распространяется основное правило обработки координат в OpenGL – параметры, описывающее положение в пространстве, преобразуются текущей модельно-видовой матрицей в момент формирования объекта, т.е. в момент вызова соответствующих команд OpenGL. Таким образом, формируя источник света одновременно с объектом сцены или камерой, его можно привязать к этому объекту. Или, наоборот, сформировать стационарный источник света, который будет оставаться на месте, пока другие объекты перемещаются.

Общее правило такое:

Если положение источника света задается командой glLight*() перед определением положения виртуальной камеры (например, командой glLookAt()), то будет считаться, что координаты (0,0,0) источника находится в точке наблюдения и, следовательно, положение источника света определяется относительно положения наблюдателя.

Если положение устанавливается между определением положения камеры и преобразованиями модельно-видовой матрицы объекта, то оно фиксируется, т.е. в этом случае положение источника света задается в мировых координатах.

Для использования освещения сначала надо установить соответствующий режим вызовом команды glEnable(GL_LIGHTNING), а затем включить нужный источник командой glEnable(GL_LIGHTi).

Еще раз обратим внимание на то, что при выключенном освещении цвет вершины равен текущему цвету, который задается командами glColor*(). При включенном освещении цвет вершины вычисляется исходя из информации о материале, нормалях и источниках света.

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

Текстурирование

Под текстурой будем понимать некоторое изображение, которое надо определенным образом нанести на объект, например, для придания иллюзии рельефности поверхности.

Наложение текстуры на поверхность объектов сцены повышает ее реалистичность, однако при этом надо учитывать, что этот процесс требует вычислительных затрат, особенно если OpenGL не поддерживается аппаратно.

Для работы с текстурой следует выполнить следующую последовательность действий:

  1. выбрать изображение и преобразовать его к нужному формату;

  2. передать изображение в OpenGL;

  3. определить, как текстура будет наноситься на объект и как она будет с ним взаимодействовать;

  4. связать текстуру с объектом.

Подготовка текстуры

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

Считывание графических данных из файла и их преобразование можно проводить вручную. Можно также воспользоваться функцией, входящей в состав библиотеки GLAUX (для ее использования надо дополнительно подключить glaux.lib), которая сама проводит необходимые операции. Это функция

AUX_RGBImageRec* auxDIBImageLoad (const char *file)

где file – название файла с расширением *.bmp или *.dib. Функция возвращает указатель на область памяти, где хранятся преобразованные данные.

При создании образа текстуры в памяти следует учитывать следующие требования:

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

void gluScaleImage(GLenum format, GLint widthin,
GL heightin, GLenum typein,
const void *datain,
GLint widthout,
GLint heightout, GLenum typeout,
void *dataout)

В качестве значения параметра format обычно используется значение GL_RGB или GL_RGBA, определяющее формат хранения информации. Параметры widthin, heightin, widhtout, heightout определяют размеры входного и выходного изображений, а с помощью typein и typeout задается тип элементов массивов, расположенных по адресам datain и dataout. Как и обычно, это может быть тип GL_UNSIGNED_BYTE, GL_SHORT, GL_INT и так далее. Результат своей работы функция заносит в область памяти, на которую указывает параметр dataout.

Во-вторых, надо предусмотреть случай, когда объект после растеризации оказывается по размерам значительно меньше наносимой на него текстуры. Чем меньше объект, тем меньше должна быть наносимая на него текстура и поэтому вводится понятие уровней детализации текстуры. (mipmap) Каждый уровень детализации задает некоторое изображение, которое является, как правило, уменьшенной в два раза копией оригинала. Такой подход позволяет улучшить качество нанесения текстуры на объект. Например, для изображения размером 2mx2n можно построить max(m,n)+1 уменьшенных изображений, соответствующих различным уровням детализации.

Эти два этапа создания образа текстуры во внутренней памяти OpenGL можно провести с помощью команды

void gluBuild2DMipmaps(GLenum target, GLint components,
GLint width, GLint height,
GLenum format, GLenum type,
const void *data)

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

GL_LUMINANCE одна компонента – яркость. (текстура будет монохромной)

GL_RGB красный, синий, зеленый

GL_RGBA все компоненты.

Параметры width, height, data определяют размеры и расположение текстуры соответственно, а format и type имеют аналогичный смысл, что и в команде gluScaleImage().

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

В OpenGL допускается использование одномерных текстур, то есть размера 1xN, однако, это всегда надо указывать, задавая в качестве значения target константу GL_TEXTURE_1D. Полезность одномерных текстур сомнительна, поэтому не будем останавливаться на этом подробно.

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

void glGenTextures(GLsizei n, GLuint* textures)

надо создать n идентификаторов текстур, которые будут записаны в массив textures. Перед началом определения свойств очередной текстуры следует сделать ее текущей («привязать» текстуру), вызвав команду

void glBindTexture(GLenum target, GLuint texture)

где target может принимать значения GL_TEXTURE_1D или GL_TEXTURE_2D, а параметр texture должен быть равен идентификатору той текстуры, к которой будут относиться последующие команды. Для того, чтобы в процессе рисования сделать текущей текстуру с некоторым идентификатором, достаточно опять вызвать команду glBindTexture() c соответствующим значением target и texture. Таким образом, команда glBindTexture() включает режим создания текстуры с идентификатором texture, если такая текстура еще не создана, либо режим ее использования, то есть делает эту текстуру текущей.

Так как не всякая аппаратура может оперировать текстурами большого размера, целесообразно ограничить размеры текстуры до 256x256 или 512x512 пикселей. Отметим, что использование небольших текстур повышает эффективность программы.

Наложение текстуры на объекты

При наложении текстуры, как уже упоминалось, надо учитывать случай, когда размеры текстуры отличаются от оконных размеров объекта, на который она накладывается. При этом возможно как растяжение, так и сжатие изображения, и то, как будут проводиться эти преобразования, может серьезно повлиять на качество построенного изображения. Для определения положения точки на текстуре используется параметрическая система координат (s,t), причем значения s и t находятся в отрезке [0,1] (см. рисунок)

Рис. 7 Текстурные координаты




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

void glTexParameter[i f] (GLenum target, GLenum pname,
GLenum param)

void glTexParameter[i f]v (GLenum target, GLenum pname,
Glenum* params)

При этом target может принимать значения GL_TEXTURE_1D или GL_TEXTURE_2D, pname определяет, какое свойство будем менять, а с помощью param или params устанавливается новое значение. Возможные значения pname:

GL_TEXTURE_MIN_FILTER параметр param определяет функцию, которая будет использоваться для сжатия текстуры. При значении GL_NEAREST будет использоваться один (ближайший), а при значении GL_LINEAR четыре ближайших элемента текстуры. Значение по умолчанию:GL_LINEAR.

GL_TEXTURE_MAG_FILTER параметр param определяет функцию, которая будет использоваться для увеличения (растяжения) текстуры. При значении GL_NEAREST будет использоваться один (ближайший), а при значении GL_LINEAR четыре ближайших элемента текстуры. Значение по умолчанию:GL_LINEAR.

GL_TEXTURE_WRAP_S параметр param устанавливает значение координаты s, если оно не входит в отрезок [0,1]. При значении GL_ REPEAT целая часть s отбрасывается, и в результате изображение размножается по поверхности. При значении GL_CLAMP используются краевые значения: 0 или 1, что удобно использовать, если на объект накладывается один образ. Значение по умолчанию: GL_REPEAT.

GL_TEXTURE_WRAP_T аналогично предыдущему значению, только для координаты t.

Использование режима GL_NEAREST повышает скорость наложения текстуры, однако при этом снижается качество, так как в отличие от GL_LINEAR интерполяция не производится.

Для того чтобы определить, как текстура будет взаимодействовать с материалом, из которого сделан объект, используются команды

void glTexEnv[i f] (GLenum target, GLenum pname,
GLtype param)

void glTexEnv[i f]v (GLenum target, GLenum pname,
GLtype *params)

Параметр target должен быть равен GL_TEXTURE_ENV, а в качестве pname рассмотрим только одно значение GL_TEXTURE_ENV_MODE, которое наиболее часто применяется.

Наиболее часто используемые значения параметра param:

GL_MODULATE конечный цвет находится как произведение цвета точки на поверхности и цвета соответствующей ей точки на текстуре.

GL_REPLACE в качестве конечного цвета используется цвет точки на текстуре.

Текстурные координаты

Перед нанесением текстуры на объект необходимо установить соответствие между точками на поверхности объекта и на самой текстуре. Задавать это соответствие можно двумя методами: отдельно для каждой вершины или сразу для всех вершин, задав параметры специальной функции отображения.

Первый метод реализуется с помощью команд

void glTexCoord[1 2 3 4][s i f d] (type coord)

void glTexCoord[1 2 3 4][s i f d]v (type *coord)

Чаще всего используется команды вида glTexCoord2*(types, typet), задающие текущие координаты текстуры. Понятие текущих координат текстуры аналогично понятиям текущего цвета и текущей нормали, и является атрибутом вершины. Однако даже для куба нахождение соответствующих координат текстуры является довольно трудоемким занятием, поэтому в библиотеке GLU помимо команд, проводящих построение таких примитивов, как сфера, цилиндр и диск, предусмотрено также наложение на них текстур. Для этого достаточно вызвать команду

void gluQuadricTexture (GLUquadricObj* quadObject, GLboolean textureCoords)

с параметром textureCoords равным GL_TRUE, и тогда текущая текстура будет автоматически накладываться на примитив.

Второй метод реализуется с помощью команд

void glTexGen[i f d] (GLenum coord, GLenum pname,
GLtype param)

void glTexGen[i f d]v (GLenum coord, GLenum pname,
const GLtype *params)

Параметр coord определяет, для какой координаты задается формула, и может принимать значение GL_S,GL_T; pname может быть равен одному из следующих значений:

GL_TEXTURE_GEN_MODE определяет функцию для наложения текстуры.

В этом случае аргумент param принимает значения:

GL_OBJECT_LINEAR значение соответствующей текстурной координаты определяется расстоянием до плоскости, задаваемой с помощью значения pname GL_OBJECT_PLANE (см. ниже). Формула выглядит следующим образом: g=x*xp+y*yp+z*zp+w*wp, где g–соответвующая текстурная координата (s или p), x, y, z, w – координаты соответствующей точки. xp, yp, zp, wp – коэффициенты уравнения плоскости. В формуле используются координаты объекта.

GL_EYE_LINEAR аналогично предыдущему значению, только в формуле используются видовые координаты. Т.е. координаты текстуры объекта в этом случае зависят от положения этого объекта.

GL_SPHERE_MAP позволяет эмулировать отражение от поверхности объекта. Текстура как бы ";оборачивается"; вокруг объекта. Для данного метода используются видовые координаты и необходимо задание нормалей.

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

GL_EYE_PLANE аналогично предыдущему значению. Позволяет задать плоскость для режима GL_EYE_LINEAR

Для установки автоматического режима задания текстурных координат необходимо вызвать команду glEnable с параметром GL_TEXTURE_GEN_S или GL_TEXTURE_GEN_P.

Пример:

Рассмотрим, как можно задать зеркальную текстуру. При таком наложении текстуры изображение будет как бы отражаться от поверхности объекта, вызывая интересный оптический эффект. Для этого сначала надо создать два целочисленных массива коэффициентов s_coeffs и t_coeffs со значениями (1,0,0,1) и (0,1,0,1) соответственно, а затем вызвать команды:

glEnable (GL_TEXTURE_GEN_S);

glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);

glTexGendv (GL_S, GL_EYE_PLANE, s_coeffs);

и такие же команды для координаты t с соответствующими изменениями.

Смешивание изображений. Прозрачность

Разнообразные прозрачные объекты – стекла, прозрачная посуда и т.д. часто встречаются в реальности, поэтому важно уметь создавать такие объекты в интерактивной графике. 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,Bdd)

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*(), но и это в общем случае нетривиально.

Создание приложения в среде Borland C++ 5.02

Вначале необходимо обеспечить наличие файлов glut.h, glut32.lib, glut32.dll в каталогах BorlandC\Include\Gl, BorlandC\Lib, Windows\System соответственно. Также в этих каталогах надо проверить наличие файлов gl.h, glu.h, opengl32.lib, glu32.lib, opengl32.dll, glu32.dll, которые обычно входят в состав BorlandC++ и Windows. При этом надо учитывать, что версии Microsoft файлов opengl32.lib, glu32.lib, glut32.lib для Borland C++ не подходят, и следует использовать только совместимые версии. Чтобы создать такие версии, надо использовать стандартную программу ‘implib’, которая находится в каталоге BorlandC\Bin. Для этого надо выполнить команды вида

implib BorlandC\Lib\filename.lib filename.dll

для перечисленных файлов, которые создают нужный *.lib файл из соответствующего *.dll файла. Кроме того, надо отметить, что компилятор BorlandC не может по неизвестным причинам использовать файл glaux.lib, входящий в состав BorlandC++5.02, при компиляции приложения, использующего библиотеку GLAUX, поэтому возможно от этой библиотеки придется отказаться. Для создания приложения надо выполнить следующие действия:

  • Создание проекта: для этого надо выбрать Project->New Project и заполнить поля в окне Target Expert следующим образом: в поле Platform выбрать Win32, в поле Taget Model выбрать Сonsole, нажать Advanced и отменить выбор пунктов ‘ *.rc ‘ и ‘ *.def ‘.

  • Подключить к проекту библиотеки OpenGL. Для этого надо выбрать в окне проекта название исполняемого файла проекта (*.exe) и, нажав правую кнопку мыши, выбрать в контекстном меню пункт Add node. Затем надо определить положение файлов opengl32.lib, glu32.lib, glut32.lib.

  • Для компиляции выбрать Project->Build All, для выполнения – Debug->Run.

Создание приложения в среде MS Visual C++ 6.0

Перед началом работы необходимо скопировать файлы glut.h, glut32.lib glut32.dll в каталоги MSVC\Include\Gl, MSVC\Lib, Windows\System соответственно. Также в этих каталогах надо проверить наличие файлов gl.h, glu.h, opengl32.lib, glu32.lib, opengl32.dll, glu32.dll, которые обычно входят в состав Visual C++ и Windows. При использовании команд из библиотеки GLAUX к перечисленным файлам надо добавить glaux.h, glaux.lib.

Для создания приложения надо выполнить следующие действия:

  • Создание проекта: для этого надо выбрать File->New->Projects->Win32 Console Application, набрать имя проекта, OK.

  • В появившемся окне выбрать ‘An empty project’, Finish,OK.

  • Текст программы можно либо разместить в созданном текстовом файле (выбрав File->New->Files->Text File), либо добавиьб файл с расширением *.c или *.cpp в проект (выбрав Project->Add To Project->Files).

  • Подключить к проекту библиотеки OpenGL. Для этого надо выбрать Project->Settings->Link и в поле Object/library modules набрать названия нужных библиотек: opengl32.lib, glu32.lib, glut32.lib и, если надо, glaux.lib.

  • Для компиляции выбрать Build->Build program.exe, для выполнения – Build->Execute program.exe.

  • Чтобы при запуске не появлялось текстовое окно, надо выбрать Project->Settings->Link и в поле Project Options вместо ‘subsystem:console’ набрать ‘subsystem:windows’, и набрать там же строку ‘/entry:mainCRTStartup’

  • Когда программа готова, рекомендуется перекомпилировать ее в режиме ‘Release’ для оптимизации по быстродействию и объему. Для этого сначала надо выбрать Build->Set Active Configuration… и отметить ‘…-Win32 Release’, а затем заново подключить необходимые библиотеки.



Скачать документ

Похожие документы:

  1. Содержание введение 4 глава 1 основы opengl 6 1 1 основные возможности 6

    Контрольные вопросы
    ... , необходимых для написания интерактивных графических приложений. НасегодняшнийденьграфическаясистемаOpenGLподдерживаетсябольшинствомпроизводителейаппаратных и программныхплатформ. Эта система доступна тем, кто работает ...
  2. МАТЕМАТИКИ И КИБЕРНЕТИКИ ЛАБОРАТОРИЯ КОМПЬЮТЕРНОЙ ГРАФИКИ И МУЛЬТИМЕДИА

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

    Контрольные вопросы
    ... , необходимых для написания интерактивных графических приложений. НасегодняшнийденьграфическаясистемаOpenGLподдерживаетсябольшинствомпроизводителейаппаратных и программныхплатформ. Эта система доступна тем, кто работает ...
  4. Численные решения и инженерные подходы в проектировании и построении вычислительных экспериментов в гидромеханике УДК 519 67

    Документ
    ... , необходимых для написания интерактивных графических приложений. НасегодняшнийденьграфическаясистемаOpenGLподдерживаетсябольшинствомпроизводителейаппаратных и программныхплатформ. Эта система доступна тем, кто работает ...
  5. Численные решения и инженерные подходы в проектировании и построении вычислительных экспериментов в гидромеханике УДК 519 67

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

Другие похожие документы..