Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

книги / C++Builder. ╨г╤З╨╡╨▒╨╜╤Л╨╣ ╨║╤Г╤А╤Б

.pdf
Скачиваний:
0
Добавлен:
12.11.2023
Размер:
9.63 Mб
Скачать

11.4.4. Освещение

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

glE nable(G L _L IG H T IN G );

разрешить работу с освещенностью и командой

g l E n a b l e (GL_LIGHT0) ;

включить источник света. Это минимальные действия для включения источника света. При необходимости можно «устано­ вить» несколько источников, например:

g l E n a b l e (GL_LIGHT1) ; / / включаем источник света 1

Все добавляемые источники света используют установки, принятые по умолчанию, и ничем не отличаются друг от друга. Источник света по умолчанию располагается в пространстве в точке с координатами (0, 0, 1). При построениях необходимо зада­ вать вектор нормали, используемый для расчета цветовых пара­ метров каждого пиксела.

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

Пример 11.15

- В секции p r i v a t e определения класса формы объявите переменные:

HDC DC;

HGLRC h r e ;

- Создайте обработчик события OnCreate.

v o id __f a s t c a l l T Form l: : FormCreate (TObject *Sender)

{

DC = G e tD C ( H a n d l e ) ;

S e t D C P i x e lF o r m a t ( D C ) ;

h r c = w g l C r e a t e C o n t e x t ( D C ) ;

w glM akeC urrent(D C ,

h r c ) ;

 

g l C l e a r C o l o r ( 0 . 5 , 0 . 5 , 0 . 7 5 , 1 . 0 ) ;

g l C o l o r 3 f ( 0 . 0 , 0 . 5 , 0 . 0 ) ;

glEnable(G L _ LIG H TIN G );

 

g lE n a b le (G L _ L IG H T 0 );

 

 

glEnable(GL_DEPTH_TEST);

 

}

 

 

 

При создании окна включается источник света:

g l E n a b l e (GL__LIGHTING) ;

/ /

разрешаем р а б о т у

 

 

/ /

с освещенностью

glE nable(G L _ L IG H T 0) ;

/ /

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

Это минимальные действия для включения источника света. Теперь в сцене присутствует один источник света с номером 0.

- Создайте обработчик события O n D e s tr o y .

v o id __f a s t c a l l T F o r m l : : F o r m D e s t r o y ( T O b j e c t * S ender)

{

w g l M a k e C u r r e n t (0,

0 ) ;

w g l D e l e t e C o n t e x t ( h r c ) ;

R e le a s e D C ( H a n d le ,

DC);

D e le te D C (D C );

 

}

- Создайте обработчик события O n P a in t .

v o id __f a s t c a l l T F o r m l : : F o r m P a i n t ( T O b j e c t ‘ S e n d e r )

{

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) ;

glBegin(GL_QUADS);

g l N o r m a l 3 f ( 0 . 0 , 0 . 0 , 1 . 0 ) ; g l V e r t e x 3 f ( 1 . 0 , 1 . 0 , 1 . 0 ) ;

g l V e r t e x 3 f ( - 1 . 0 , 1 . 0 , 1 . 0 ) ; g l V e r t e x 3 f ( - 1 . 0 , - 1 . 0 , 1 . 0 ) ; g l V e r t ex 3 f ( 1 . 0 , - 1 . 0 , 1 . 0 ) ;

g l E n d ( ) ;

g l B e g i n (Gli_QUADS) ;

g l N o r m a l 3 f ( - 1 . 0 , 0 . 0 , 0 . 0 ) ; g l V e r t e x 3 f ( - 1 . 0 , 1 . 0 , 1 . 0 ) ; g l V e r t e x 3 f ( - 1 . 0 , 1 . 0 , - 1 . 0 ) ;

g l V e r t e x 3 f ( - 1 . 0 , - 1 . 0 , - 1 . 0 ) ; g l V e r t e x 3 f ( - 1 . 0 , - 1 . 0 , 1 . 0 ) ;

g l E n d ( ) ;

glBegin(GL_QUADS) ;

g l N o r m a l 3 f (0 . 0 , 1 . 0 , 0 . 0 ) ;

g l V e r t e x 3 f ( - 1 . 0 , 1 . 0 , - 1 . 0 ) ; g l V e r t e x 3 f ( - 1 . 0 , 1 . 0 , 1 . 0 ) ; g l V e r t e x 3 f ( 1 . 0 , 1 . 0 , 1 . 0 ) ;

g l V e r t e x 3 f (1 . 0 , 1 . 0 , - 1 . 0 ) ; g l E n d ( ) ;

SwapBuffers(DC) ;

}

Для сокращения кода из шести сторон куба остаются только три непосредственно видимые наблюдателю. При рисовании каж­ дой стороны куба задается вектор нормали, используемый для расчета цветовых параметров каждого пиксела. Вектора нормалей строятся перпендикулярно каждой стороне куба. В силу того, что наш кубик строится вокруг точки (0, 0, 0), аргументы g lN o rm a l3 f в данном случае совпадают с точкой пересечения диагоналей каждой грани куба. Вектор нормали не обязательно должен исходить именно из середины площадки, достаточно того, чтобы он был параллелен действительному вектору нормали к площадке.

- Создайте обработчик события OnResize.

Если режим GL_COLOR_MATERlAL не включен, то текущие цветовые установки не влияют на цвет поверхности куба, поэтому он выглядит серым, хотя текущий цвет задан зеленоватым. Попут­ но обращу ваше внимание на то, что если объект приближается чересчур близко к глазу наблюдателя и пересекает ближнюю плоскость отсечения, в нем появляется дырка, сквозь которую можно заглянуть внутрь объекта. Кроме того, существует еще об­ щее фоновое (am bient) освещение.

Для правильного освещения объектов необходимо для каждой грани задать материал, обладающий определенными свойствами. Материал может испускать свой собственный свет, рассеивать па­ дающий свет во всех направлениях (диффузное отражение) или подобно зеркалу отражать свет в определенных направлениях. Пользователь может определить до восьми источников света и их свойства, такие, как цвет, положение и направление. Большинство параметров источника света задается с помощью, например ко­ манды g l L i g h t f v .

glLicjhtfv(GL _LIGHT0, GL_POSITION, p o s i t i o n ) ;

Первый параметр команды - идентификатор источника света; второй аргумент - символическая константа, указывающая, какой атрибут устанавливается. Последний аргумент - имя массива, со­ держащего задаваемые значения. Для задания позиции использу­ ется символическая константа GL_P0SITI0N, указываемый мас­ сив определяет позицию источника света в текущей системе коор­ динат, например:

G L f lO a t p o s i t i o n [4] = {0 .0, 0 . 0 , 1 . 5, 1.0} ;

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

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

g l E n a b l e (GL_CULL_FACE) ;

11.5. Надстройки над OpenGL

Существует несколько надстроек над OpenGL, представляю­ щих собой набор готовых команд для упрощения кодирования. Стандартной надстройкой, поставляемой вместе с OpenGL, явля­ ется библиотека g lu , физически располагающаяся в файле g lu 3 2 . d l l . Мы уже изучили несколько команд этой библиотеки, и в дальнейшем продолжим ее изучение. Помимо этой стандарт­ ной надстройки наиболее популярной является библиотека g lu t . Для программистов, пишущих на языке С, эта библиотека особен­ но привлекательна, поскольку является независимой от операци­ онной системы. Ее применение значительно упрощает кодирова­ ние программ, поскольку, например, для рисования куба с единич­ ной длиной ребра вместо двух десятков строк теперь достаточно одной:

g l u t S o l i d C u b e ( 1 .0) ;

Помимо куба, модуль (и библиотека) содержит команды вос­ произведения сферы, тора, конуса и некоторых правильных много­ гранников, таких как тетраэдр и додекаэдр. Есть здесь и команда для рисования классического объекта для тестовых программ ма­ шинной графики - чайника. Команды из этой библиотеки начина­ ются с префикса g l u t . Ниже приводятся примеры для рисования других геометрических фигур:

g l u t S o l i d S p h e r e ( 1 . 5 , 20,

2 0 ) ;

g l u tS o l id C o n e ( 0 . 5 ,

1 . 5 ,

20,

2 0 ) ;

g l u t S o l i d T o r u s ( 0 . 5 ,

1 . 5 ,

20,

2 0 ) ;

g lu tS o lid D o d e c a h e d r o n (); g l u t S o l i d l c o s a h e d r o n (); g l u t S o l i d T e t r a h e d r o n ()

g l u t S o l i d T e a p o t ( 1 . 5 ) ;

Для подключения библиотеки g l u t необходимо выполнить

следующие действия:

-Поместить в заголовочном файле модуля команду препро­ цессора:

# in c lu d e < g l \ g l u t . h>

 

- Скопировать в папку С : \P r o g r a m

F i l e s \ C o d e G e a r \

RAD

S t u d i o \ 5 . 0 \ i n c l u d e \ g l файл g l u t

.h .

 

-Скопировать

в

папку

C : \ P r o g r a m

F i l e s \ C o d e G e a r \

RAD

S t u d i o \ 5 . 0 \ l i b файл g l u t 3 2 . l i b .

 

 

-Скопировать

в

папку

C :\W in d o w s \s y s te m 3 2 файл

g l u t 3 2 . d l l .

 

 

 

 

 

 

 

 

- В

секции

p r i v a t e

определения

класса формы объявите

переменные:

 

 

 

 

 

 

 

HDC DC;

 

 

 

 

 

 

 

HGLRC

h r с ;

 

 

 

 

 

 

 

 

-Создайте

обработчик

события O n C reate формы. Само­

стоятельно разберитесь с назначением каждого оператора обра­ ботчика.

v o id __f a s t c a l l

T Form l: : F o rm C reate(T O b ject *Sender)

{

 

C lie n tW id th =

C lie n tH e ig h t+ P a n e ll- > W id th ;

R a d io G ro u p l-> lte m ln d e x = 2; DC = G etD C (H andle);

SetD C P ixelF orm at(D C );

h rc = w g lC re a te C o n te x t(D C );

wglM akeCurrent(DC,

h r c ) ;

g l C l e a r C o l o r (0 .5 ,

0 . 5, 0 . 75, 1 . 0 ) ;

g l C o l o r 3 f (1 .0 , 0 . 0, 0 . 5 ) ; g lL in e W id th ( 1 . 5 ) ;

g l P o i n t S i z e (5) ;

g lE n a b le (GL_POINT__SMOOTH) ; g l E n a b l e (GL_LIGHTING);

glEnable(GL_LIGHTO) ; glEnable(GL_DEPTH_TEST) ;

g l N o r m a l 3 f ( - 1 . 0 , 0 . 0 , 0 . 0 ) ;

- Создайте обработчик события O nD e stroy .

v o i d __ f a s t c a l l T F orm l: : FormDestroy (TObject ‘ Sender)

{

w g l M a k e C u r r e n t (0, 0) ; w g l D e l e t e C o n t e x t ( h r c ) ; R e le a se D C (H a n d le , DC) ; D e le te D C (D C );

}

- Создайте обработчик события O n P a in t .

v o id __f a s t c a l l T F orm l:: FormPaint (TObject ^Sender)

{

g l C l e a r (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ; g l u t S o l i d C u b e (1 .5) ;

S w a p B u f f e r s ( D C ) ;

}

- Создайте обработчик события OnResize.

v o id __f a s t c a l l T F orm l:: FormResize (TObject ‘ Sender)

{

g l V i e w p o r t (0, 0, C lie n tW id th - P a n e ll - > W id th / C l i e n t H e i g h t );

glMatrixMode(GL_PROJECTION) ;

g l L o a d l d e n t i t y ( ) ;

 

 

 

g l F r u s t u m f - l , 1,

-1, 1,

4,

15);

g lM atrix M o d e (GL__MODELVIEW) ;

 

g l L o a d l d e n t i t y () ;

 

 

 

/ / э т о т фрагмент

нужен

для

придания трёхмерности

g l T r a n s l a t e f ( 0 . 0 , 0 . 0 , - 8 . 0 ) ;

g l R o t a t e f

(3 0 . 0 ,

1 . 0 ,

0 . 0 ,

0 . 0 ) ;

g l R o t a t e f

(7 0 . 0 ,

0 . 0 ,

1 . 0 ,

0 . 0 ) ;

-Создайте обработчик события O n C lic k компонента R a ­

d i o g r o u p l .

void __fastcall T F o r m l : : R a d i o G r o u p l C l i c k ( T O b j e c t * S e n d e r )

{

switch ( R a d i o G r o u p l - > l t e m l n d e x )

{

case 0:

glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;

case 1:

glPolygonM ode (GL_FRONT_AND_BACK, GL_LINE) ; break;

case 2:

glPolygonMode(GL_FRONT_AND_BACK, GL _FILL);

}

I n v a l i d a t e R e c t ( H a n d l e , NULL, false);

}

- Запустите приложение и проверьте правильность его работы. Для того, чтобы можно было вращать куб с помощью мыши

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

int x l , у1 ,*

B o o le a n Down = false;

- Создайте обработчик события OnMouseDown формы.

void __fastcall T F o r m l : : FormMouseDown(TObject

* S e n d e r , TM ouseButton B u t t o n , T S h i f t S t a t e S h i f t , int X, int Y)

{

Down = true; x l = X;

Соседние файлы в папке книги