Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Операторные скобки glBegin / glEnd



 

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

 

void glBegin (GLenum mode);

void glEnd (void);

 

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

· GL_POINTS каждая вершина задает координаты некоторой точки.

· GL_LINES каждая отдельная пара вершин определяет отрезок; если задано нечетное число вершин, то последняя вершина игнорируется.

· GL_LINE_STRIP каждая следующая вершина задает отрезок вместе с предыдущей.

· GL_LINE_LOOP отличие от предыдущего примитива только в том, что последний отрезок определяется последней и первой вершиной, образуя замкнутую ломаную линию.

· GL_TRIANGLES каждые отдельные три вершины определяют треугольник; если задано не кратное трем число вершин, то последние вершины игнорируются.

· GL_TRIANGLE_STRIP каждая следующая вершина задает треугольник вместе с двумя предыдущими.

· GL_TRIANGLE_FAN треугольники задаются первой вершиной и каждой следующей парой вершин. (пары не пересекаются)

· GL_QUADS каждая отдельная четверка вершин определяет четырехугольник; если задано не кратное четырем число вершин, то последние вершины игнорируются.

· GL_QUAD_STRIP четырехугольник с номером n определяется вершинами с номерами 2n-1, 2n, 2n+2, 2n+1.

· GL_POLYGON последовательно задаются вершины выпуклого многоугольника.

 

 

 

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

 

GLfloat BlueCol[3] = {0, 0, 1};

glBegin(GL_TRIANGLES);

glColor3f(1.0, 0.0, 0.0); /* красный */

glVertex3f(0.0, 0.0, 0.0);

glColor3ub(0, 255, 0); /* зеленый */

glVertex3f(1.0, 0.0, 0.0);

glColor3fv(BlueCol); /* синий */

glVertex3f(1.0, 1.0, 0.0);

glEnd();

 

Как правило, разные типы примитивов имеют различную скорость визуализации на разных платформах. Для увеличения производительности предпочтительнее использовать примитивы, требующие меньшее количество информации для передачи на сервер, такие как GL_TRIANGLE_STRIP, GL_QUAD_STRIP, GL_TRIAGLE_FAN.

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

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

void glFrontFace (GLenum mode);

 

со значением параметра mode равным GL_CW (clockwise), а вернуть значение по умолчанию можно, указав GL_CCW (counter-clockwise). Чтобы изменить метод отображения примитива используется команда:

void glPolygonMode (GLenum face, Glenum mode);

 

Параметр mode определяет, как будут отображаться примитивы:

GL_POINT - отображение только вершин многоугольников.

GL_LINE - многоугольники будут представляться набором отрезков.

GL_FILL - многоугольники будут закрашиваться текущим цветом с учетом освещения, и этот режим установлен по умолчанию.

 

а параметр face устанавливает тип примитивов, к которым будет применяться эта команда:

GL_FRONT - для лицевых граней

GL_BACK - для обратных граней

GL_FRONT_AND_BACK - для всех граней

 

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

 

void glCullFace (GLenum mode);

 

Вызов с параметром GL_FRONT приводит к удалению из изображения всех лицевых граней, а с параметром GL_BACK – обратных (установка по умолчанию).

 

Кроме рассмотренных стандартных примитивов в библиотеках GLU и GLUT описаны более сложные фигуры, такие как сфера, цилиндр, диск (в GLU ) и сфера, куб, конус, тор, тетраэдр, додекаэдр, икосаэдр, октаэдр и чайник (в GLUT ). Например, чтобы нарисовать сферу, надо сначала создать объект специального типа GLUquadricObj с помощью команды:

 

GLUquadricObj* gluNewQuadric (void);

 

а затем вызвать соответствующую команду:

 

void gluSphere (GLUquadricObj * qobj, GLdouble radius, GLint slices, GLint stacks);

 

где параметр slices задает число разбиений вокруг оси z, а stacks – вдоль оси z.

13. Дисплейные списки. Массивы вершин. (самостоятельно)

Дисплейные списки

Если мы несколько раз обращаемся к одной и той же группе команд, то их можно объединить в так называемый дисплейный список ( display list ), и вызывать его при необходимости.

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

 

void glNewList (GLuint list, GLenum mode);

void glEndList ();

 

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

 

GL_COMPILE команды записываются в список без выполнения

GL_COMPILE_AND_EXECUTE команды сначала выполняются, а затем записываются в список

 

После того, как список создан, его можно вызвать командой:

 

void glCallList (GLuint list);

 

указав в параметре list идентификатор нужного списка.

 

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

 

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

 

вызывающей n списков с идентификаторами из массива lists, тип элементов которого указывается в параметре type. Это могут быть типы GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_INT, GL_UNSIGNED_INT и некоторые другие.

 

Для удаления списков используется команда:

 

void glDeleteLists (GLint list, GLsizei range);

 

которая удаляет списки с идентификаторами ID из диапазона list ≤ ID ≤ list+range-1.

 

Пример:

 

glNewList(1, GL_COMPILE);

glBegin(GL_TRIANGLES);

glVertex3f(1.0f, 1.0f, 1.0f);

glVertex3f(10.0f, 1.0f, 1.0f);

glVertex3f(10.0f, 10.0f, 1.0f);

glEnd();

glEndList()

glCallList(1);

 

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

Массивы вершин

Если вершин много, то чтобы не вызывать для каждой команду glVertex, удобно объединять вершины в массивы, используя команду:

 

void glVertexPointer (GLint size, GLenum type, GLsizei stride, void* ptr);

 

которая определяет способ хранения и координаты вершин. При этом size определяет число координат вершины (может быть равен 2, 3, 4), type определяет тип данных (может быть равен GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE ).

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

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

 

void glNormalPointer ( GLenum type, GLsizei stride, void *pointer );

void glColorPointer ( GLint size, GLenum type, GLsizei stride, void *pointer );

 

Для того чтобы эти массивы можно было использовать в дальнейшем, надо вызвать команду:

 

void glEnableClientState (GLenum array);

 

с параметрами GL_VERTEX_ARRAY, GL_NORMAL_ARRAY, GL_COLOR_ARRAY соответственно. После окончания работы с массивом желательно вызвать команду:

 

void glDisableClientState (GLenum array);

 

с соответствующим значением параметра array.

 

Для отображения содержимого массивов используется команда:

 

void glArrayElement (GLint index);

 

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

 

glColor*(…), glNormal*(…), glVertex*(…) с соответствующими параметрами.

 

Однако вместо нее обычно вызывается команда:

 

void glDrawArrays (GLenum mode, GLint first, GLsizei count);

 

рисующая count примитивов, определяемых параметром mode, используя элементы из массивов с индексами от first до first+count-1. Это эквивалентно вызову последовательности команд glArrayElement () с соответствующими индексами.

 

В случае, если одна вершина входит в несколько примитивов, то вместо дублирования ее координат в массиве удобно использовать ее индекс. Для этого надо вызвать команду:

 

void glDrawElements (GLenum mode, GLsizei count, GLenum type, void *indices);

 

где indices – это массив номеров вершин, которые надо использовать для построения примитивов, type определяет тип элементов этого массива: GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, а count задает их количество. Важно отметить, что использование массивов вершин позволяет оптимизировать передачу данных на сервер OpenGL, и, как следствие, повысить скорость рисования трехмерной сцены.

 

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

14. Работа с матрицами. Модельно-видовые преобразования. (км)

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

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

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

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

  • модельно-видовая
  • матрица проекций
  • матрица текстуры.

 

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

Матрица проекций определяет, как будут проецироваться трехмерные объекты на плоскость экрана (в оконные координаты).

Матрица текстуры определяет наложение текстуры на объект.

 

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

 

void glMatrixMode (GLenum mode);

 

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

 

Команда void glLoadIdentity (void); записывает в текущую матрицу единичную матрицу.

 

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

 

void glPushMatrix (void);

void glPopMatrix (void);

 

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

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

 

void glMultMatrix[f d] (GLtype *m);

 

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

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

 

Запомните: все видовые преобразования объектов, положения камеры и пр. в OpenGL производятся с помощью умножения векторов координат объектов на соответствующие матрицы.

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

 

 

 

1. Исходные координаты объекта умножаются на матрицу моделей. Получается измененный вектор координат с учетом видовых преобразований.

2. умножение на матрицу проекций. При этом отсекаются координаты находящиеся вне моделируемой сцены.

3. координаты нормализуются при помощи параметра W (однородная система координат).

4. трансформация в 2-х мерные координаты окна.

 

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

К модельно-видовым преобразованиям будем относить перенос, поворот и изменение масштаба вдоль координатных осей.

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

 

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

 

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

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

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

void glRotate[f d] (GLtype angle, 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() имеет смысл перед определением преобразований объектов, когда модельно-видовая матрица равна единичной.

15. Проекции. Область вывода. (км)

В 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);

 

Первая команда создает матрицу проекции, которая отсекает координаты в объем видимости (параллелепипед) в левосторонней системе координат. Параметры команды задают точки, которые отвечают левому нижнему и правому верхнему углам окна вывода. Параметры 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.

 

 

Прежде чем задавать матрицы проекций, не забудьте включить режим работы с нужной матрицей командой 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);

16. Модель освещения и спецификация материалов (самостоятельно)

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

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

 

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

 

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, вне зависимости от положения в видовых координатах. Если же он равен 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 () и повышает эффективность программы.

 

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

 

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

 

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);

17. Описание источников света (самостоятельно).

Добавить в сцену источник света можно с помощью команд:

 

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 должен содержать четыре целых или вещественных числа, которые определяют направление света. Эта характеристика источника имеет смысл, если значение GL_SPOT_CUTOFF отлично от 180 (которое, кстати, задано по умолчанию).

Значение по умолчанию: (0.0, 0.0, -1.0, 1.0).

 

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

 

Attenuation=1/(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 (). При включенном освещении цвет вершины вычисляется исходя из информации о материале, нормалях и источниках света.

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

18. Создание эффекта тумана (самостоятельно)

В завершение рассмотрим одну интересную и часто используемую возможность OpenGL – создание эффекта уровня прозрачности среды («тумана»). Легкое затуманивание сцены создает реалистичный эффект, когда в сцене присутствуют объекты с разной степенью удаленности от пользователя.

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

 

glEnable (GL_FOG);

 

Метод вычисления интенсивности тумана в вершине можно определить с помощью команд:

 

void glFog[if] (enum pname, T param);

void glFog[if]v (enum pname, T params);

 

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

 

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

 

GL_EXP - интенсивность вычисляется по формуле f=exp(-d*z)

GL_EXP2 - интенсивность вычисляется по формуле f=exp(-(d*z)2)

GL_LINEAR - и нтенсивность вычисляется по формуле f=e-z/e-s

 

где z – расстояние от вершины, в которой вычисляется интенсивность тумана, до точки наблюдения.

Коэффициенты d, e, s задаются с помощью следующих значений аргумента pname:

 

GL_FOG_DENSITY param определяет коэффициент d

GL_FOG_START param определяет коэффициент s

GL_FOG_END param определяет коэффициент e

 

Цвет тумана задается с помощью аргумента pname, равного GL_FOG_COLOR в этом случае params является указателем на массив из 4-х компонент цвета.

 

Пример использования этого эффекта:

 

GLfloat FogColor[4]={0.5, 0.5, 0.5, 1};

glEnable(GL_FOG);

glFogi(GL_FOG_MODE, GL_LINEAR);

glFogf(GL_FOG_START, 20.0);

glFogf(GL_FOG_END, 100.0);

glFogfv(GL_FOG_COLOR, FogColor);

19 Текстуры. Подготовка текстуры (самостоятельно)

Для использования текстуры необходимо сначала загрузить в память нужное изображение и передать его OpenGL. Считывание графических данных из файла и их преобразование можно проводить вручную. В приложении D приведен исходный текст функции для загрузки изображения из файла в формате BMP.

Можно также воспользоваться функцией, входящей в состав библиотеки GLAUX, которая сама проводит необходимые операции. Это функция:

 

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.

 


Поделиться:



Популярное:

Последнее изменение этой страницы: 2017-03-03; Просмотров: 861; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.259 с.)
Главная | Случайная страница | Обратная связь