Основы OpenGL

Основные возможности и описание набора базовых примитивов стандарта OpenGL. Программное построение вершин и примитивов. Основы работы с матрицами. Создание материалов и освещения. Технология создания текстур. Особенности написания спецэффектов и теней.

Рубрика Программирование, компьютеры и кибернетика
Вид учебное пособие
Язык русский
Дата добавления 20.04.2011
Размер файла 95,7 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

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

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

Общий подход к созданию текстур:

/* нужное нам количество текстур */

#define NUM_TEXTURES 10

/* идентификаторы текстур */

int TextureIDs[NUM_TEXTURES];

/* образ текстуры */

AUX_RGBImageRec *pImage;

/* 1) получаем идентификаторы текстур */

glGenTextures(NUM_TEXTURES,TextureIDs);

/* 2) выбираем текстуру для модификации параметров */

glBindTexture(TextureIDs[i]); /* 0<=i<NUM_TEXTURES*/

/* 3) загружаем текстуру. Размеры текстуры - степень 2 */

pImage=dibImageLoad("texture.bmp");

if (Texture!=NULL)

{

/* 4) передаем текстуру OpenGL и задаем параметры*/

/* выравнивание по байту */

glPixelStorei(GL_UNPACK_ALIGNMENT,1);

gluBuildMipmaps(GL_TEXTURE_2D,GL_RGB, pImage->sizeX,
pImage->sizeY, GL_RGB, GL_UNSIGNED_BYTE,
pImage->data);

glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,
(float)GL_LINEAR);

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
(float)GL_LINEAR);

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
(float)GL_REPEAT);

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
(float)GL_REPEAT);

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
(float)GL_REPLACE);

/* 5) удаляем исходное изображение.*/

free(Texture);

}else Error();

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

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

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

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..(type s, type t), задающие текущие координаты текстуры. Вообще, понятие текущих координат текстуры аналогично понятиям текущего цвета и текущей нормали, и является атрибутом вершины. Однако даже для куба нахождение соответствующих координат текстуры является довольно трудоемким занятием, поэтому в библиотеке 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 с соответствующими изменениями.

6. Создание спецэффектов

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

6.1 Туман

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

Туман в 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);

6.2 Прозрачность

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

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

Режим включается с помощью команды glEnable(GL_BLEND).

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

void glBlendFunc(enum src,enum dst)

Параметр src определяет, как получить коэффициент k1 исходного цвета пикселя, a dst определяет способ получения коэффициента k2 для цвета в буфере кадра. Для получения результирующего цвета используется следующая формула: res=сsrc*k1+cdst*k2, где сsrc - цвет исходного пикселя, cdst - цвет пикселя в буфере кадра. ( res, k1, k2, сsrc, cdst - векторы!).

Приведем наиболее часто используемые значения агрументов 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)

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)

Пример:

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

glEnable(GL_BLEND);

glBlendFunc(GL_SRC_ALPHA,GL_SRC_ONE_MINUS_ALPHA);

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

Все прозрачные объекты выводятся после непрозрачных.

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

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

6.3 Буфер накопления

Буфер накопления (accumulation buffer) - это дополнительный внутренный буфер OpenGL. В нем можно сохранять визуализированное изображение, применяя при этом попиксельно специальные операции.

Изображение берется из буфера, выбранного на чтение командой

void glReadBuffer(enum buf)

Аргумент buf определяет буфер для чтения. Значения buf, равные GL_BACK, GL_FRONT, определяют соответствующие буфера для чтения.

Применяя различные операции, описанные ниже, можно как-бы понемногу накапливать изображение в буфере.

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

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. Достаточно только иметь сам буфер.

В качестве примера использования буфера накопления рассмотрим задачу устранения лестничного эффекта (antialiasing).

Алгоритм ее решения сразу для всей сцены таков:

Для каждого кадра выводим сцену несколько раз, каждый раз немного смещая камеру относительно начального положения (положения камер, например, могут образовывать окружность). Все сцены сохраняем в буфере накопления с коэффициентом 1/n, где n - число сцен для каждого кадра. Чем больше таких сцен (antialiasing samples) - тем хуже производительность, но лучше качество.

for(i=0;i<samples_count;++i)

/* обычно samples_count лежит в пределах от 5 до 10 */

{

ShiftCamera(i); /* сдвигаем камеру */

RenderScene();

if (i==0)

/* на первой итерации загружаем изображение */

glAccum(GL_LOAD,1/(float)samples_count);

else

/* добавляем к уже существующему */

glAccum(GL_ADD,1/(float)samples_count);

}

/* Пишем то, что получилось, назад в исходный буфер */

glAccum(GL_RETURN,1.0);

Буфер накопления редко реализуется аппаратно. Поэтому использование устранения ступенчатости сразу для всей сцены практически несовместимо с визуализацией динамических изображений с приемлемой частотой вывода кадров ( frame rate).

6.4 Трафаретный буфер

При выводе пикселей в буфер кадра иногда возникает необходимость выводить не все пиксели, а только некоторое их подмножество, т.е. как-бы наложить трафарет на изображение. Для этого OpenGL предоставляет так называемый трафаретный буфер (stencil buffer). Кроме наложения трафарета, этот буфер предоставляет еще несколько интересных возможностей.

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

Механизм сравнения контролируется следующими командами:

void glStencilFunc (enum func, int ref, uint mask)

void glStencilOp (enum sfail, enum dpfail, enum dppass)

Аргумент ref команды StencilFunc задает значение для сравнения. Он должен принимать значение от 0 до 2s -1. s - число бит на точку в трафаретном буфере.

С помощью аргумента func задается функция сравнения. Он может принимать следующие значения:

GL_NEVER тест никогда не проходит, т.е всегда возвращает false

GL_ALWAYS тест проходит всегда.

GL_LESS, GL_LEQUAL, GL_EQUAL,

GL_GEQUAL, GL_GREATE, GL_NOTEQUAL тест проходит в случае, если ref соответственно меньше значения в трафаретном буфере, меньше либо равен, равен, больше, больше либо равен или не равен.

Аргумент mask задает маску для значений. Т.е. в итоге для трафаретного теста получаем следующую формулу: ((ref AND mask) op (svalue AND mask))

Команда StencilOp предназначена для определения действий над пикселем трафаретного буфера в случае положительного или отрицательного результата теста.

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

GL_KEEP,GL_ZERO,GL_REPLACE,

GL_INCR,GL_DECR,GL_INVERT соответственно сохраняет значение в трафаретном буфере, обнуляет его, заменяет на заданное значение (ref), увеличивает, уменьшает или побитово инвертирует.

Аргументы dpfail определяют действия в случае отрицательного результата теста на глубину в z-буфере. dppass задает действие в случае положительного результата этого теста. Аргументы принимают те же значения, что и аргумент sfail. По умолчанию все три параметра установлены на GL_KEEP.

Для включения трафаретного теста необходимо выполнить команду glEnable(GL_STENCIL_TEST);

Трафаретный тест используется при создании таких спецэффектов, как тени, отражения, плавные переходы из одной картинки в другую, создания конструктивной геометрии (CSG) и др.

Пример использования трафаретного теста при создании теней описан в Приложении.

7. Приложение

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

7.1 Стандартные геометрические примитивы

Рассмотрим стандартные команды построения примитивов, которые реализованы в библиотеках GLU и GLUT.

Как уже было сказано, чтобы построить примитив из библиотеки GLU, надо сначала создать указатель на quadric-объект с помощью команды gluNewQuadric(), а затем вызвать одну из команд gluSphere(), gluCylinder(), gluDisk(), gluPartialDisk(). Рассмотрим эти команды отдельно:

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

Строит сферу с центром в начале координат и радиусом radius. При этом число разбиений сферы вокруг оси z задается параметром slices, а вдоль оси z - параметром stacks.

void gluCylinder (GLUquadricObj *qobj,GLdouble baseRadius,GLdouble topRadius, GLdouble height, GLint slices, GLint stacks)

Строит цилиндр без оснований (то есть кольцо), продольная ось параллельна оси z, заднее основание имеет радиус baseRadius, и расположено в плоскости z=0, переднее основание имеет радиус topRadius и расположено в плоскости z= height. Если задать один из радиусов равным нулю, то будет построен конус.

Параметры slices и stacks имеют аналогичный смысл, что и в предыдущей команде.

void gluDisk (GLUquadricObj *qobj, GLdouble innerRadius, GLdouble outerRadius, GLint slices, GLint loops)

Строит плоский диск (то есть круг) с центром в начале координат и радиусом outerRadius. При этом если значение innerRadius ненулевое, то в центре диска будет находиться отверстие радиусом innerRadius. Параметр slices задает число разбиений диска вокруг оси z, а параметр loops -число концентрических колец, перпендикулярных оси z.

void gluPartialDisk (GLUquadricObj *qobj, GLdouble innerRadius, GLdouble outerRadius, GLint slices, GLint loops, GLdouble startAngle, GLdouble sweepAngle);

Отличие этой команды от предыдущей заключается в том, что она строит сектор круга, начальный и конечный углы которого отсчитываются против часовой стрелки от положительного направления оси y и задаются параметрами startAngle и sweepAngle. Углы измеряются в градусах.

Команды, проводящие построение примитивов из библиотеки GLUT, реализованы через стандартные примитивы OpenGL и GLU. Для построения нужного примитива достаточно произвести вызов соответствующей команды.

void glutSolidSphere (GLdouble radius, GLint slices, GLint stacks)

void glutWireSphere (GLdouble radius, GLint slices, GLint stacks)

Команда glutSolidSphere() строит сферу, а glutWireSphere()-каркас сферы радиусом radius. Остальные параметры имеют аналогичный смысл, что и в предыдущих командах.

void glutSolidCube (GLdouble size)

void glutWireCube (GLdouble size)

Эти команды строят куб или каркас куба с центром в начале координат и длиной ребра size.

void glutSolidCone (GLdouble base, GLdouble height, GLint slices, GLint stacks)

void glutWireCone (GLdouble base, GLdouble height, GLint slices, GLint stacks)

Эти команды строят конус или его каркас высотой height и радиусом основания base, расположенный вдоль оси z. Основание находится в плоскости z=0. Остальные параметры имеют аналогичный смысл, что и в предыдущих командах.

void glutSolidTorus (GLdouble innerRadius, GLdouble outerRadius, GLint nsides, GLint rings)

void glutWireTorus (GLdouble innerRadius, GLdouble outerRadius, GLint nsides, GLint rings)

Эти команды строят тор или его каркас в плоскости z=0. Внутренний и внешний радиусы задаются параметрами innerRadius, outerRadius. Параметр nsides задает число сторон в кольцах, составляющих ортогональное сечение тора, а rings-число радиальных разбиений тора.

void glutSolidTetrahedron (void)

void glutWireTetrahedron (void)

Эти команды строят тетраэдр (правильную треугольную пирамиду) или его каркас, при этом радиус описанной сферы вокруг него равен 1.

void glutSolidOctahedron (void)

void glutWireOctahedron (void)

Эти команды строят октаэдр или его каркас, радиус описанной вокруг него сферы равен 1.

void glutSolidDodecahedron (void)

void glutWireDodecahedron (void)

Эти команды строят додекаэдр или его каркас, радиус описанной вокруг него сферы равен квадратному корню из трех.

void glutSolidIcosahedron (void)

void glutWireIcosahedron (void)

Эти команды строят икосаэдр или его каркас, радиус описанной вокруг него сферы равен 1.

7.2 Построение теней

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

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

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

Рассмотрим математические основы данного метода.

Пусть:

P - точка в трехмерном пространстве, которая отбрасывает тень.

L - положение источника света, который освещает данную точку.

S=a(L-P)-P - точка, в которую отбрасывает тень точка P.

Для нахождения параметра а положим, что тень падает на плоскость z=0. В этом случае a=zp/(zl-zp). Следовательно,

xs=(xpzl-zlzp)/(zl-zp),

ys=(ypzl-ylzp)/(zl-zp),

zs=0

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

xs=xs'/ws'

ys=ys'/ws'

zs=0

ws'=zl-zp

Отсюда S может быть получена с использованием умножения матриц следующим образом:

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

aP+bL, где a и b - скалярные параметры.

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

Точка, в которой луч, проведенный от источника света через данную точку P, пересекает плоскость G, определяется параметрами a и b, удовлетворяющими следующему уравнению:

(aP+bL)G=0

Отсюда получаем: a(PG)+b(LG)=0. Этому уравнению удовлетворяют

a=(LG), b=-(PG)

Следовательно, искомая точка S=(LG)P-(PG)L. Пользуясь ассоциативностью матричного произведения, получим

S=P[(LG)I-GL], где I - единичная матрица.

Матрица (LG)I-GL (*) используется для получения теней на произвольной плоскости.

Рассмотрим некоторые аспекты практической реализации данного метода с помощью OpenGL.

Предположим, что матрица floorShadow была ранее получена нами из формулы (*). Следующий код с ее помощью строит тени для заданной плоскости:

/* Делаем тени полупрозрачными с использованием смешения цветов(blending) */

glEnable(GL_BLEND);

glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

glDisable(GL_LIGHTING);

glColor4f(0.0, 0.0, 0.0, 0.5);

glPushMatrix();

/* Проецирум тень */

glMultMatrixf((GLfloat *) floorShadow);

/* Визуализируем сцену в проекции */

RenderGeometry();

glPopMatrix();

glEnable(GL_LIGHTING);

glDisable(GL_BLEND);

/* Визуализируем сцену в обычном режиме */

RenderGeometry();

Матрица floorShadow может быть получена из уравнения (*) с помощью следующей функции:

/* args: plane - plane equation

lightpos - light positions

return: matrix - resulting matrix

*/

void

shadowmatrix(GLfloat matrix[4][4], GLfloat plane[4], GLfloat lightpos[4])

{

GLfloat dot;

dot = plane[0] * lightpos[0] +

plane[1] * lightpos[1] +

plane[2] * lightpos[2] +

plane[3] * lightpos[3];

matrix[0][0] = dot - lightpos[0] * plane[0];

matrix[1][0] = 0.f - lightpos[0] * plane[1];

matrix[2][0] = 0.f - lightpos[0] * plane[2];

matrix[3][0] = 0.f - lightpos[0] * plane[3];

matrix[0][1] = 0.f - lightpos[1] * plane[0];

matrix[1][1] = dot - lightpos[1] * plane[1];

matrix[2][1] = 0.f - lightpos[1] * plane[2];

matrix[3][1] = 0.f - lightpos[1] * plane[3];

matrix[0][2] = 0.f - lightpos[2] * plane[0];

matrix[1][2] = 0.f - lightpos[2] * plane[1];

matrix[2][2] = dot - lightpos[2] * plane[2];

matrix[3][2] = 0.f - lightpos[2] * plane[3];

matrix[0][3] = 0.f - lightpos[3] * plane[0];

matrix[1][3] = 0.f - lightpos[3] * plane[1];

matrix[2][3] = 0.f - lightpos[3] * plane[2];

matrix[3][3] = dot - lightpos[3] * plane[3];

}

Тени, построенные таким образом, имеют ряд недостатков.

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

В некоторых местах тени может наблюдаться эффект "двойного смешения" (reblending), т.е. темные пятна в тех участках, где спроецированные треугольники перекрывают друг друга.

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

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

Однако имеется решение первой и второй проблемы. Для этого используется трафаретный буфер, работа с которым была описана в предыдущей главе.

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

Очищаем трафаретный буфер значением 0

Отображаем заданную область, устанавливая значения в трафаретном буфере в 1

Выводим тени в те области, где в трафаретном буфере установлены значения 1. Если тест проходит, устанавливаем в эти области значение 2.

Рассмотрим эти этапы более подробно.

1.

/* очищаем трафаретный буфер */

glClearStencil(0x0);

/* включаем тест */

glEnable(GL_STENCIL_TEST);

2.

/* условие всегда выполнено и значение в буфере будет равно 1*/

glStencilFunc (GL_ALWAYS, 0x1, 0xffffffff);

/* в любом случае заменяем значение в трафаретном буфере*/

glStencilOp (GL_REPLACE, GL_REPLACE, GL_REPLACE);

/* выводим геометрию, по которой затем будет отсечена тень*/

RenderPlane();

3.

/* условие выполнено и тест дает истину только если значение в трафаретном буфере равно 1 */

glStencilFunc (GL_EQUAL, 0x1, 0xffffffff);

/* значение в буфере равно 2,если тень уже выведена */

glStencilOp (GL_KEEP, GL_KEEP, GL_ADD);

/* выводим тени */

RenderShadow();

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

7.3 Создание приложения в среде 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.

7.4 Создание приложения в среде 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', а затем заново подключить необходимые библиотеки.

7.5 Примеры программ

Пример №1

Этот простой пример предназначен для демонстрации структуры GLUT-приложения и простейших основ OpenGL. Результатом работы программы является случайный набор цветных прямоугольников, который меняется при нажатии левой кнопки мыши. С помощью правой кнопки мыши можно менять режим заливки прямоугольников.

#include <stdlib.h>

#include <gl\glut.h>

#ifdef random

#undef random

#endif

#define random(m) (float)rand()*m/RAND_MAX

/* ширина и высота окна */

GLint Width = 512, Height = 512;

/* число прямоугольников в окне */

int Times = 100;

/* с заполнением ?*/

int FillFlag = 1;

long Seed = 0;

/* функция отображает прямоугольник */

void

DrawRect( float x1, float y1, float x2, float y2,

int FillFlag )

{

glBegin(FillFlag ? GL_QUADS : GL_LINE_LOOP);

glVertex2f(x1, y1);

glVertex2f(x2, y1);

glVertex2f(x2, y2);

glVertex2f(x1, y2);

glEnd();

}

/* управляет всем выводом на экран */

void

Display(void)

{

int i;

float x1, y1, x2, y2;

float r, g, b;

srand(Seed);

glClearColor(0, 0, 0, 1);

glClear(GL_COLOR_BUFFER_BIT);

for( i = 0; i < Times; i++ ) {

r = random(1);

g = random(1);

b = random(1);

glColor3f( r, g, b );

x1 = random(1) * Width;

y1 = random(1) * Height;

x2 = random(1) * Width;

y2 = random(1) * Height;

DrawRect(x1, y1, x2, y2, FillFlag);

}

glFinish();

}

/* Вызывается при изменении размеров окна */

void

Reshape(GLint w, GLint h)

{

Width = w;

Height = h;

glViewport(0, 0, w, h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

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

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

/* Обрабатывает сообщения от мыши */

void

Mouse(int button, int state, int x, int y)

{

if( state == GLUT_DOWN ) {

switch( button ) {

case GLUT_LEFT_BUTTON:

Seed = random(RAND_MAX);

break;

case GLUT_RIGHT_BUTTON:

FillFlag = !FillFlag;

break;

}

glutPostRedisplay();

}

}

/* Обрабатывает сообщения от клавиатуры */

void

Keyboard( unsigned char key, int x, int y )

{

#define ESCAPE '\033'

if( key == ESCAPE )

exit(0);

}

main(int argc, char *argv[])

{

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_RGB);

glutInitWindowSize(Width, Height);

glutCreateWindow("Rect draw example (RGB)");

glutDisplayFunc(Display);

glutReshapeFunc(Reshape);

glutKeyboardFunc(Keyboard);

glutMouseFunc(Mouse);

glutMainLoop();

}

Пример №2

Программа предназначена для демонстрации модели освещения OpenGL. Результатом работы программы является простая сцена, состоящая из тора, конуса и шара. Объектам назначаются разные материалы. В сцене присутствует точечный источник света.

#include <GL/glut.h>

#include <stdlib.h>

/* параметры материала тора */

float mat1_dif[]={0.8f,0.8f,0.0f};

float mat1_amb[]= {0.2f,0.2f,0.2f};

float mat1_spec[]={0.6f,0.6f,0.6f};

float mat1_shininess=0.5f*128;

/* параметры материала конуса */

float mat2_dif[]={0.0f,0.0f,0.8f};

float mat2_amb[]= {0.2f,0.2f,0.2f};

float mat2_spec[]={0.6f,0.6f,0.6f};

float mat2_shininess=0.7f*128;

/* параметры материала шара */

float mat3_dif[]={0.9f,0.2f,0.0f};

float mat3_amb[]= {0.2f,0.2f,0.2f};

float mat3_spec[]={0.6f,0.6f,0.6f};

float mat3_shininess=0.1f*128;

/* Инициализируем параметры материалов и

* источника света

*/

void init (void)

{

GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };

GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };

GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };

GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };

/* устанавливаем параметры источника света */

glLightfv (GL_LIGHT0, GL_AMBIENT, light_ambient);

glLightfv (GL_LIGHT0, GL_DIFFUSE, light_diffuse);

glLightfv (GL_LIGHT0, GL_SPECULAR, light_specular);

glLightfv (GL_LIGHT0, GL_POSITION, light_position);

/* включаем освещение и источник света */

glEnable (GL_LIGHTING);

glEnable (GL_LIGHT0);

/* включаем z-буфер */

glEnable(GL_DEPTH_TEST);

}

/* Функция вызывается при необходимости

* перерисовки изображения. В ней осуществляется

* весь вывод геометрии.

*/

void display (void)

{

/* очищаем буфер кадра и буфер глубины */

glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glPushMatrix ();

glRotatef (20.0, 1.0, 0.0, 0.0);

/* отображаем тор */

glMaterialfv (GL_FRONT,GL_AMBIENT,mat1_amb);

glMaterialfv (GL_FRONT,GL_DIFFUSE,mat1_dif);

glMaterialfv (GL_FRONT,GL_SPECULAR,mat1_spec);

glMaterialf (GL_FRONT,GL_SHININESS,mat1_shininess);

glPushMatrix ();

glTranslatef (-0.75, 0.5, 0.0);

glRotatef (90.0, 1.0, 0.0, 0.0);

glutSolidTorus (0.275, 0.85, 15, 15);

glPopMatrix ();

/* отображаем конус */

glMaterialfv (GL_FRONT,GL_AMBIENT,mat2_amb);

glMaterialfv (GL_FRONT,GL_DIFFUSE,mat2_dif);

glMaterialfv (GL_FRONT,GL_SPECULAR,mat2_spec);

glMaterialf (GL_FRONT,GL_SHININESS,mat2_shininess);

glPushMatrix ();

glTranslatef (-0.75, -0.5, 0.0);

glRotatef (270.0, 1.0, 0.0, 0.0);

glutSolidCone (1.0, 2.0, 15, 15);

glPopMatrix ();

/* отображаем шар */

glMaterialfv (GL_FRONT,GL_AMBIENT,mat3_amb);

glMaterialfv (GL_FRONT,GL_DIFFUSE,mat3_dif);

glMaterialfv (GL_FRONT,GL_SPECULAR,mat3_spec);

glMaterialf (GL_FRONT,GL_SHININESS,mat3_shininess);

glPushMatrix ();

glTranslatef (0.75, 0.0, -1.0);

glutSolidSphere (1.0, 15, 15);

glPopMatrix ();

glPopMatrix ();

/* выводим сцену на экран */

glFlush ();

}

/* Вызывается при изменении пользователем размеров окна

*/

void reshape(int w, int h)

{

/* устанавливаем размер области вывода

* равным размеру окна

*/

glViewport (0, 0, (GLsizei) w, (GLsizei) h);

/* задаем матрицу проекции с учетом размеров окна */

glMatrixMode (GL_PROJECTION);

glLoadIdentity ();

gluPerspective(

40.0, /* угол зрения в градусах */

(GLfloat)w/h, /* коэффициент сжатия окна */

1,100.0); /* расстояние до плоскостей отсечения */

glMatrixMode (GL_MODELVIEW);

glLoadIdentity ();

gluLookAt(

0.0f,0.0f,8.0f, /* положение камеры */

0.0f,0.0f,0.0f, /* центр сцены */

0.0f,1.0f,0.0f); /* положительное направление оси y */

}

/* Вызывается при нажатии клавиши на клавиатуре */

void keyboard(unsigned char key, int x, int y)

{

switch (key) {

case 27: /* escape */

exit(0);

break;

}

}

/* Главный цикл приложения.

* Создается окно, устанавливается режим

* экрана с буфером глубины

*/

int main(int argc, char** argv)

{

glutInit(&argc, argv);

glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB

| GLUT_DEPTH);

glutInitWindowSize (500, 500);

glutCreateWindow (argv[0]);

init ();

glutReshapeFunc (reshape);

glutDisplayFunc (display);

glutKeyboardFunc (keyboard);

glutMainLoop();

return 0;

}

Пример №3

Результатом выполнения этой программы является построение тетраэдра с вращающимися вокруг него кольцами, на которые нанесена текстура. В среде MS Visual C++ программа может компилироваться без изменений, а при компиляции в Borland C++ придется закомментировать вызов и описание функции TextureInit(), после чего не будет проводиться наложение текстур. Как было сказано выше, попытка использовать функции из библиотеки GLAUX приводит к сообщению об ошибке при компиляции программы.

При компиляции программы в MS Visual C++ файл `texture.bmp' надо поместить в каталог проекта или указать полный путь к нему, используя символ `/'. Если путь не указан, то при запуске исполняемого файла из операционной системы, файл с текстурой должен находиться в том же каталоге.

#include <GL\glut.h>

#include <gl\glaux.h>

#include <math.h>

#define TETR_LIST 1

GLfloat light_col[] = {1,1,1};

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

float mat_diff2[]={0.0,0.0,0.9};

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

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

float shininess=0.7*128,

float CurAng=0, RingRad=1, RingHeight=0.1;

GLUquadricObj* QuadrObj;

GLuint TexId;

GLfloat TetrVertex[4][3], TetrNormal[4][3];

/* Вычисление нормали к плоскости,

* задаваемой точками a,b,c

*/

void getnorm (float a[3],float b[3],float c[3],float *n)

{

float mult=0,sqr;

int i,j;

n[0]=(b[1]-a[1])*(c[2]-a[2])-(b[2]-a[2])*(c[1]-a[1]);

n[1]=(c[0]-a[0])*(b[2]-a[2])-(b[0]-a[0])*(c[2]-a[2]);

n[2]=(b[0]-a[0])*(c[1]-a[1])-(c[0]-a[0])*(b[1]-a[1]);

/* Определение нужного направления нормали: от точки (0,0,0) */

for (i=0;i<3;i++) mult+=a[i]*n[i];

if (mult<0) for (j=0;j<3;j++) n[j]=-n[j];

}

/* Вычисление координат вершин тетраэдра */

void InitVertexTetr()

{

float alpha=0;

int i;

TetrVertex[0][0]=0;

TetrVertex[0][1]=1.3;

TetrVertex[0][2]=0;

/* Вычисление координат основания тетраэдра */

for (i=1;i<4;i++)

{

TetrVertex[i][0]=0.94*cos(alpha);

TetrVertex[i][1]=0;

TetrVertex[i][2]=0.94*sin(alpha);

alpha+=120.0*3.14/180.0;

}

}

/* Вычисление нормалей сторон тетраэдра */

void InitNormsTetr()

{

getnorm(TetrVertex[0], TetrVertex[1],

TetrVertex[2], TetrNormal[0]);

getnorm(TetrVertex[0], TetrVertex[2],

TetrVertex[3], TetrNormal[1]);

getnorm(TetrVertex[0], TetrVertex[3],

TetrVertex[1], TetrNormal[2]);

getnorm(TetrVertex[1], TetrVertex[2],

TetrVertex[3], TetrNormal[3]);

}

/* Создание списка построения тетраэдра */

void MakeTetrList()

{

int i;

glNewList(TETR_LIST,GL_COMPILE);

/* Задание сторон тетраэдра */

glBegin(GL_TRIANGLES);

for (i=1;i<4;i++)

{

glNormal3fv(TetrNormal[i-1]);

glVertex3fv(TetrVertex[0]);

glVertex3fv(TetrVertex[i]);

if (i!=3) glVertex3fv(TetrVertex[i+1]);

else glVertex3fv(TetrVertex[1]);

}

glNormal3fv(TetrNormal[3]);

glVertex3fv(TetrVertex[1]);

glVertex3fv(TetrVertex[2]);

glVertex3fv(TetrVertex[3]);

glEnd();

glEndList();

}

void DrawRing()

{

/* Построение цилиндра (кольца), расположенного

* параллельно оси z. Второй и третий параметры

* задают радиусы оснований, четвертый высоту,

* последние два-число разбиений вокруг и вдоль

* оси z. При этом дальнее основание цилиндра

* находится в плоскости z=0

*/

gluCylinder (QuadrObj,RingRad,RingRad,RingHeight,30,2);

}

void TextureInit()

{

char strFile[]="texture.bmp";

AUX_RGBImageRec *pImage;

/* Выравнивание в *.bmp по байту */

glPixelStorei(GL_UNPACK_ALIGNMENT,1);

/* Создание идентификатора для текстуры */

glGenTextures(1,&TexId);

/* Загрузка изображения в память */

pImage = auxDIBImageLoad(strFile);

/* Начало описания свойств текстуры */

glBindTexture (GL_TEXTURE_2D,TexId);

/* Создание уровней детализации и инициализация текстуры

*/

gluBuild2DMipmaps(GL_TEXTURE_2D,3,pImage->sizeX,

pImage->sizeY,GL_RGB,GL_UNSIGNED_BYTE,

pImage->data);

/* Разрешение наложения этой текстуры на quadric-объекты

*/

gluQuadricTexture (QuadrObj, GL_TRUE);

/* Задание параметров текстуры */

/* Повтор изображения по параметрическим осям s и t */

glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);

glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

/* Не использовать интерполяцию при выборе точки на

* текстуре

*/

glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

/* Совмещать текстуру и материал объекта */

glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

}

void Init(void)

{

InitVertexTetr();

InitNormsTetr();

MakeTetrList();

/* Определение свойств материала */

glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, mat_amb);

glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, mat_spec);

glMaterialf (GL_FRONT, GL_SHININESS, shininess);

/* Определение свойств освещения */

glLightfv(GL_LIGHT0, GL_DIFFUSE, light_col);

glEnable(GL_LIGHTING);

glEnable(GL_LIGHT0);

/* Проводить удаление невидимых линий и поверхностей */

glEnable(GL_DEPTH_TEST);

/* Проводить нормирование нормалей */

glEnable(GL_NORMALIZE);

/* Материалы объектов отличаются только цветом диффуз-

* ного отражения

*/

glEnable(GL_COLOR_MATERIAL);

glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE);

/* Создания указателя на quadric-объект для построения

* колец

*/

QuadrObj=gluNewQuadric();

/* Определение свойств текстуры */

TextureInit();

/* Задание перспективной проекции */

glMatrixMode(GL_PROJECTION);

gluPerspective(89.0,1.0,0.5,100.0);

/* Далее будет проводиться только

* преобразование объектов сцены

*/

glMatrixMode(GL_MODELVIEW);

}

void DrawFigures(void)

{

/* Включение режима нанесения текстуры */

glEnable(GL_TEXTURE_2D);

/* Задаем цвет диффузного отражения для колец */

glColor3fv(mat_diff1);

/* Чтобы не проводить перемножение с предыдущей матрицей

* загружаем единичную матрицу

*/

glLoadIdentity();

/* Определяем точку наблюдения */

gluLookAt(0.0, 0.0, 2.5,0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

/* Сохраняем видовую матрицу, так как дальше будет

* проводиться поворот колец

*/

glPushMatrix();

/* Производим несколько поворотов на новый

* угол (это быстрее, чем умножать предыдущую

* видовую матрицу на матрицу поворота с фиксированным

* углом поворота)

*/

glRotatef (-CurAng,1,1,0);

glRotatef (CurAng,1,0,0);

/* Для рисования колец каждое из них надо

* преобразовать отдельно, поэтому сначала сохраняем

* видовую матрицу, затем восстанавливаем

*/

glPushMatrix();

glTranslatef (0,0,-RingHeight/2);

DrawRing();

glPopMatrix();

glPushMatrix();

glTranslatef (0,RingHeight/2,0);

glRotatef (90,1,0,0);

DrawRing();

glPopMatrix();

glPushMatrix();

glTranslatef (-RingHeight/2,0,0);

glRotatef (90,0,1,0);

DrawRing();

glPopMatrix();

/* Восстанавливаем матрицу для поворотов тераэдра */

glPopMatrix();

/* Выключаем режим наложения текстуры */

glDisable(GL_TEXTURE_2D);

/* Проводим повороты */

glRotatef (CurAng,1,0,0);

glRotatef (CurAng/2,1,0,1);

/* Чтобы тетраэдр вращался вокруг центра, его

* надо сдвинуть вниз по оси oz

*/

glTranslatef (0,-0.33,0);

/* Задаем цвет диффузного отражения для тетраэдра */

glColor3fv(mat_diff2);

/* Проводим построение тетраэдра */

glCallList(TETR_LIST);

}

void Display(void)

{

/* Инициализация (очистка) текущего буфера кадра и

* глубины

*/

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

/* Построение объектов */

DrawFigures();

/* Перестановка буферов кадра */

glutSwapBuffers();

}

void Redraw(void)

{

/* Увеличение текущего угла поворота */

CurAng+=1;

/* Сигнал для вызова процедуры создания

* изображения (для обновления)

*/

glutPostRedisplay();

}

int main(int argc, char **argv)

{

/* Инициализация функций библиотеки GLUT */

glutInit(&argc, argv);

/* Задание режима с двойной буферизацией,

* представление цвета в формате RGB, использование

* буфера глубины

*/

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

/* Создание окна приложения */

glutCreateWindow("Example of using OpenGL");

/* Регистрация функции построения изображения */

glutDisplayFunc(Display);

/* Регистрация функции обновления изображения */

glutIdleFunc(Redraw);

/* Инициализация функций OpenGL */

Init();

/* Цикл обработки событий */

glutMainLoop();

return 0;

}

Использованные материалы

1. Тихомиров Ю. Программирование трехмерной графики. СПб., BHV 1998.

2. Visual Introduction in OpenGL, Siggraph'98.

3. The OpenGL graphics system: a specification (version 1.1).

4. Программирование GLUT: окна и анимация. Miguel Angel Sepulveda, LinuxFocus.

5. The OpenGL Utility Toolkit (GLUT) Programming Interface, API version 3, specification.

Размещено на Allbest.ru


Подобные документы

  • Программный код OpenGL. Синтаксис команд OpenGL. OpenGL как конечный автомат. Конвейер визуализации OpenGL. Библиотеки, относящиеся к OpenGL. Библиотека OpenGL. Подключаемые файлы. GLUT, инструментарий утилит библиотеки OpenGL.

    курсовая работа [304,9 K], добавлен 01.06.2004

  • Назначение и стандарты реализации OpenGL для Windows, порядок подключения графической библиотеки. Основные функции и синтаксис команд. Рисование примитивов, видовые и аффинные преобразования. Моделирование двумерных графических объектов и анимации.

    лабораторная работа [35,0 K], добавлен 04.07.2009

  • Ознакомление с интерфейсом, основными возможностями и преимуществами использования программы OpenGL - популярной библиотекой для работы с 2D и 3D графикой. Рассмотрение назначения, базовых компонент и правил инициализации программного движка DirectX.

    презентация [19,4 K], добавлен 14.08.2013

  • Суть программирования с использованием библиотеки OpenGL, его назначение, архитектура, преимущества и базовые возможности. Разработка приложения для построения динамического изображения трехмерной модели объекта "Компьютер", руководство пользователя.

    курсовая работа [866,8 K], добавлен 22.06.2011

  • Разработка компоненты для математических вычислений (операций над матрицами) с использованием технологии OpenGL (сложение, вычитание, умножение, транспонирование, определитель, обратная матрица). Базовые навыки по работе с технологией в среде .Net.

    курсовая работа [365,6 K], добавлен 17.02.2015

  • Основы работы с графиков средствами OpenGL в C#. Ее спецификации, принципы и возможности. Direct3D как самостоятельная часть библиотеки Microsoft DirectX, которая отвечает за графику и вывод графической информации. Независимость от языка программирования.

    курсовая работа [2,1 M], добавлен 17.02.2013

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

    реферат [160,8 K], добавлен 10.01.2012

  • Описание используемых функций и директивы Invoke: get module handle, get command line, win main, exit process, load menu. Архитектура OpenGL, основные задачи. Текст программы: краткое описание, opengl.inc, opngl.asm. Результаты выполнения программы.

    курсовая работа [215,6 K], добавлен 18.05.2014

  • Общие сведения о OpenGL и его использование для разработки логотипа. Разработка программы: функции, их использование в программе. Построение модели и возможность перемещения объектов. Задание освещения объектов моделирования и проработка элементов фона.

    курсовая работа [447,7 K], добавлен 14.07.2012

  • 3D Studio Max - программа трёхмерной графики, ее назначение, технические возможности, особенности управления, поддержка .NET в SDK и основные аспекты работы. Описание создания и простейшего редактирования стандартных примитивов (на примере чайника).

    реферат [1,5 M], добавлен 01.05.2010

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.