Динамична светлина
Динамичната светлина е изключително важна за една триизмерна графика, понеже тя кара света да изглежда триизмерен. За да има ефект динамичната светлина, трябва да са дефинирани нормалите на обектите. Ако използвате функциите за изграждане на готови обекти с GLUT или GLAUX няма за какво да се притеснявате, но в противен случай ще трябва да определите нормалите на обектите създадени от вас. Kак се изчисляват нормали ( нормални вектори ) ще бъде обяснено в друга тема, затова засега използвайте някой обект генериран от функция на GLUT или GLAUX. За да включите динамична светлина трябва да изпълните две стъпки - дефиниране на източника на светлината и определяне на материала на обектите или начина по който обектите ще отразяват даден тип светлина, от което зависи и как ще изглеждат те. Преди да започнете с динамичната светлина трябва да накарате OpenGL да проверява разстоянията до обектите т.е. да не се изрисуват обекти, които се намират зад други обекти и реално не трябва да бъдат виждани. Това става като подадете на функцията glEnable( ) аргумента GL_DEPTH_TEST. Освен това за да използвате динамичната светлина, тя трябва да бъде включена : извикайте отново glEnable( ), но с аргумента GL_LIGHTING.Тези две функции както и всички по-надолу е строго препоръчително да бъдат извикани предварително в main / WinMain ( ако ползвате Win32 Api ) след като вече сте направили прозореца за вашето приложение, а не във вашата рендерираща функция.
В OpenGL съществуват три вида светлина:

Ambient - тази свeтлина идва отвсякъде и се отразява навсякъде. Този вид светлина се получава когато светлината от даден източник се отрази многократно във всички обекти. Т.е. Ambient светлината е глобалната светлина, която ни позволява да виждаме обектите по нашата сцена. Аналогично в слънчево време всичко изглежда по-светло, а в облачно - по-тъмно. Можете да дефинирате глобална Ambient светлина. Ще видите как по-надолу.

Diffuse - тази светлина идва от определена посока и се отразява навсякъде. Пример за това е една обикновена лампа.

Specular - тази светлина идва от определена посока и се отразява в определена посока. Пример за това е отблясъка на даден предмет.

След като сте включили динамичната светлина трябва да определите светлинен източник. Това става с една от двете разновидности на следната функция :

glLightf( GLenum light, GLenum pname, GLfloat param )
glLightfv( GLenum light, GLenum pname, const GLfloat *params )

Тя приема три аргумента. Първия е името на светлинния източник, което се определя чрез една от константите GL_LIGHT0, GL_LIGHT1, GL_LIGHT2, GL_LIGHT3, GL_LIGHT4, GL_LIGHT5, GL_LIGHT6 или GL_LIGHT7. В OpenGL може да има едновременно осем действащи светлинни източника. Вторият аргумент може да бъде един от аргументите :

GL_AMBIENT - oпределя Аmbient излъчването на източника. Трябва да използвате функцията glLightfv( ), като подадете за трети аргумент float масив от стойности, определящи нейното излъчване. Ако още не сте забелязали можете да определите цвят на светлината, като сложите в масива съответната RGBA стойност. Например:
float m[ ] = { 0.2 , 0.2 , 0.2, 1.0 }; ( четвъртото число се отнася за прозрачността, оставете го единица )
Ето как можете да определите Ambient излъчването за светлинен източник GL_LIGHT0 :
glLightfv( GL_LIGHT0 , GL_AMBIENT , m );

Съветвам ви да не правите светлинни източници, които излъчват Ambient светлина, а да определите глобална Ambient светлина, което е описано по-надолу.

GL_DIFFUSE - oпределя Diffuse излъчването на източника. Трябва да използвате glLightfv( ) , като подадете съответния масив със стойности.

GL_SPECURAL - oпределя Specular излъчването на източника. Отново трябва да използвате glLightfv( ), като подадете съответния масив със стойности.

GL_POSITION - oпределя координатите на светлинния източник. Трябва да използвате glLightfv( ) , като подадете съответния масив със стойности, определящ ( x , y , z , (w) ) позицията на източника. Ако имате w аргумент и той е равен на 0, това означава че източника се намира на безкрайно разстояние и съответните стойности определят посоката на светлината.

GL_SPOT_DIRECTION - определя посоката на разпространение на светлината. Трябва да използвате glLightfv( ) , като подадете съответния масив със стойности.

GL_SPOT_EXPONENT - определя фокуса на светлината. Той може да бъде стойност от 0 - 128. Колкото е по-голям, толкова светлината е по-ярка в центъра и по-слаба по краищата на конуса. Вече трябва да използвате glLightf( ). Например:
glLightf ( GL_LIGHT0 ,GL_SPOT_EXPONENT ,10.0 );

GL_SPOT_CUTOFF - определя ъгъла между вектора сочещ посоката на светлината и края на конуса, в който се разпространява светлината. Може да приема стойности от 0 до 90. При по-големи от 90 градуса светлината се разпростанява навсякъде и няма конус. Трябва да използвате glLightf( ), като подадете за трети аргумент съответния ъгъл. Например :
glLightf ( GL_LIGHT0 , GL_SPOT_CUTOFF , 45.0 );
За да определите всичко необходимо за определен светлинен източник трябва да извикате последователно няколко пъти glLightf( ) / glLightfv( ) , като можете и да дефинирате няколко вида светлина които се излъчват от един източник.

Сега трябва да включите съответния светлинен източник със функцията glEnable( ), като подадете за параметъра неговото име. Например : glEnable( GL_LIGHT0 ). Той може да бъде и изключен с функцията glDisable( ).

Остава да определим материала на обектите. Това става с една от разновидностите на следната функция :

glMaterialfv( GLenum face, GLenum pname, const GLfloat *params )
glMaterialf( GLenum face, GLenum pname, GLfloat param )

Тя приема три аргумента. Първия аргумент може да бъде една от константите GL_FRONT, GL_BACK или GL_FRONT_AND_BACK, които определят за коя част от обекта се отнася съответната дефиниция на материала. Вторият аргумент може да бъде един от аргументите:

GL_AMBIENT - определя начина на отразяване на светлина тип Ambient. Трябва да използвате glMaterialfv( ), като подадете съответния масив от стойности. Това може да бъде същия масив, който сте използвали при дефинирането на излъчваната светлина от определен източник.

GL_DIFFUSE - определя начина на отразяване на светлина тип Diffuse. Трябва да използвате glMaterialfv( ), като подадете съответния масив от стойности.

GL_SPECULAR - определя начина на отразяване на светлина тип Specular. Използвайте glMaterialfv( ), като подадете съответния масив от стойности.

GL_EMISSION - определя излъчвана от обекта светлина. Тя се отразява единствено на цвета на обекта и може да бъде използвана ако искате да създадете лампа. Трябва да използвате glMaterialfv( ), като подадете съответния масив от стойности.

GL_SHININESS - определя големината на най-яркото отражение, причинено от светлина тип SPECULAR. С glMateriali( ) подавате число от 0 до 128. Колкото по-голямо е то, толкова по-точно фокусирано и по-малко е светлинното петно. Определянето на най-яркото изображение при използването на светлина тип SPECULAR е много важно.

GL_AMBIENT_AND_DIFFUSE - определя едновременно еднакъв начин на отразяване за Ambient и Diffuse светлината.

Ако вашите обекти са били с предварително дефиниран цвят, то при включване на динамичната светлина тяхния цвят не се взема в предвид, а се генерира нов цвят в зависимост от светлинните източници и начина на отразяване на светлината. Ако обаче подадете на glEnable( ) константата GL_COLOR_MATERIAL предварителния цвят на обектите взема участие в създаването на крайния цвят. Това не е препоръчително ако вашата светлина не е само бяла т.е. ако RGB стойностите в масива не са еднакви. Например: float Diffuse_light[] = { 0.8 , 0.8 , 0.8 , 1.0 }; Защото в противен случай e възможно да получите нещо което въобще не става за гледане :) Aко имате предварително определен цвят на даден обект, ще ви бъде нужна и функцията :

glColorMaterial(GLenum face, GLenum mode) - тя определя за кои видове светлина да се взема в предвид цвета на обекта при изграждането на крайния му цвят. Първия аргумент може да бъде една от вече познатите ви константи GL_FRONT, GL_BACK или GL_FRONT_AND_BACK, а втория - GL_EMISSION, GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR или GL_AMBIENT_AND_DIFFUSE т.е. съответно светлината при която ще вслиза в сила и цвета на обекта.

Желателно е всеки път да определяте глобална Ambient светлина вместо да определяте за даден светлинен източник Ambient светлината, която излъчва, ако има такава. Това става с функцията :

glLightModelfv( GLenum pname, const GLfloat *params ) - тя приема два аргумента. За определите глобална Ambient светлина трябва да подадете за първи аргумент константата GL_LIGHT_MODEL_AMBIENT, а за втори масива, който определя излъчването на Ambient светлината. Oпределянето на глобална Ambient светлина може да бъде изключително полезно. Ако не определите никаква Ambient светлина, това не значи че няма да има такава. По подразбиране Ambient светлината в OpenGL е ambient_light[] = { 0.2 , 0.2 , 0.2 , 1.0 }.

Toва не е всичко, което може да се каже за динамичната светлина, но като за начало е достатъчно. Ето тук може да видите примера използващ динамична светлина. Определено с нея всичко изглежда много по-добре.

Автор: Иван Георгиев Иванов [ Nickname: tuschko ]
e-mail: tuschko@abv.bg


Този сайт е хостван от сървър на
Headoff Gaming Intranetwork