Točkovni vir svetlobe v opengl. Nadaljujemo našo študijo OpenGL: osvetlitev po Phongu. Vse skupaj

Osvetlitev v OpenGL ES je uporabna funkcija, ki lahko doda prijeten pridih 3D igram. Za uporabo takšne funkcionalnosti moramo najprej razumeti model osvetlitve OpenGL ES.

Kako deluje osvetlitev

Razmislimo o tem, kako deluje osvetlitev. Najprej potrebujemo vir svetlobe, ki oddaja svetlobo. Potrebovali boste tudi osvetljen predmet. Končno potrebujemo tudi senzor, kot je oko ali kamera, ki sprejema fotone, ki jih pošilja svetlobni vir in odbija predmet. Osvetlitev spremeni zaznano barvo predmeta glede na: vrsto svetlobnega vira; barva ali intenzivnost svetlobnega vira; položaj vira svetlobe in njegova smer glede na osvetljeni predmet; material in tekstura predmeta.

Intenzivnost, s katero se svetloba odbija od predmeta, je odvisna od številnih dejavnikov. Najpomembnejši dejavnik, ki ga gledamo, je kot, pod katerim svetlobni žarek pade na površino. Bližje kot je ta kot pravemu kotu, večja je intenzivnost, s katero se bo svetloba odbijala od predmeta. To je prikazano na sl. 11.1.

Ko svetlobni žarek zadene površino, se odbije v dve različni smeri. Večina svetlobe se bo odbila difuzno. To pomeni, da so odbiti svetlobni žarki neenakomerno in naključno razpršeni po površini predmeta. Nekateri žarki se odbijajo zrcalno. To pomeni, da se bodo svetlobni žarki odbijali nazaj, kot da bi udarili v popolno ogledalo. Na sl. Slika 11.2 prikazuje razliko med difuznimi in zrcalnimi odboji.

riž. 11.1. Bližje kot je pravemu kotu, večja je intenzivnost odbite svetlobe

riž. 11.2. Razpršeni in zrcalni odboji

Zrcalni odsevi bodo prikazani kot poudarki na predmetih. Ali se svetloba zrcalno odbija od predmeta, je odvisno od materiala, iz katerega je izdelan. Predmeti z neravno ali hrapavo površino, kot je koža, najverjetneje ne bodo imeli zrcalnih poudarkov. Predmeti z gladko površino, kot sta steklo ali marmor, bodo pokazali te svetlobne artefakte. Steklo ali marmor seveda nista popolnoma gladka, a v primerjavi z lesom ali človeško kožo sta.

Ko svetloba zadene površino, tudi njen odboj spremeni barvo glede na kemična sestava osvetljeni predmet. Predmeti, ki se nam zdijo rdeči, odbijajo samo rdeče dele svetlobe in absorbirajo vse druge frekvence. Črn predmet je tisti, ki absorbira skoraj vso svetlobo, ki pade nanj.

OpenGL ES vam omogoča simulacijo obnašanja v resničnem svetu z definiranjem virov svetlobe in materialov predmetov.

Viri svetlobe

Obkroženi smo s številnimi različnimi viri svetlobe. Sonce nenehno oddaja svoje fotone. Monitorji oddajajo svetlobo, ki nas ponoči obdaja s prijetnim sijem. Žarnice in žarometi nam pomagajo preprečiti trke v različne predmete v temi. OpenGL ES omogoča ustvarjanje štirih vrst svetlobnih virov.

Osvetlitev ozadja. Sama po sebi ni vir svetlobe, temveč posledica pojavljanja fotonov iz drugih svetlobnih virov. Ti naključni fotoni skupaj ustvarjajo konstantno raven osvetlitve, ki nima smeri in enako osvetljuje vse predmete.

Točkovni viri svetlobe. Imajo položaj v prostoru in oddajajo svetlobo v vse smeri. Na primer, točkovni vir svetlobe je žarnica.

Viri usmerjene svetlobe. Izraženo kot navodila v OpenGL ES. Predpostavlja se, da so neskončno daleč. V idealnem primeru bi lahko bil tak vir Sonce. Predvidevamo lahko, da vsi svetlobni žarki, ki prihajajo od Sonca, zadenejo Zemljo pod enakim kotom zaradi razdalje med Zemljo in Soncem.

O svetilkah. Te luči so podobne točkastim lučem, saj imajo določen položaj v prostoru. Poleg tega imajo smer, v katero oddajajo svetlobne žarke. Ustvarijo svetlobni stožec, omejen na določen radij. Primer takega vira svetlobe je ulična svetilka.

Upoštevali bomo samo osvetlitev ozadja, pa tudi točkovne in usmerjene vire svetlobe. Zaradi načina, na katerega OpenGL ES izračuna osvetlitev, je luči pogosto težko uporabljati v napravah Android, omejenih z GPU. Kmalu vam bo jasno, zakaj je tako.

Poleg položaja in smeri vira svetlobe vam OpenGL ES omogoča določitev barve ali jakosti svetlobe. Te značilnosti so izražene z barvo RGBA. Vendar pa OpenGL ES zahteva, da določite štiri različne barve na vir namesto samo ene.

Osvetlitev – Intenzivnost/barva, ki prispeva k senčenju predmeta. Predmet bo enakomerno osvetljen z vseh strani, ne glede na njegov položaj ali orientacijo glede na vir svetlobe.

Difuzno – intenzivnost/barva svetlobe, ki bo osvetlila objekt po izračunu difuznega odboja. Robovi predmeta, ki niso obrnjeni proti viru svetlobe, ne bodo osvetljeni, tako kot v resničnem življenju.

Specular – intenzivnost/barva podobna difuzni barvi. Vendar pa vpliva samo na tiste točke predmeta, ki imajo določeno orientacijo glede na vir svetlobe in senzor.

Emisija je zelo zapleten barvni izračun, ki ima izjemno omejeno uporabo v fizikalnih aplikacijah v resničnem svetu, zato ga ne bomo obravnavali.

Najpogosteje bomo uporabili difuzno in zrcalno jakost vira svetlobe, drugi dve pa privzeti vrednosti. Poleg tega bomo večino časa uporabljali isto barvo RGBA za razpršeno in zrcalno intenzivnost.

Materiali

Vsi predmeti v našem svetu so sestavljeni iz neke vrste materiala. Vsak material določa, kako se bo svetloba, ki pada na predmet, odbila in spremenila barvo odbite svetlobe. OpenGL ES vam omogoča, da definirate iste štiri barve RGBA za material kot za vir svetlobe.

Osvetlitev ozadja je barva, ki se kombinira z barvo ozadja katerega koli vira svetlobe v prizoru.

Difuzna je barva, ki se kombinira z difuzno barvo katerega koli vira svetlobe.

Specular je barva, ki se kombinira z zrcalno barvo katerega koli vira svetlobe. Uporablja se za ustvarjanje poudarkov na površini predmeta.

Emisivna - to vrsto barve še naprej ignoriramo, saj se v našem kontekstu praktično ne uporablja.

Slika 11.3 prikazuje prve tri vrste lastnosti materiala/svetlobnega vira: osvetlitev od zadaj, razpršena in zrcalna.

riž. 11.3. Različne vrste materialov/virov svetlobe: samo osvetlitev od zadaj (levo), samo razpršena (na sredini), osvetlitev od zadaj in razpršena barva z zrcalnimi poudarki (desno)

Na sl. Slika 11.3 prikazuje vpliv različnih lastnosti materialov in svetlobnih virov na barvo. Osvetlitev ozadja enakomerno osvetli velikost. Razpršena svetloba se bo odbila glede na kot, pod katerim svetlobni žarki zadenejo predmet; Področja, ki so neposredno obrnjena proti viru svetlobe, bodo svetleje osvetljena, območja, ki jih svetloba ne doseže, bodo temna. Na desni sliki lahko vidite kombinacijo osvetlitve ozadja, difuzne in zrcalne svetlobe. Zrcalna svetloba se pojavi kot beli poudarki na krogli.

Kako OpenGL ES izračuna osvetlitev: normale vozlišč

Veste, da je intenzivnost svetlobe, ki se odbije od predmeta, odvisna od njenega vpadnega kota na predmet. OpenGL ES uporablja to dejstvo za izračun osvetlitve. Za to uporablja normale vozlišč, ki morajo biti definirane v kodi na enak način kot koordinate teksture ali barve vozlišč. Na sl. Slika 11.4 prikazuje kroglo in normale njenih oglišč.

riž. 11.4. Krogla in normale njenih oglišč

Normale so enotski vektorji, ki označujejo smer, v katero se vrti površina. V našem primeru je površina trikotnik. Namesto normale površine definiramo normalo oglišča. Razlika med temi normalami je v tem, da normala oglišča morda ne kaže v isto smer kot normala površine. To je jasno vidno na sl. 11.4, kjer je vsaka normala oglišča povprečna normala vseh trikotnikov, ki jim oglišče pripada. To povprečenje se izvede za ustvarjanje gladkega senčenja predmeta.

Pri upodabljanju predmeta z osvetlitvijo in normalami oglišč bo OpenGL ES določil kot med vsakim ogliščem in virom svetlobe. Če ta kot pozna, lahko glede na lastnosti materiala izračuna barvo oglišča. Končni rezultat je barva vsakega oglišča, ki se nato uporabi za vsak trikotnik v kombinaciji z izračunanimi barvami drugih oglišč. Ta uporabljena barva bo kombinirana z vsemi transformacijami teksture, ki jih uporabimo za predmet.

To zveni precej strašljivo, a pravzaprav ni tako hudo. Omogočiti moramo osvetlitev in definirati vire svetlobe, material, ki ga je mogoče upodobiti, in normale vozlišč (poleg parametrov vozlišč, ki bi jih običajno definirali, kot so koordinate položaja ali teksture). Poglejmo, kako je to mogoče implementirati z uporabo OpenGL ES.

Na praksi

Zdaj pa izvedimo vse potrebne korake za delo z osvetlitvijo z uporabo OpenGL ES. Ustvarimo nekaj majhnih pomožnih razredov, ki bodo nekoliko olajšali delo z viri svetlobe, in jih postavimo v paket com.badlogi with.androi dgames.framework.gl.

Dovoljenje in prepoved razsvetljave

Kot pri drugih stanjih OpenGL ES morate najprej omogočiti imenovano funkcionalnost. To je mogoče storiti na naslednji način:

Po tem bo osvetlitev uporabljena za vse upodobljene predmete. Če želite dobiti rezultat, morate definirati svetlobne vire in materiale ter normale vozlišč. Ko smo končali z risanjem vseh potrebnih objektov, lahko osvetlitev izklopimo:

Določanje svetlobnih virov

OpenGL ES nudi 4 vrste svetlobnih virov: osvetlitev ozadja, točkovna, usmerjena in reflektorska. Poglejmo, kako določiti prve tri. Da bi bila svetila učinkovita in lepa, mora biti vsak model sestavljen iz ogromnega števila trikotnikov. To ni mogoče za mnoge trenutne mobilne naprave.

OpenGL ES vam omogoča, da definirate največ 8 virov svetlobe hkrati, kot tudi en globalni vir svetlobe. Vsak od 8 svetlobnih virov ima identifikator, od GL10.GL LIGHT0 do GL10.GL LIGHT7. Če morate spremeniti lastnosti ene od teh luči, lahko to storite tako, da definirate ustrezni ID.

Uporabo luči lahko omogočite z naslednjo sintakso:

Nato bo OpenGL ES prejel lastnosti tega vira svetlobe in jih uporabil za vse upodobljene predmete. Če moramo onemogočiti uporabo vira svetlobe, lahko to storimo z naslednjim stavkom:

Vrhunec je poseben primer, ker nima ID-ja. V prizorišču OpenGL ES lahko obstaja samo en poudarek. Oglejmo si podrobneje ta vir svetlobe.

Osvetlitev ozadja

Osvetlitev ozadja je posebna vrsta osvetlitve. Nima položaja ali smeri, le barvo, ki se enakomerno nanaša na vse osvetljene predmete. OpenGL ES vam omogoča definiranje globalnega označevanja na naslednji način:

Ambi entCol ali matrika vsebuje vrednosti RGBA barve osvetlitve ozadja, predstavljene kot števila s plavajočo vejico v razponu od 0 do 1. Metoda gl LightModel fv vzame kot prvi parameter konstanto, ki določa, da želimo nastaviti barvo svetlobe ozadja. vir, niz števil s plavajočo vejico, ki vsebuje izvorno barvo in odmik za niz s plavajočo vejico, iz katerega bo metoda začela brati vrednosti RGBA. Postavimo kodo, ki rešuje ta problem, v majhen razred. Njegova koda je prikazana na seznamu 11.2.

Seznam 11.2. Razred AmbientLight.java. preprosta abstrakcija globalne osvetlitve ODenGL ES

Vse, kar naredimo, je, da shranimo poudarjeno barvo v plavajočem nizu in zagotovimo dve metodi: ena se uporablja za nastavitev barve in druga, ki se uporablja za ukaz OpenGL ES, naj uporabi to barvo. Privzeta barva je siva.

Točkovni viri svetlobe

Točkovne luči imajo položaj, pa tudi ozadje, razpršeno in zrcalno barvo/intenzivnost (emisijske barve/intenzivnosti ne upoštevamo). Določite različni tipi barve kot sledi:

Prvi parameter je identifikator svetlobnega vira. V tem primeru uporabimo četrti vir. Naslednji parameter določa atribut, ki ga želimo spremeniti. Tretji parameter je niz števil s plavajočo vejico, ki vsebuje vrednosti RGBA, zadnji pa je odmik v tem nizu. Določanje položaja vira je prav tako enostavno:

Ponovno definiramo atribut, ki ga želimo spremeniti (v tem primeru položaj), niz štirih elementov, ki vsebuje x-, y- in z-koordinato vira svetlobe v svetu, ki se ustvarja. Upoštevajte, da mora biti četrti element niza enak ena, če ima vir svetlobe položaj. Dajmo to v pomožni razred. Njegova koda je v seznamu 11.3.

Seznam 11.3. Razred Point.Light.java, preprosta abstrakcija točkovnih luči OpenGL ES

Naš pomožni razred vsebuje komponente barve ozadja, razpršene in zrcalne barve svetlobe ter položaj (četrti element je ena). Poleg tega shranimo zadnji identifikator, uporabljen za dani vir, tako da je mogoče ustvariti metodo disableO, ki bo po potrebi izklopila luč. Imamo tudi metodo enableO, ki vzame primerek razreda GL10 in identifikator svetlobnega vira (na primer GL10.GL LIGHT6). Omogoča uporabo osvetlitve, nastavi njene atribute in shrani uporabljeni ID. Metoda disableO preprosto onemogoči uporabo osvetlitve z uporabo nabora članov razreda 1ast.Ligh.tId v metodi enable.

Pri inicializaciji nizov članov razreda uporabljamo razumne privzete vrednosti za barve ozadja, razpršene in zrcalne barve. Svetloba bo bela in ne bo ustvarjala bleščanja, saj je njena zrcalna komponenta črna.

Usmerjeni svetlobni viri

Usmerjeni viri svetlobe so skoraj enaki točkovnim. Edina razlika je, da imajo namesto položaja smer. Način izražanja smeri je nekoliko zmeden. Namesto uporabe vektorja za označevanje smeri OpenGL ES pričakuje, da definiramo eno točko. Smer bo nato določena z uporabo vektorja, ki povezuje to točko in izhodišče. Naslednji delček vam omogoča, da ustvarite usmerjen vir svetlobe, ki prihaja z desne strani sveta:

Lahko ga pretvorimo v vektor:

Drugi atributi, kot sta barva ozadja ali difuzna barva, so enaki tistim pri točkovni luči. Listing 11.4 prikazuje kodo za majhen pomožni razred, ki se uporablja za ustvarjanje usmerjenih luči.

Seznam 11.4. Razred Directi onLi ght.java, preprosta abstrakcija usmerjenih svetlobnih virov v OpenGL ES

Ta pomožni razred je skoraj enak razredu PointLight. Edina razlika je v tem, da je v nizu directi on četrti element ena. Poleg tega se je namesto metode setPosition pojavila metoda setDirecti on. Omogoča vam določitev smeri, na primer takole: (-1; 0; 0), v tem primeru bo svetloba prišla z desne strani. Znotraj metode vse komponente vektorja spremenijo predznak, tako da pretvorimo smer v obliko, ki jo pričakuje OpenGL ES.

Določanje materialov

Material definira več atributov. Kot pri vseh drugih predmetih OpenGL ES je material stanje, ki bo ostalo aktivno, dokler ga znova ne spremenimo ali dokler se kontekst OpenGL ES ne izgubi. Za nastavitev trenutnih materialnih atributov lahko storimo naslednje:

Kot običajno moramo določiti barve ozadja, difuzne in zrcalne barve RGBA. To je mogoče storiti na enak način kot prej - z uporabo nizov števil s plavajočo vejico, sestavljenih iz štirih elementov.

Združevanje teh dejanj v en pomožni razred je zelo preprosto. Rezultat si lahko ogledate v seznamu 11.5.

Seznam 11.5. Materialni razred Java, preprosta abstrakcija materialov OpenGL ES

Tudi tukaj ni nič presenetljivega. Preprosto shranimo tri komponente, ki opisujejo gradivo, in nudimo tudi funkcije za nastavitev njihovih vrednosti in omogočanje metode, ki jih posreduje OpenGL ES.

OpenGL ES ima še enega asa v rokavu, ko gre za materiale. Običajno namesto metode glMaterialfvO uporablja nekaj, kar se imenuje barva materiala. To pomeni, da bo OpenGL ES namesto barv ozadja in razpršenih barv, določenih z metodo glMateri al fv, prevzel barvo oglišč naših modelov kot barve ozadja in razpršene barve materiala. Če želite omogočiti to funkcijo, jo preprosto pokličite:

Običajno to počnem, ker so barve ozadja in difuzne barve pogosto enake. Ker v večini svojih iger in predstavitev ne uporabljam zrcalnih poudarkov, lahko preprosto uporabim to metodo in sploh ne pokličem metode glMaterial fv. Na kakšen način ga boste uporabili, se odločite sami.

Določitev normale

Da bo osvetlitev delovala v OpenGL ES, morate definirati normale vozlišč za vsako vozlišče v modelu. Normala oglišča bi morala biti enotski vektor, ki kaže (običajno) v smeri, v kateri se vrti površina, ki ji oglišče pripada. Na sl. Slika 11.5 prikazuje normale oglišč naše kocke.

riž. 11.5. Normale oglišč za vsako oglišče naše kocke

Normala vozlišča je še en atribut vozlišča, tako kot položaj ali barva. Če želimo izkoristiti normale vozlišč, moramo znova spremeniti razred Verti ces3. Če želite OpenGL ES povedati, kje lahko najde normale za posamezno vozlišče, bomo uporabili metodo gl Normal PointerO, tako kot smo prej uporabljali metode gl VertexPointer ali gl Col ali Pointer. Listing 11.6 prikazuje končno različico razreda Vertices3.

Seznam 11.6. Razred Vertices3.Java, končna različica, ki podpira običajne vrednosti

Razred ima novega člana hasNormal.s, ki spremlja, ali imajo vozlišča normale.

Konstruktor zdaj sprejme tudi parameter hasNormals. Še vedno moramo spremeniti izračun člana vertexSize tako, da vsaki točki, kjer je to mogoče, dodamo tri lebdeče vrednosti.

Kot lahko vidite, ostajata metodi setVertices in setlndices nespremenjeni.

V metodi bindO, ki smo jo pravkar pokazali, uporabljamo iste tehnike z ByteBuffer kot prej, vendar tokrat normalne vrednosti dodajamo z metodo gl Normal Pointer. Za izračun odmika normalnega kazalca je treba upoštevati, ali so podane koordinate teksture in barve.

Kot lahko vidite, se tudi metoda žrebanja ni spremenila; vsa dejanja se zgodijo v metodi povezovanja O.

Na koncu nekoliko spremenimo metodo unbindO. Onemogočimo uporabo običajnih kazalcev, če obstajajo, in ustrezno počistimo stanje OpenGL ES.

Uporaba spremenjenega razreda Verti ces3 je prav tako enostavna kot prej. Poglejmo majhen primer:

Ustvarimo matriko s plavajočo vejico za shranjevanje treh vozlišč, od katerih ima vsaka položaj (prve tri številke v vsaki vrstici) in normalo (zadnje tri številke v vsaki vrstici). V tem primeru določimo trikotnik v ravnini xy, njegove normale pa kažejo v smeri pozitivnega dela osi z.

Vse kar moramo storiti je, da ustvarimo primerek razreda Vertices3 in nastavimo vrednosti tock. Precej enostavno, kajne?

Vsa vezava, risanje in odvezovanje poteka popolnoma enako kot v prejšnji različici razreda. Kot prej lahko dodamo barve vozlišč in koordinate teksture.

Vse skupaj

Sestavimo vse skupaj. Narisati moramo prizor, ki ima globalno osvetlitev, točkovne in usmerjene vire svetlobe. Osvetlili bodo kocko, ki se nahaja na izvoru. Poklicati moramo tudi metodo gl uLookAt. za postavitev kamere. Na sl. 11.6 prikazano videz naš svet.

Kot pri vseh drugih primerih ustvarimo razred z imenom LightTest, ki kot običajno razširi razred GLGame. Vrnil bo primerek razreda LightScreen z uporabo metode getStartScreenO. Razred LightScreen podeduje razred GLScreen (izpis 11.7).

riž. 11.6. Naša prva osvetljena scena

Seznam 11.7. Fragmenti razreda LightTest.java. ustvarjanje osvetlitve z uporabo OpenGL ES

Začnimo z opisom nekaj članov razreda. Kotni člen hrani informacije o trenutnem kotu vrtenja kocke okoli osi y. Član Verti ces3 hrani oglišča modela kocke, ki jih bomo definirali v kratkem. Poleg tega imamo primerke razredov AmbientLight, PointLight in Directional Light ter primerek razreda Material.

Sledi konstruktor. Tu se ustvarijo oglišča modela kocke in naloži se tekstura polja. Inicializiramo tudi luči in materiale. Barva osvetlitve ozadja je svetlo zelena. Usmerjeni vir je rdeče barve in se nahaja na točki (3; 3; 0) našega sveta. Usmerjeni svetlobni vir ima modro difuzno barvo, svetloba pada z leve strani. Za material uporabljamo privzete vrednosti (nekoliko ozadja, bela za difuzno komponento in črna za zrcalno komponento).

Pri metodi nadaljevanja poskrbimo, da se naša tekstura (ponovno) naloži, če se izgubi kontekst.

Metoda createCube je v bistvu nespremenjena od prejšnjih primerov. Vendar pa tokrat vsaki točki dodamo normale, kot je prikazano na sl. 11.5. Sicer pa vse ostaja isto.

Pri metodi posodobitve preprosto povečamo kot vrtenja kocke.

Tukaj postane bolj zanimivo. Prvih nekaj vrstic je okvirna koda za brisanje barvnega in globinskega medpomnilnika, omogočanje globinskega testiranja in nastavitev obsega.

Nato nastavimo projekcijsko matriko enako perspektivni projekcijski matriki z metodo gl uPerspecti ve in uporabimo tudi metodo gl uLookAt za matriko modela-pogleda, zahvaljujoč kateri kamera deluje enako kot na sliki. 11.6.

Nato dovolimo uporabo razsvetljave. Na tej točki še ni bilo definiranih nobenih luči, zato jih definiramo v naslednjih nekaj vrsticah s klicem metode na luči in materialih.

Kot običajno omogočimo tudi teksturiranje in povežemo teksturo polja. Na koncu pokličemo metodo gl RotatefC), da zavrtimo kocko in nato narišemo njena oglišča z uporabo dobro postavljenih klicev instance razreda Verti ces3.

Na koncu metode onemogočimo točkovne in usmerjene luči (ne pozabite, osvetlitev ozadja je globalno stanje), pa tudi teksturiranje in testiranje globine. To je to za osvetlitev v OpenGL ES.

Preostali del učilnice je prazen; v primeru premora nam ni treba izvajati nobenih dejanj. Na sl. Slika 11.7 prikazuje rezultat programa.

riž. 11.7. Prizor, prikazan na sl. 11.6, upodobljeno z OpenGL ES

Nekaj ​​opomb o osvetlitvi v OpenGL ES

Čeprav lahko uporaba osvetlitve doda okus vaši igri, ima svoje omejitve in pasti. Nekaj ​​stvari se morate zavedati.

Uporaba osvetlitve porabi preveč virov, kar je še posebej opazno pri počasnih napravah. Previdno uporabljajte osvetlitev. Več svetlobnih virov kot opišete, več izračunov bo potrebnih za upodabljanje scene.

Položaj/smer točkovnih/usmerjenih svetlobnih virov je treba določiti po nalaganju matrik kamere in preden se matrika pogleda modela pomnoži z drugimi matricami za premikanje in vrtenje predmetov. To je kritično. Če teh navodil ne upoštevate, lahko pride do nepojasnjenih svetlobnih artefaktov.

Ko za spreminjanje velikosti modela uporabite metodo gl Seal ef, bodo njegove normale prav tako prilagojene. To je slabo, ker OpenGL ES pričakuje, da imajo normalne vrednosti parametre v danih enotah. Če se želite izogniti tej težavi, lahko uporabite ukaz glEnable(GL10.GL NORMALIZE) ali v nekaterih okoliščinah gl Enable(GL10 .GL RESCALE N0RMAL). Menim, da je treba uporabiti prvi ukaz, saj ima uporaba drugega omejitve in pasti. Težava je v tem, da normalizacija ali sprememba velikosti normalnih vrednosti zahteva veliko procesorske moči. Najboljša rešitev z vidika zmogljivosti je, da osvetljenih predmetov ne spreminjate.

No, gospodje. V zadnjem času smo se naučili kar nekaj o OpenGL, vključno s tem, kako nadzoruje kamero , delo s teksturami, in tudi z modeli. Čas je, da se pogovorimo o nečem veliko bolj zanimivem, namreč o razsvetljavi. Ta tema je zanimiva, ker v OpenGL ni nič pripravljenega za delo s svetlobo; vse je treba napisati neodvisno z uporabo senčil. V tej objavi si bomo ogledali razsvetljavo Phong. To je precej obsežna tema, zato bomo govorili izključno o njej osvetlitev. V tem, kako so narejeni sence, bomo morali ugotoviti drugič.

Shranjevanje in uporaba običajnih vrednosti

Preden preidemo neposredno na razsvetljavo, potrebujemo nekaj takega, kot je normala.

Vemo že, da imajo modeli oglišča in UV koordinate, ki ustrezajo tem ogliščem. Za ustvarjanje osvetlitve potrebujemo nekaj več informacij o modelih, in sicer normalnih. Normala je enotski vektor, ki ustreza točki (ali alternativno poligonu, vendar to ni naš primer). Kakšno vlogo imajo normalke pri izvedbi osvetlitve, bomo izvedeli v nadaljevanju. Za zdaj je dovolj reči, da so normalne vrednosti res zelo pomembne. Na primer, zaradi njih so površine videti bolj gladke in lahko ločite kroglo od običajnega konveksnega poliedra, kot je ikozaeder. In ker so normalne vrednosti tako pomembne, se moramo naučiti, kako jih ohraniti pri pretvarjanju Blenderjevih modelov v lastno obliko.

Ustrezne spremembe so precej nepomembne. Normale dobimo na enak način, kot smo dobili koordinate vozlišč in UV koordinate:

// del telesa procedure importedModelCreate

za (unsigned int j = 0; j< face.mNumIndices ; ++ j) {
unsigned int index = face.mIndices[ j] ;
aiVector3D pos = mesh->mVertices[ index] ;
aiVector3D uv = mreža-> mTextureCoords[ 0 ] [ indeks] ;
aiVector3D normal = mreža-> mNormals[ indeks] ;

VerticesBuffer[verticesBufferIndex++] = pos.x;
verticesBuffer[ verticesBufferIndex++] = pos.y;
verticesBuffer[verticesBufferIndex++] = pos.z;
verticesBuffer[verticesBufferIndex++] = normal.x;
verticesBuffer[verticesBufferIndex++] = normal.y;
verticesBuffer[verticesBufferIndex++] = normal.z;
verticesBuffer[ verticesBufferIndex++] = uv.x;
verticesBuffer[verticesBufferIndex++] = 1.0f - uv.y;
}

Podobno se spreminja postopek optimizacije modela. In v proceduri modelLoad namesto dveh nizov atributov zdaj potrebujemo tri:

// del telesa procedure modelLoad

GlBindVertexArray(modelVAO) ;
glEnableVertexAttribArray(0) ;
glEnableVertexAttribArray(1) ;
glEnableVertexAttribArray(2) ;

GlBindBuffer(GL_ARRAY_BUFFER, modelVBO);
glBufferData(GL_ARRAY_BUFFER, header- > verticesDataSize, verticesPtr,
GL_STATIC_DRAW);

GLsizei korak = 8 * sizeof(GLfloat) ;
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, korak, nullptr);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, korak,
(const void * ) (3 * sizeof (GLfloat) ) ) ;
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, korak,
(const void * ) (6 * sizeof (GLfloat) ) ) ;

Dodatno potrebujemo še uniformno spremenljivko z matriko M:

GLint uniformM = getUniformLocation(programId, "M" ) ;

// ...

GlUniformMatrix4fv(uniformM, 1, GL_FALSE, & stolpM[ 0 ] [ 0 ] );

... za pravilno vrtenje normale v prostoru v senčniku vozlišč:

#različica 330 jedro

Postavitev (lokacija = 0 ) v vec3 vertexPos;
postavitev (lokacija = 1) v vec3 vertexNorm;
postavitev (lokacija = 2) v vec2 vertexUV;

uniforma mat4 MVP;
enotna podloga4 M;

ven vec2 fragmentUV;
ven vec3 fragmentNormal;
ven vec3 fragmentPos;

void main() (
fragmentUV = vertexUV;
fragmentNormal = (M * vec4 (vertexNorm, 0 ) ) . xyz;
fragmentPos = (M * vec4 (vertexPos, 1 ) ) . xyz;

gl_Pozicija = MVP * vec4 (vertexPos, 1) ;
}

Nazadnje, senčnik fragmentov vzame normalo, interpolirano čez tri vozlišča:

// ...

void main() (

// ...
}

Na ta preprost način dobimo normale za fragmenti.

Kaj je razsvetljava Phong?

Kot že omenjeno, osvetlitev v OpenGL v senčnikih zapiše programer sam. Jasno je, da obstaja več kot en način za izvedbo te osvetlitve, vsak s svojo stopnjo realizma in zahtevami po virih. In vsaka metoda ima lahko še vedno nešteto specifičnih implementacij. Kolikor razumem, je učinkovita in realistična razsvetljava v realnem času še vedno področje aktivnih raziskav. V tej objavi si bomo ogledali osvetlitev Phong, ki je precej realistična in enostavna za izvedbo.

Pomembno je razumeti razliko med naslednjimi pojmi:

  • Gouraudovo senčenje je, ko izračunate osvetljenost vsake vozlišča in osvetlitev fragmentov med njimi interpolirate;
  • Phong senčenje - ko se osvetlitev izračuna ločeno za vsak fragment;
  • Osvetlitev Phong ali Phongov refleksijski model je specifična metoda osvetlitve, o kateri razpravljamo v tem članku in ki se lahko uporablja tako pri senčenju Gouraud kot Phong;

Ni presenetljivo, da se Phong senčenje in Phong osvetlitev pogosto zamenjujeta, v nekaterih vadnicah pa lahko preberete neumnosti, kot je "Ideja Phong senčenja je uporaba treh komponent ...", zaradi česar takoj močno dvomite v avtoriteto oseba, ki je napisala to vadnico.

Kolikor sem lahko razumel, se v sodobnih aplikacijah senčenje Gouraud skoraj ne uporablja, namesto tega se daje prednost senčenju Phong. V tej objavi bomo uporabili tudi senčenje Phong, to pomeni, da bo osvetlitev izračunana posebej za vsak fragment. Posebna metoda osvetlitve, ki jo bomo uporabili, je osvetlitev Phong. Ta metoda je naslednja.

Tri komponente osvetlitve se izračunajo z različnimi formulami:

  • Ambientalna osvetlitev je imitacija svetlobe, ki je dosegla določeno točko, potem ko se je odbila od drugih predmetov. Pri izračunu osvetlitve ozadja se ne upoštevajo ne normalne vrednosti ne trenutni položaj kamere;
  • Difuzna svetloba je svetloba iz vira, ki se razprši po udarcu v določeno točko. Odvisno od kota, pod katerim pada svetloba, postane osvetlitev močnejša ali šibkejša. To upošteva običajne vrednosti, ne pa tudi položaja kamere;
  • Zrcalna osvetlitev je svetloba iz vira, ki se odbije po udarcu v dano točko. Odbita svetloba je vidna, če vstopi v kamero. Zato sta tu upoštevana normalna vrednost in položaj kamere;

Rezultati se nato seštejejo, da dobimo skupno osvetlitev.

Da je stvar še bolj zanimiva, obstajajo različni viri svetlobe. Očitno sonce zunaj in svetilka v temi osvetljujeta prizor zelo različno. Najprej si bomo ogledali najpreprostejši vir - usmerjeno svetlobo.

Usmerjena svetloba

Usmerjena svetloba je imitacija neskončno oddaljenega svetlobnega vira. Vzemimo za primer Sonce. Sonce je zelo daleč od zemlje. Zato lahko na površju Zemlje vse sončne žarke z veliko natančnostjo štejemo za vzporedne. Za usmerjeno svetlobo je značilna njena smer, barva in nekateri koeficienti, ki jih bomo potrebovali spodaj:

struct DirectionalLight(
smer vec3;

barva vec3;
float ambientIntensity;
float diffuseIntensity;
float specularIntensity;
} ;

V kodi senčila fragmentov bomo definirali proceduro calcDirectionalLight, ki bo uporabljena nekako takole:

v vec3 fragmentPos;
enotna vec3 kameraPos;
enotna DirectionalLight usmerjena svetloba;

// ...

void main() (
// normalno je treba popraviti po interpolaciji
vec3 normalno = normaliziraj (fragmentNormal) ;


usmerjena svetloba);

// ...
}

Razmislimo o izvajanju postopka.

vec4 calcDirectionalLight(vec3 normalno, vec3 fragmentToCamera,
Usmerjena svetloba) (
vec4 ambientColor = vec4 (svetla barva, 1) * svetloba. ambientIntensity ;

// ...
}

Najprej se izračuna prva komponenta - osvetlitev ozadja. To je preprosto barva oddane svetlobe, pomnožena z intenzivnostjo svetlobe ozadja. Zaenkrat je vse preprosto.

// ...

float diffuseFactor = max (0,0 , pika (normalno, - smer svetlobe ) ) ;
vec4 diffuseColor = vec4 (svetla barva, 1) * svetloba. diffuseIntensity
* difuzni faktor;

// ...

Razpršena razsvetljava. Spremenljivka diffuseFactor predstavlja kosinus kota med normalo na fragment in vektorjem, usmerjenim od fragmenta na vir svetlobe. Če svetloba vpada pravokotno na površino, je kot enak nič. Kosinus tega kota je enak ena in osvetlitev je največja (glejte članek v Wikipediji o Lambertovem zakonu). Z večanjem kota se kosinus zmanjšuje in postane enak nič, če je svetloba vzporedna s površino. Če je kosinus negativen, potem je vir svetlobe nekje za površino in ni osvetljen, zato negativne vrednosti spremenimo na nič z max(0.0, ...) . Poleg kota, pod katerim pada svetloba, se upošteva tudi razpršena jakost razpršene svetlobe.

// ...
vec3 lightReflect = normalize(reflect(light. direction, normal));
float specularFactor = pow(
max (0,0 , pika (fragmentToCamera, lightReflect) ,
materialSpecularFactor
) ;
vec4 specularColor = svetloba. specularIntensity * vec4(light.color, 1)
* materialSpecularIntensity * specularFactor;
// ...

Indirektna osvetlitev. Spremenljivka lightReflect je enotski vektor, ki določa smer odbite svetlobe. Spremenljivka specularFactor se izračuna na podoben način kot diffuseFactor, le da tokrat upošteva kosinus kota med smerjo, v kateri se je svetloba odbila, in smerjo od fragmenta do kamere. Če je ta kot enak nič, potem odbita svetloba leti neposredno v kamero in bleščanje na površini je največje. Če je kot velik, ne sme biti vidno bleščanje. Tu je materialSpecularFactor uniformna spremenljivka. Večja kot je, manjša je površina bleščanja na površini predmeta. Spremenljivka materialSpecularIntensity se uporablja tudi za določanje svetlosti svetlih delov. Upoštevajte, da so vse to lastnosti materiala, ne svetlobe. Na primer, kovina odbija svetlobo in ima zato bleščanje. Toda les ne odbija svetlobe in potem na drevesih nikoli ne vidite bleščanja (seveda, če je površina suha in tako naprej).

V zgornji kodi ima svetloba lastnost specularIntensity. Vendar bi ga smeli uporabljati le za namene odpravljanja napak, da poudarite poudarke iz določenega vira svetlobe. V različici kode za izdajo mora biti ta koeficient bodisi enak eni bodisi popolnoma odstranjen iz kode.

Nazadnje se dodajo tri komponente in vrne rezultat:

// ...

vrni ambientColor + diffuseColor + specularColor;
}

Ni tako težko, kajne?

Točkovni vir svetlobe

Točkovni vir svetlobe je na primer goreča žarnica. Svetloba žarnice je usmerjena v vse smeri. Zato točkovnega vira svetlobe ne označuje smer svetlobe, temveč položaj vira v prostoru:

struct PointLight(
položaj vec3;

barva vec3;
float ambientIntensity;
float diffuseIntensity;
float specularIntensity; // za namene odpravljanja napak mora biti nastavljen na 1.0
} ;

Osvetlitev iz točkovnega svetlobnega vira je enostavno izračunati z že obstoječim postopkom calcDirectionalLight:

vec4 calcPointLight(vec3 normalno, vec3 fragmentToCamera,
PointLight lučka) (
vec3 lightDirection = normalize (fragmentPos - light. position ) ;
lebdeča razdalja = dolžina (fragmentPos - svetlobni položaj) ;
float pointFactor = 1,0 / (1,0 + pow(razdalja, 2));

DirectionalLight tempDirectionalLight = DirectionalLight(
LightDirection,
svetloba. barva,
svetloba. ambientIntensity
svetloba. diffuseIntensity
svetloba. specularIntensity
) ;
return pointFactor * calcDirectionalLight(normal, fragmentToCamera,
tempDirectionalLight);
}

Če imate koordinate fragmenta in vira svetlobe, lahko preprosto izračunate smer svetlobe na dani fragment skozi razliko vektorjev. Množitelj pointFactor odraža dejstvo, da svetloba slabi s kvadratom razdalje do njenega vira (v skladu s formulo za odvisnost površine krogle od polmera). Pri izračunu pointFactorja se delitelju doda še ena, da se prepreči možnost deljenja z ničlo. Nato se vse izračuna na popolnoma enak način kot za usmerjeno svetlobo.

Ospredje

Primer tega vira svetlobe je svetilka. Podoben je točkovnemu viru svetlobe, le da ima dodatno smer in vplivni kot (cutoff):

struct SpotLight (
smer vec3;
položaj vec3;
izklop plovca;

barva vec3;
float ambientIntensity;
float diffuseIntensity;
float specularIntensity; // za namene odpravljanja napak mora biti nastavljen na 1.0
} ;

Ustrezen postopek:

vec4 calcSpotLight(vec3 normalno, vec3 fragmentToCamera,
Lučka SpotLight) (
vec3 spotLightDirection = normalize (fragmentPos - light. position ) ;
float spotAngleCos = pika (spotLightDirection, light. direction) ;
plavajoče slabljenje = (1,0 - 1,0 * (1,0 - spotAngleCos) /
(1.0 - lahka meja) );
float spotFactor = float (spotAngleCos > light. cutoff ) * dušenje;

PointLight tempPointLight = PointLight(
svetloba. položaj
svetloba. barva,
svetloba. ambientIntensity
svetloba. diffuseIntensity
svetloba. ambientIntensity
) ;
vrni spotFactor * calcPointLight(normal, fragmentToCamera,
tempPointLight);
}

Smer svetlobe se izračuna na enak način kot pri točkovnem viru. Nato se izračuna kosinus kota med to smerjo in smerjo, določeno v lastnostih samega svetlobnega vira. Uporaba izraza float(spotAngleCos > light.cutoff) luč je togo pritrjena na določen kot. Atenuacijski množitelj dodaja gladka oslabitev svetlobe, ko se drobci odmikajo od smeri svetlobe, določene v lastnostih vira. Po tem se vsi izračuni zmanjšajo na izračune za točkovni vir svetlobe.

Korekcija gama

Celoten glavni postopek v senčniku fragmentov izgleda takole:

void main() (
// normalno je treba popraviti po interpolaciji
vec3 normalno = normaliziraj (fragmentNormal) ;
vec3 fragmentToCamera = normalize(cameraPos - fragmentPos) ;

vec4 directColor = calcDirectionalLight(normal, fragmentToCamera,
usmerjena svetloba);
vec4 pointColor = calcPointLight(normal, fragmentToCamera,
pointLight);
vec4 spotColor = calcSpotLight(normal, fragmentToCamera, spotLight) ;
vec4 linearColor = texture(textureSampler, fragmentUV) *
(vec4(materialEmission, 1) + directColor +
pointColor + spotColor);

vec4 gama = vec4 (vec3 (1,0 / 2,2) , 1 ) ;
barva = pow(linearnabarva, gama); // barva popravljena gama
}

Ne posvečajte veliko pozornosti materialnim emisijam. To je samo še ena lastnost materiala, ki doda svoj sijaj. Mnogi predmeti se svetijo sami. Vzemite enake žarnice, ki služijo kot vir svetlobe za druge predmete. Morali bi jih videti v popolni temi, tudi če žarnice ne osvetljuje noben drug vir svetlobe, kajne?

Kar si resnično zasluži pozornost, je korekcija gama, ki je sestavljena iz dviga vseh svetlobnih komponent na potenco 1/2,2. Doslej smo delali v linearnem barvnem prostoru ob predpostavki, da je barva z intenzivnostjo 1,0 dvakrat svetlejša od barve z intenzivnostjo 0,5. Težava je v tem, da človeško oko ne zaznava svetlosti linearno. Zato je za realistično osvetlitev potrebno opraviti korekcijo gama po vseh izračunih v linearnem prostoru.

Upoštevati je treba, da pri shranjevanju slike sodobni grafični urejevalniki izvajajo tudi korekcijo gama. Zato morate pred uporabo tekstur preklicati ta popravek gama. Na srečo ni težko.

Dovolj je, da zamenjate vse konstante v kodi za nalaganje teksture:

GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
GL_COMPRESSED_RGBA_S3TC_DXT5_EXT

GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT

… oz. To bo pomenilo, da je bil na sliki uporabljen popravek gama in ga je treba razveljaviti. OpenGL bo poskrbel za ostalo.

V realnih aplikacijah je parameter gama (imamo gamma = 2,2) bolje postavljen v nastavitve programa, da ga lahko uporabnik po želji nekoliko prilagodi svojemu monitorju.

Zaključek

Čas je za ogled slik!

Tukaj vidimo različne komponente osvetlitve. Od leve proti desni, zgoraj navzdol: ozadje, razpršeno, odbito, vse tri skupaj. Kot lahko vidite, je bil sceni dodan model torusa. Zaradi zapletene postavitve normal je ta model priporočljiv za testiranje razsvetljave.

Različni viri svetlobe. Od leve proti desni, zgoraj navzdol: beli reflektor, rdeči reflektor, modri reflektor, vse tri skupaj.

Naj ponovno opozorim, da ima isti način osvetljevanja lahko različne izvedbe. Lastnosti materiala lahko na primer nastavite na ambientalno, difuzno in zrcalno barvo, kar vam bo omogočilo risanje rdečih predmetov, ki razpršijo zeleno in imajo modre poudarke. Pri nekaterih izvedbah osvetlitve Phong sem videl, da se osvetlitev ozadja izračuna enkrat in ne za vsako luč. Videl sem tudi izvedbe, pri katerih svetloba iz točkovnega vira ni zbledela le sorazmerno s kvadratom razdalje do njega (d * d), temveč v skladu s splošnejšo formulo (v slogu A + B*d + C* d*d). Nekdo naredi ambientalno intenzivnost in razpršeno intenzivnost lastnost ne samo vira svetlobe, ampak tudi materiala. Nisem pa prepričan, koliko ima vse to opraviti z realistično osvetlitvijo. Lahko pa se igrate z vsem tem kot z domačo nalogo.

Dela let. Vološin Maksimilijan. HRABROST PESNIKA. 1. Uredite pesem kot besedilo čezoceanske pošiljke: Suhost, jasnost, pritisk - vsaka beseda je na preži.

Rezati črko za črko na trdem in utesnjenem kamnu: Čim redkejše so besede, tem intenzivnejša je njihova moč. Voljni naboj misli je enak tihim kiticam.

Izbrišite besede "Lepota", "Navdih" iz slovarja - podli žargon rimarjev. Za pesnika - razumevanja: Resnica, načrt, načrt, enakovrednost, jedrnatost in natančnost. V trezni, trdi obrti je navdih in čast pesnika: Ostriti transcendentalno čuječnost v gluhonemi materiji. Voloshin M.A. Knjižnica: Oryolska regionalna znanstvena univerzalna javna knjižnica poimenovana po. I.A. Bunina. - M., ; Izbrana dela: V 2 zv.

M., ; Rdeči dim: Zgodbe. - M., ; Gladyshev iz izvidniške čete: Zgodbe. - M., ; Echelon; Neizogibnost: Romani. Veliko je prevajal marijske in udmurtske pesnike. Občasno sem se preizkusil tudi v prozi. Op. Maksimilijan Aleksandrovič Vološin () je eden največjih pesnikov prve tretjine 20. stoletja. Je nadarjen umetnik, večplasten lirik, ki je prehodil pot od simbolističnih, ezoteričnih pesmi do državljansko-žurnalistične in znanstveno-filozofske poezije, preko antropozofskih nagnjenj – do »ideala božjega mesta«.

Predlagana publikacija daje bralcu priložnost, da se seznani ne le z Vološinovimi najboljšimi pesniškimi deli, ampak tudi z njegovimi najzanimivejšimi deli o estetiki, memoarski prozi, novinarstvu in pismih, povezanih z dramatičnimi dogodki v življenju držav. Avtor. Vološin Maksimilijan. Vse pesmi avtorja. delo. Hrabrost pesnika. 2. Zvezde. Ustvarite najljubše zbirke avtorjev in pesmi!

Klepetajte s podobno mislečimi ljudmi! Pišite ocene, sodelujte v pesniških dvobojih in tekmovanjih! Pridružite se najboljšim! Hvala, ker ste se pridružili Poembooku! Pismo s podatki za dostop do računa je bilo poslano na vaš e-mail!

Prijaviti se morate v 24 urah. V nasprotnem primeru bo račun izbrisan! Registrirani uporabniki prejmejo številne ugodnosti: Objavite poezijo - spoznajte svoj talent! Ustvarite najljubše zbirke avtorjev in pesmi! Klepetajte s podobno mislečimi ljudmi! Pišite ocene, sodelujte v pesniških dvobojih in tekmovanjih!. Maksimilijan Vološin. Opis. Maksimilijan Aleksandrovič Vološin je eden največjih pesnikov prve tretjine 20. stoletja.

Je nadarjen umetnik, večplasten lirik, ki je prehodil pot od simbolističnih, ezoteričnih pesnitev do državljansko-publicistične in znanstveno-filozofske poezije, preko antropozofskih nagnjenj – do »ideala božjega mesta«. Predlagana publikacija daje bralcu priložnost, da se seznani ne le z Vološinovimi najboljšimi pesniškimi deli, temveč tudi z njegovimi najzanimivejšimi deli o estetiki, memoarski prozi, novinarstvu in pismih, povezanih z dramatiko.

Izbrana dela in pisma. M. A. Vološin. Cena. drgnite. Maksimilijan Aleksandrovič Vološin je eden največjih pesnikov prve tretjine 20. stoletja. Je nadarjen umetnik, večplasten lirik, ki je prehodil pot od simbolističnih, ezoteričnih pesnitev do državljansko-publicistične in znanstveno-filozofske poezije, preko antropozofskih nagnjenj – do »ideala božjega mesta«.

Voloshin M.A., Pesnikova hrabrost: izbrana dela in pisma. serija: Nova knjižnica ruske klasike: obvezen izvod Parada, mesto, stran, Opis knjige. Maksimilijan Aleksandrovič Vološin () je eden največjih pesnikov prve tretjine 20. stoletja. Je nadarjen umetnik, večplasten lirik, ki je prehodil pot od simbolistične, ezoterične pesmi do državljansko-publicistične in znanstveno-filozofske poezije, prek antropozofskih nagnjenj – do »ideala božjega mesta«.

kategorije Navigacija po objavi

Brez vira svetlobe slika ni vidna. Za inicializacijo vira in omogočanje procesorja za izračun vpliva vira na objekte preprosto izvedite ukaze: glEnable(gl_lighting); // omogoči način analize osvetlitve

GlEnable(gl_light0); // v sceno vključi določen (ničelni) vir z njegovimi značilnostmi

Če želite onemogočiti vir, uporabite funkcijo Disable(). Vir svetlobe se privzeto nahaja v prostoru s koordinatami (0,0,∞). Vir svetlobe lahko ustvarite kjer koli v prostoru slike.

Knjižnica OpenGl podpira štiri vrste svetlobnih virov:

  • osvetlitev ozadja (ambientalna osvetlitev),
  • točkovni viri,
  • reflektorji,
  • oddaljeni viri svetlobe (oddaljena svetloba).
Vsak vir svetlobe ima svoj nabor značilnosti.
Značilnosti vira svetlobe ustrezajo parametrom modela Phong.
Za nastavitev vektorskih parametrov uporabite funkcijo glLightfv(), ki ima naslednjo obliko:

glLightfv(vir, parameter, kazalec_na_matriko);

Obstajajo štirje vektorski parametri, ki določajo položaj in smer izvornih žarkov ter barvno sestavo njegovih komponent - ozadje, difuzno in zrcalno.
Za nastavitev skalarnih parametrov v OpenGL uporabite funkcijo glLightf():

glLightf(vir, parameter, vrednost);

Recimo, da želite v sceno vključiti vir GL_LIGHT0, ki naj se nahaja na točki (1.0, 2.0, 3.0). Izvorni položaj se v programu shrani kot točka v enotnih koordinatah:

GLfloat light0_pos=(1.0, 2.0, 3.0, 1.0);

Če je četrta komponenta te točke enaka nič, se točkovni vir spremeni v oddaljeni vir, za katerega je pomembna samo smer žarkov:

GLfloat light0_dir=(1.0, 2.0, 3.0, 0.0);

Nato se določi barvna sestava ozadja, difuzijske in zrcalne komponente vira. Če ima v obravnavanem primeru vir zrcalno komponento bele barve, komponente ozadja in difuzije pa morajo biti rdeče, potem je fragment programa, ki tvori vir, videti takole:

GLfloat diffise0= (1,0, 0,0, 0,0, 1,0);

GLfloat ambient0=(1,0, 0,0, 0,0, 1,0);

GLfloat specular0=(1,0, 1,0, 1,0, 1,0);

GlEnable(GL_LIGHTING);

GlEnable(GL_LIGHT0);

GlLightfv(GL_LIGHT0, GL_POSITION, light0_pos);

GlLightfv(GL_LIGHT0, GL_AMBIENT, ambient0);

GlLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse0);

GlLightfv(GL_LIGHT0, GL_SPECULAR, specular0);

V sceno lahko vključite tudi globalno osvetlitev ozadja, ki ni povezana z nobenim posameznim virom svetlobe. Če želite na primer vse predmete v prizoru zatemnjeno osvetliti z belo, morate v program vključiti naslednji del kode:

GLfloat global_ambient=(0,1, 0,1, 0,1, 1,0);

GlLightModelfv(GL_LIGHT_MODEL_AMBIENT, globalni_ambient);

V modelu osvetlitve ima izraz, ki upošteva razdaljo do vira, obliko:

K= 1/(a+ b*d+ c*d^2)

In konstantne, linearne in kvadratne komponente. Ustrezni koeficienti za vsak vir se nastavijo posebej z uporabo funkcije za nastavitev skalarnih parametrov, na primer:

GlLightf(GL_LIGHT0, GL_CONSTANT_ATTENATION, a);

Če želite pretvoriti točkovni vir v reflektor, morate določiti smer žarka reflektorja (GL_SPOT_DIRECTION), indikator funkcije porazdelitve intenzivnosti (GL_SPOT_EXPONENT) in kot razpršitve žarka (GL_SPOT_CUTTOF). Ti parametri so nastavljeni s funkcijama glLightf() in glLightfv().

Privzeti parametri za vire svetlobe so prikazani v tabeli 3.

Privzete nastavitve za luči

Tabela 3

Ime parametra Privzeta vrednost Vsebina
GL_AMBIENT (0.0, 0.0, 0.0, 1.0) ambientalna intenzivnost svetlobe RGBA
GL_DIFUZNO (1.0, 1.0, 1.0, 1.0) difuzna jakost svetlobe RGBA
GL_SPECULAR (1.0, 1.0, 1.0, 1.0) zrcalna jakost svetlobe RGBA
GL_POSITION (0.0, 0.0, 1.0, 0.0) (x, y, z, w) položaj svetlobe
GL_SPOT_DIRECTION (0.0, 0.0, -1.0) (x, y, z) smer reflektorja
GL_SPOT_EXPONENT 0.0 žaromet eksponent
GL_SPOT_CUTOFF 180.0 mejni kot reflektorja
GL_CONSTANT_ATTENUATION 1.0 stalni faktor slabljenja
GL_LINEAR_ATTENUATION 0.0 linearni faktor slabljenja
GL_QUADRATIC_ATTENUATION 0.0 kvadratni faktor slabljenja