Opengl-da nuqta yorug'lik manbai. Biz OpenGL: Phong lighting bo'yicha o'rganishimizni davom ettiramiz. Hammasini bir joyga qo'yish

OpenGL ES-dagi yorug'lik 3D o'yinlarga yoqimli teginish berishi mumkin bo'lgan yoqimli xususiyatdir. Ushbu funksiyadan foydalanish uchun biz birinchi navbatda OpenGL ES yoritish modelini tushunishimiz kerak.

Yoritish qanday ishlaydi

Keling, yorug'lik qanday ishlashini o'ylab ko'raylik. Avval bizga yorug'lik chiqaradigan yorug'lik manbai kerak. Bundan tashqari, sizga yoritilgan ob'ekt kerak bo'ladi. Va nihoyat, bizga yorug'lik manbai tomonidan yuborilgan va ob'ekt tomonidan aks ettirilgan fotonlarni qabul qiluvchi ko'zlar yoki kamera kabi sensor kerak. Yoritish ob'ektning idrok qilingan rangini quyidagilarga qarab o'zgartiradi: yorug'lik manbasining turiga; yorug'lik manbasining rangi yoki intensivligi; yorug'lik manbasining holati va uning yoritilgan ob'ektga nisbatan yo'nalishi; ob'ektning materiali va tuzilishi.

Yorug'likning ob'ekt tomonidan aks ettirish intensivligi ko'p omillarga bog'liq. Biz e'tibor beradigan eng muhim omil - yorug'lik nurining sirtga tushadigan burchagi. Bu burchak to'g'ri burchakka qanchalik yaqin bo'lsa, ob'ektdan yorug'lik qanchalik kuchli aks etadi. Bu rasmda ko'rsatilgan. 11.1.

Yorug'lik nuri sirtga tegsa, u ikki xil yo'nalishda sakrab chiqadi. Yorug'likning katta qismi diffuz tarzda aks etadi. Bu shuni anglatadiki, aks ettirilgan yorug'lik nurlari ob'ekt yuzasida notekis ravishda tasodifiy tarqaladi. Ba'zi nurlar aniq aks ettiriladi. Bu shuni anglatadiki, yorug'lik nurlari xuddi mukammal oynaga urilgandek orqaga qaytadi. Shaklda. 11.2-rasmda diffuz va ko'zgu aks ettirish o'rtasidagi farq ko'rsatilgan.

Guruch. 11.1. Burchak to'g'ri burchakka qanchalik yaqin bo'lsa, aks ettirilgan nurning intensivligi shunchalik katta bo'ladi.

Guruch. 11.2. Diffuz va spekulyar aks ettirish

Ko'zgu ob'ektlarda diqqatga sazovor joylar sifatida paydo bo'ladi. Yorug'lik ob'ektdan ko'zga ko'rinadigan tarzda o'tadimi yoki yo'qmi, u yaratilgan materialga bog'liq. Noto'g'ri yoki qo'pol teriga o'xshash yuzalarga ega bo'lgan narsalar ko'proq yorqin ranglarga ega emas. Shisha yoki marmar kabi silliq yuzaga ega bo'lgan narsalar bu yorug'lik artefaktlarini ko'rsatadi. Albatta, shisha yoki marmar mukammal silliq emas, lekin yog'och yoki inson terisi bilan solishtirganda, ular.

Yorug'lik sirtga tushganda, uning aks etishi ham rangiga qarab o'zgaradi kimyoviy tarkibi yoritilgan ob'ekt. Bizga qizil ko'rinadigan ob'ektlar yorug'likning faqat qizil qismlarini aks ettiradi va boshqa barcha chastotalarni o'zlashtiradi. Qora ob'ekt - bu unga tushadigan deyarli barcha yorug'likni o'zlashtiradigan narsa.

OpenGL ES yorug'lik manbalari va ob'ekt materiallarini aniqlash orqali haqiqiy hayot xatti-harakatlarini taqlid qilish imkonini beradi.

Yorug'lik manbalari

Biz turli xil yorug'lik manbalari bilan o'ralganmiz. Quyosh doimo o'z fotonlarini yuboradi. Monitorlar tunda bizni yoqimli nur bilan o'rab turgan yorug'lik chiqaradi. Lampochka va faralar qorong'uda turli xil narsalar bilan to'qnashuvdan qochishimizga yordam beradi. OpenGL ES to'rt turdagi yorug'lik manbalarini yaratishga imkon beradi.

Orqa yorug'lik. Bu o'z-o'zidan yorug'lik manbai emas, balki boshqa yorug'lik manbalaridan fotonlarning paydo bo'lishining natijasidir. Birgalikda bu tasodifiy fotonlar hech qanday yo'nalishga ega bo'lmagan va barcha ob'ektlarni teng ravishda yoritadigan doimiy yorug'lik darajasini yaratadi.

Nuqtali yorug'lik manbalari. Ular kosmosda mavqega ega va barcha yo'nalishlarda yorug'lik chiqaradilar. Misol uchun, lampochka yorug'likning nuqta manbai hisoblanadi.

Yo'nalishli yorug'lik manbalari. OpenGL ES da yo'nalish sifatida ifodalangan. Ular cheksiz uzoqlikda joylashgan deb taxmin qilinadi. Ideal holda, Quyosh bunday manba bo'lishi mumkin. Quyoshdan keladigan barcha yorug'lik nurlari Yer bilan Quyosh orasidagi masofa tufayli Yerga bir xil burchak ostida tushadi deb taxmin qilishimiz mumkin.

Oh lampalar. Bu chiroqlar nuqta chiroqlariga o'xshaydi, chunki ular kosmosda qat'iy pozitsiyaga ega. Bundan tashqari, ular yorug'lik nurlarini chiqaradigan yo'nalishga ega. Ular ma'lum bir radius bilan cheklangan yorug'lik konusini yaratadilar. Bunday yorug'lik manbasiga misol ko'cha chiroqidir.

Biz faqat orqa yorug'likni, shuningdek, nuqta va yo'nalishli yorug'lik manbalarini ko'rib chiqamiz. OpenGL ESda yoritishni hisoblash usuli tufayli Android qurilmalarining cheklangan GPUlarida chiroqlardan foydalanish odatda qiyin. Nega bunday bo'lganini tez orada tushunasiz.

Yorug'lik manbasining joylashuvi va yo'nalishiga qo'shimcha ravishda, OpenGL ES yorug'likning rangi yoki intensivligini aniqlash imkonini beradi. Ushbu xususiyatlar RGBA rangi yordamida ifodalanadi. Biroq, OpenGL ES bitta manba uchun bitta emas, balki to'rt xil rangni aniqlashni talab qiladi.

Ajratish - ob'ektning soyalanishiga hissa qo'shadigan intensivlik/rang. Ob'ekt yorug'lik manbasiga nisbatan joylashishi yoki yo'nalishidan qat'i nazar, barcha yo'nalishlardan teng ravishda yoritiladi.

Diffuz - diffuz aks ettirishni hisoblashdan keyin ob'ektni yoritadigan yorug'likning intensivligi/rangi. Ob'ektning yorug'lik manbasiga qaramagan qirralari, xuddi haqiqiy hayotda bo'lgani kabi, yoqilmaydi.

Specular - tarqoq rangga o'xshash intensivlik / rang. Biroq, u faqat yorug'lik manbai va sensorga nisbatan ma'lum bir yo'nalishga ega bo'lgan ob'ektning nuqtalariga ta'sir qiladi.

Emissiv - bu haqiqiy dunyo fizikasi ilovalarida juda cheklangan foydalanishga ega bo'lgan juda murakkab rang hisobi, shuning uchun biz bu erda uni qamrab olmaymiz.

Ko'pincha biz yorug'lik manbasining diffuz va aniq intensivliklaridan foydalanamiz va qolgan ikkitasi uchun standart qiymatlarni belgilaymiz. Bundan tashqari, ko'pincha biz diffuz va aniq intensivlik uchun bir xil RGBA rangidan foydalanamiz.

materiallar

Bizning dunyomizdagi barcha ob'ektlar ma'lum bir materialdan yasalgan. Har bir material ob'ektga tushgan yorug'lik qanday aks etishini aniqlaydi va aks ettirilgan yorug'lik rangini o'zgartiradi. OpenGL ES sizga yorug'lik manbai kabi material uchun bir xil to'rtta RGBA rangini aniqlash imkonini beradi.

Ajratish - Sahnadagi har qanday yorug'lik manbasining fon rangi bilan uyg'unlashadigan rang.

Tarqalgan - har qanday yorug'lik manbasining diffuz rangi bilan birlashadigan rang.

Specular - har qanday yorug'lik manbasining spekulyar rangi bilan birlashadigan rang. U ob'ekt yuzasida yorqin joylarni yaratish uchun ishlatiladi.

Emissiv - biz ushbu rang turiga e'tibor bermaslikda davom etamiz, chunki u bizning kontekstimizda deyarli ishlatilmaydi.

11.3-rasmda dastlabki uch turdagi material/yorug'lik xossalari ko'rsatilgan: orqa yorug'lik, diffuz va aynali.

Guruch. 11.3. Har xil turdagi materiallar/chiroqlar: faqat orqa yorug'lik (chapda), faqat diffuz (o'rtada), orqa yorug'lik va diffuz rang, yorqin ranglar bilan (o'ngda)

Shaklda. 11.3 materiallar va yorug'lik manbalarining turli xususiyatlarining rangga ta'sirini ko'rsatadi. Orqa yorug'lik o'lchamni teng ravishda yoritadi. Tarqalgan yorug'lik yorug'lik nurlarining ob'ektga tushish burchagiga qarab aks etadi; yorug'lik manbasiga to'g'ridan-to'g'ri qaragan joylar yorqinroq yoritiladi, yorug'lik yeta olmaydigan joylar qorong'i bo'ladi. To'g'ri tasvirda siz orqa yorug'lik, atrof-muhit va aynali yorug'likning kombinatsiyasini ko'rishingiz mumkin. Ko'zga ko'rinadigan yorug'lik o'zini sferada oq nuqta sifatida namoyon qiladi.

OpenGL ES yoritishni qanday hisoblaydi: Vertex Normals

Ob'ektdan aks ettirilgan yorug'likning intensivligi uning ob'ektga tushish burchagiga bog'liqligini bilasiz. OpenGL ES yorug'likni hisoblash uchun ushbu faktdan foydalanadi. Buning uchun u kodda to'qimalarning koordinatalari yoki cho'qqi ranglari bilan bir xil tarzda aniqlanishi kerak bo'lgan vertex normalaridan foydalanadi. Shaklda. 11.4-rasmda shar va uning cho'qqi normallari ko'rsatilgan.

Guruch. 11.4. Sfera va uning uchi normalari

Normallar - bu sirt qaragan yo'nalishini ko'rsatadigan birlik vektorlari. Bizning holatlarimizda sirt uchburchakdir. Sirt normalini belgilash o'rniga biz normal cho'qqisini aniqlaymiz. Ushbu normalar orasidagi farq shundaki, normal cho'qqi normal sirt bilan bir xil yo'nalishni ko'rsatmasligi mumkin. Bu rasmda aniq ko'rinadi. 11.4, bu erda har bir cho'qqi normali cho'qqi tegishli bo'lgan barcha uchburchaklarning o'rtacha normali hisoblanadi. Bu o'rtacha ob'ektning silliq soyasini yaratish uchun amalga oshiriladi.

Yoritish va cho'qqi normalari yordamida ob'ektni ko'rsatishda OpenGL ES har bir cho'qqi va yorug'lik manbai o'rtasidagi burchakni aniqlaydi. Agar u bu burchakni bilsa, u materialning xususiyatlariga asoslanib, cho'qqi rangini hisoblashi mumkin. Yakuniy natija har bir uchburchakning rangi bo'lib, u har bir uchburchakka boshqa uchlarning hisoblangan ranglari bilan birgalikda qo'llaniladi. Ushbu ishlatilgan rang biz ob'ektga qo'llaydigan har qanday tekstura o'zgarishlari bilan birlashtiriladi.

Bu juda qo'rqinchli tuyuladi, lekin aslida hammasi unchalik yomon emas. Biz yorug'likdan foydalanishni yoqishimiz va yorug'lik manbalarini, tasvirlangan ob'ektning materialini va cho'qqi normalarini aniqlashimiz kerak (biz odatda aniqlaydigan cho'qqi parametrlariga qo'shimcha ravishda, masalan, joylashuv yoki tekstura koordinatalari). Keling, buni OpenGL ES bilan qanday qilish mumkinligini ko'rib chiqaylik.

Amalda

Keling, OpenGL ES yordamida yoritish bilan ishlash uchun zarur bo'lgan barcha bosqichlarni bajaramiz. Keling, chiroqlar bilan ishlashni biroz osonlashtiradigan kichik yordamchi sinflarni yarataylik va ularni .androi dgames.framework.gl bilan com.badlogi paketiga joylashtiramiz.

Yoritishga ruxsat berish va taqiqlash

Boshqa OpenGL ES holatlarida bo'lgani kabi, birinchi navbatda nomlangan funksiya yoqilgan bo'lishi kerak. Buni shunday qilish mumkin:

Shundan so'ng, yorug'lik barcha tasvirlangan ob'ektlarga qo'llaniladi. Natijani olish uchun siz yorug'lik manbalari va materiallarini, shuningdek, vertex normalarini belgilashingiz kerak. Barcha kerakli ob'ektlarni chizishni tugatgandan so'ng, yorug'likni o'chirish mumkin:

Yorug'lik manbalarini aniqlash

OpenGL ES 4 turdagi yorug'lik manbalarini taqdim etadi: orqa yorug'lik, nuqta, yo'nalish va yoritgich. Keling, birinchi uchtasini qanday aniqlashni ko'rib chiqaylik. Armatura samarali bo'lishi va yaxshi ko'rinishi uchun har bir model juda ko'p uchburchaklardan iborat bo'lishi kerak. Bugungi ko'plab mobil qurilmalar uchun bu mumkin emas.

OpenGL ES bir vaqtning o'zida maksimal 8 ta yorug'likni, shuningdek, bitta global yorug'lik manbasini aniqlash imkonini beradi. 8 ta chiroqning har biri GL10.GL LIGHT0 dan GL10.GL LIGHT7 gacha bo'lgan identifikatorga ega. Agar siz ushbu chiroqlardan birining xususiyatlarini o'zgartirmoqchi bo'lsangiz, tegishli identifikatorni belgilash orqali buni amalga oshirishingiz mumkin.

Quyidagi sintaksis yordamida yoritish manbalarini yoqishingiz mumkin:

Keyinchalik, OpenGL ES ushbu yorug'lik manbasining xususiyatlarini oladi va ularni barcha ko'rsatilgan ob'ektlarga qo'llaydi. Agar yorug'lik manbasini o'chirib qo'yishimiz kerak bo'lsa, buni quyidagi bayonot bilan qilishimiz mumkin:

Ajratish alohida holat, chunki uning identifikatori yo'q. OpenGL ES sahnasida faqat bitta ta'kidlash mumkin. Keling, ushbu yorug'lik manbasini batafsil ko'rib chiqaylik.

Orqa yorug'lik

Orqa yorug'lik - yorug'likning maxsus turi. Uning pozitsiyasi yoki yo'nalishi yo'q, faqat barcha yoritilgan narsalarga bir xil tarzda tegishli rang. OpenGL ES sizga quyidagi kabi global diqqatni aniqlash imkonini beradi:

ambientCol yoki massiv ochiq rangning RGBA qiymatlarini o'z ichiga oladi, ular 0 dan 1 gacha bo'lgan suzuvchi nuqta raqamlari sifatida ifodalanadi. gl LightModel fv usuli o'zining birinchi parametri sifatida biz fon rangini o'rnatmoqchi ekanligimizni bildiruvchi doimiyni oladi. yorug'lik manbai, manba rangini o'z ichiga olgan suzuvchi nuqta raqamlari qatori va usul RGBA qiymatlarini o'qishni boshlaydigan floatlar massivi uchun ofset. Keling, ushbu muammoni hal qiladigan kodni kichik sinfga joylashtiramiz. Uning kodi 11.2 ro'yxatda ko'rsatilgan.

Ro'yxat 11.2. AmbientLight.java sinfi. oddiy OdenGL ES global ta'kidlash abstraksiya

Biz qilayotgan ish faqat ta'kidlash rangini suzuvchi qatorda saqlash va ikkita usulni taqdim etishdir, ulardan biri rangni o'rnatish uchun ishlatiladi, ikkinchisi esa OpenGL ESga o'sha rangdan foydalanishni aytadi. Standart rang kulrang.

Nuqtali yorug'lik manbalari

Nuqta chiroqlari joylashuvi va foni, tarqoq va aniq rang/intensivlikka ega (biz emissiya rangi/intensivligini hisobga olmaymiz). Turli xil rang turlarini quyidagicha belgilashingiz mumkin:

Birinchi parametr yorug'lik manbasining identifikatoridir. Bunday holda biz to'rtinchi manbadan foydalanamiz. Keyingi parametr biz o'zgartirmoqchi bo'lgan atributni belgilaydi. Uchinchi parametr RGBA qiymatlarini o'z ichiga olgan floatlar massivi, oxirgisi esa ushbu massivdagi ofsetdir. Manba pozitsiyasini aniqlash juda oson:

Biz yana o'zgartirmoqchi bo'lgan atributni (bu holda pozitsiyani), yaratilayotgan dunyodagi yorug'lik manbasining x-, y- va z-koordinatalarini o'z ichiga olgan to'rtta elementdan iborat massivni aniqlaymiz. Yorug'lik manbai pozitsiyasiga ega bo'lsa, massivning to'rtinchi elementi birga teng bo'lishi kerakligini unutmang. Keling, buni yordamchi sinfga joylashtiramiz. Uning kodi 11.3 ro'yxatda keltirilgan.

Ro'yxat 11.3. Point.Light.java klassi, oddiy OpenGL ES nuqta nuri abstraktsiyasi

Bizning yordamchi sinfimiz yorug'likning fon, diffuz va ko'p rangli komponentlarini, shuningdek pozitsiyasini (to'rtinchi element bitta) o'z ichiga oladi. Bundan tashqari, biz ma'lum bir manba uchun ishlatiladigan oxirgi identifikatorni saqlaymiz, shuning uchun agar kerak bo'lsa, yorug'likni o'chiradigan disableO usulini yaratish mumkin bo'ladi. Shuningdek, bizda GL10 sinfi va yorug'lik identifikatori (masalan, GL10.GL LIGHT6) misolini oladigan enableO usuli mavjud. Bu yorug'likdan foydalanishga imkon beradi, uning atributlarini o'rnatadi va foydalanilgan identifikatorni saqlaydi. disableO usuli shunchaki yoqish usulida 1ast.Ligh.tId sinf a'zosi to'plamidan foydalangan holda yoritishdan foydalanishni o'chirib qo'yadi.

Sinf a'zolari massivlarini ishga tushirishda biz fon, tarqoq va ayyor ranglar uchun o'rtacha standart qiymatlardan foydalanamiz. Yorug'lik oq bo'ladi va hech qanday porlashni yaratmaydi, chunki uning ko'zga ko'ringan komponenti qora.

Yo'nalishli yorug'lik manbalari

Yo'nalishli yorug'lik manbalari nuqtali yorug'lik manbalari bilan deyarli bir xil. Faqatgina farq shundaki, ular pozitsiya o'rniga yo'nalishga ega. Qaysi yo'nalishda ifodalanganligi biroz chalkash. Yo'nalishni ko'rsatish uchun vektordan foydalanish o'rniga, OpenGL ES bizdan bitta nuqtani aniqlashimizni kutadi. Keyin yo'nalish ushbu nuqta va boshni bog'laydigan vektor yordamida aniqlanadi. Quyidagi parcha sizga dunyoning o'ng tomonidan keladigan yo'nalishli yorug'likni yaratishga imkon beradi:

Biz uni vektorga aylantira olamiz:

Qolgan atributlar, masalan, fon yoki atrof-muhit rangi, nuqta yorug'ligi bilan bir xil. Ro'yxat 11.4 yo'nalishli chiroqlarni yaratish uchun ishlatiladigan kichik yordamchi sinf uchun kodni ko'rsatadi.

Ro'yxat 11.4. Directi onLi ght.java klassi, OpenGL ES da yo'naltiruvchi chiroqlarning oddiy abstraktsiyasi

Ushbu yordamchi sinf PointLight sinfiga deyarli o'xshaydi. Yagona farq shundaki, massivda to'rtinchi element bitta. Bundan tashqari, setPosition usuli o'rniga setDirecti on usuli paydo bo'ldi. Bu sizga yo'nalishni belgilash imkonini beradi, masalan: (-1; 0; 0), bu holda yorug'lik o'ng tomondan keladi. Usul ichida barcha vektor komponentlari o'z belgisini o'zgartiradi, shuning uchun biz yo'nalishni OpenGL ES kutgan formatga aylantiramiz.

Biz materiallarni aniqlaymiz

Materiallar bir nechta atributlar bilan tavsiflanadi. Boshqa har qanday OpenGL ES ob'ektida bo'lgani kabi, material biz uni qayta o'zgartirmagunimizcha yoki OpenGL ES konteksti yo'qolguncha faol bo'ladigan holatdir. Joriy material atributlarini o'rnatish uchun biz quyidagilarni amalga oshirishimiz mumkin:

Odatdagidek, biz RGBA fonini, diffuz va spekulyar ranglarni aniqlashimiz kerak. Buni avvalgidek bajarish mumkin - to'rtta elementdan iborat suzuvchi nuqtali raqamlar massivlari yordamida.

Ushbu harakatlarni bitta yordamchi sinfga birlashtirish juda oson. Natijani 11.5 ro'yxatida ko'rishingiz mumkin.

Ro'yxat 11.5. Material Java klassi, OpenGL ES materiallarining oddiy abstraktsiyasi

Bu erda ham ajablanarli narsa yo'q. Biz faqat materialni tavsiflovchi uchta komponentni saqlaymiz va ularning qiymatlarini o'rnatish funktsiyalarini va ularni OpenGL ESga o'tkazadigan yoqish usulini taqdim etamiz.

Materiallar haqida gap ketganda, OpenGL ES yana bir hiyla-nayrangga ega. Odatda glMaterialfvO usuli o'rniga moddiy rang deb ataladigan narsadan foydalanadi. Bu shuni anglatadiki, glMaterial al fv usuli bilan belgilangan fon va diffuz ranglar o'rniga, OpenGL ES bizning modellarimiz cho'qqilarining rangini materialning fon va tarqoq ranglari sifatida oladi. Ushbu xususiyatni yoqish uchun siz shunchaki qo'ng'iroq qilishingiz kerak:

Men odatda shunday qilaman, chunki fon va tarqoq ranglar ko'pincha bir xil bo'ladi. Men o'yinlarim va demolarimning ko'pchiligida yorqin nuqtalardan foydalanmaganim uchun men bu usuldan bemalol foydalana olaman va glMaterial fv ni chaqirmayman. Qaysi usuldan foydalanish sizga bog'liq.

Normallarni aniqlash

Yoritish OpenGL ES da ishlashi uchun siz modelning har bir cho'qqisi uchun vertex normalarini belgilashingiz kerak. Oddiy cho'qqi, cho'qqi tegishli bo'lgan sirt qaragan yo'nalishga (odatda) ishora qiluvchi birlik vektor bo'lishi kerak. Shaklda. 11.5-rasmda kubimiz uchun vertex normalari ko'rsatilgan.

Guruch. 11.5. Kubimizning har bir cho'qqisi uchun vertex normalari

Oddiy cho'qqi cho'qqining yana bir atributidir, xuddi pozitsiya yoki rang kabi. Tepalik normalaridan foydalanish uchun Vertices3 sinfini yana o'zgartirishimiz kerak. OpenGL ES ga har bir cho'qqi uchun normalarni qayerda topishi mumkinligini aytish uchun, xuddi ilgari gl VertexPointer yoki gl Col yoki Pointer usullaridan foydalanganimiz kabi, gl Normal PointerO usulidan foydalanamiz. 11-6 ro'yxat Vertices3 sinfining yakuniy versiyasini ko'rsatadi.

Ro'yxat 11.6. Vertices3.Java klassi, normallarni qo'llab-quvvatlovchi oxirgi versiya

Sinfda yangi hasNormal.s a'zosi mavjud bo'lib, u cho'qqilarning normalari bor-yo'qligini kuzatib boradi.

Konstruktor endi hasNormals parametrini ham qabul qiladi. Biz hali ham vertexSize a'zosining hisobini o'zgartirishimiz kerak, agar iloji bo'lsa, har bir cho'qqiga uchta float qo'shamiz.

Ko'rib turganingizdek, setVertices va setIndices usullari o'zgarishsiz qoladi.

Biz hozirgina ko'rsatgan bog'lash usulida biz avvalgi kabi ByteBuffer buferi bilan bir xil fokuslardan foydalanamiz, lekin bu safar gl Normal Pointer usuli yordamida normallarni qo'shamiz. Oddiy ko'rsatkichning ofsetini hisoblash uchun to'qimalarning koordinatalari va ranglari ko'rsatilganligini hisobga olish kerak.

Ko'rib turganingizdek, chizish usuli ham o'zgarmagan; barcha harakat bogʻlanish usulida sodir boʻladi O.

Nihoyat, unbindO usulini biroz o'zgartiramiz. Oddiy ko'rsatkichlardan foydalanishni o'chirib qo'yamiz, agar mavjud bo'lsa, OpenGL ES holatini mos ravishda tozalaymiz.

O'zgartirilgan Verti ces3 sinfini qo'llash avvalgidek oson. Kichik bir misolni ko'rib chiqing:

Har birining pozitsiyasi (har bir satrdagi dastlabki uchta raqam) va normal (har bir satrdagi oxirgi uchta raqam) bo'lgan uchta cho'qqini ushlab turish uchun biz floatlar qatorini yaratamiz. Bunday holda, biz xy tekisligida uchburchakni aniqlaymiz, uning normallari musbat z o'qi yo'nalishini ko'rsatadi.

Biz qilishimiz kerak bo'lgan narsa - Vertices3 sinfining namunasini yaratish va tepalik qiymatlarini o'rnatish. Juda oson, to'g'rimi?

Barcha bog'lash, chizish va bog'lash ishlari xuddi sinfning oldingi versiyasida bo'lgani kabi amalga oshiriladi. Avvalgidek, biz vertex ranglarini va tekstura koordinatalarini qo'shishimiz mumkin.

Hammasini bir joyga qo'yish

Keling, hammasini birlashtiraylik. Biz global yoritish, nuqta va yo'nalishli yorug'lik manbalariga ega bo'lgan sahnani chizishimiz kerak. Ular boshlang'ichda joylashgan kubni yoritadi. Shuningdek, gl uLookAt usulini chaqirishimiz kerak. kamerani joylashtirish uchun. Shaklda. 11.6 ko'rsatilgan tashqi ko'rinish bizning dunyomiz.

Boshqa barcha misollarga kelsak, biz odatdagidek GLGame sinfini kengaytirib, LightTest deb nomlangan sinf yaratamiz. U getStartScreenO usuli yordamida LightScreen sinfining namunasini qaytaradi. LightScreen sinfi GLScreen sinfidan meros bo'lib o'tadi (Ro'yxat 11-7).

Guruch. 11.6. Bizning birinchi yoritilgan sahnamiz

Ro'yxat 11.7. LightTest.java sinfining fragmentlari. OpenGL ES yordamida yoritish yaratish

Keling, sinfning bir nechta a'zolarini tavsiflashdan boshlaylik. Burchak elementi kubning y o'qi atrofidagi joriy aylanishi haqidagi ma'lumotlarni saqlaydi. Vertices3 a'zosi kub modelining uchlarini saqlaydi, biz ularni tez orada aniqlaymiz. Bundan tashqari, bizda AmbientLight, PointLight va Directional Light sinflari, shuningdek Materiallar sinfining namunalari mavjud.

Keyin konstruktor keladi. Bu yerda kub modelining uchlari yaratiladi va quti teksturasi ham yuklanadi. Shuningdek, biz chiroqlar va materiallarni ishga tushiramiz. Yoritish rangi och yashil rangda. Yo'naltiruvchi manba qizil rangga ega va dunyomizning (3; 3; 0) nuqtasida joylashgan. Yo'nalishli yorug'lik manbai ko'k diffuz rangga ega, yorug'lik chapdan tushadi. Materiallar uchun standart qiymatlardan foydalaning (bir oz fon, diffuz komponent uchun oq va aynali komponent uchun qora).

Rezyume usulida, agar kontekst yo'qolgan bo'lsa, bizning teksturamiz (qayta) yuklanganligiga ishonch hosil qilamiz.

CreateCube usuli oldingi misollardan unchalik o'zgarmadi. Biroq, bu safar biz rasmda ko'rsatilganidek, har bir tepalik uchun normalarni qo'shamiz. 11.5. Bundan tashqari, hamma narsa avvalgidek qoladi.

Yangilash usulida biz shunchaki kubning aylanish burchagini oshiramiz.

Bu erda qiziqroq. Birinchi qatorlar rang va chuqurlik buferini tozalash, chuqurlik sinovini yoqish va ko'lamni o'rnatish uchun mo'ljallangan.

Keyinchalik, gl uPerspective usuli yordamida proyeksiya matritsasini istiqbolli proyeksiya matritsasiga tenglashtiramiz, shuningdek, modelni ko'rish matritsasida gl uLookAt usulidan foydalanamiz, shunda kamera rasmdagi kabi ishlaydi. 11.6.

Keyin yorug'likdan foydalanishga ruxsat beramiz. Ayni paytda, hech qanday chiroqlar hali aniqlanmagan, shuning uchun biz ularni keyingi bir necha qatorda chiroqlar va materiallar uchun usul chaqiruvi bilan aniqlaymiz.

Odatdagidek, biz ham teksturani yoqamiz va quti teksturasini bog'laymiz. Nihoyat, kubni aylantirish uchun gl RotatefC) usulini chaqiramiz va keyin Vertices3 sinfiga yaxshi joylashtirilgan misol chaqiruvlari bilan uning uchlarini chizish.

Usul oxirida biz nuqta va yo'nalishli chiroqlarni o'chirib qo'yamiz (esda tutingki, ta'kidlash - bu global holat), shuningdek, tekstura va chuqurlik sinovi. Bu OpenGL ESda yoritish uchun.

Sinfning qolgan qismi bo'sh; pauza holatida hech narsa qilishimiz shart emas. Shaklda. 11.7 dastur natijasini ko'rsatadi.

Guruch. 11.7. Rasmda ko'rsatilgan sahna. 11.6 OpenGL ES bilan yaratilgan

OpenGL ES-da yoritish bo'yicha bir nechta eslatma

Yoritishdan foydalanish o'yiningizga jo'shqinlik qo'shishi mumkin bo'lsa-da, uning cheklovlari va tuzoqlari bor. Siz bilishingiz kerak bo'lgan bir nechta narsalar mavjud.

Yoritishdan foydalanish juda ko'p resurslarni sarflaydi, ayniqsa sekin qurilmalarda seziladi. Yoritishni ehtiyotkorlik bilan qo'llang. Qanchalik ko'p chiroqlarni tasvirlasangiz, sahnani ko'rsatish uchun shunchalik ko'p hisob-kitoblar kerak bo'ladi.

Nuqtali/yo‘nalishli yorug‘lik manbalarining joylashuvi/yo‘nalishi kamera matritsalari yuklangandan so‘ng va model ko‘rinishi matritsasi ob’ektlarni ko‘chirish va aylantirish uchun boshqa matritsalar bilan ko‘paytirilishidan oldin aniqlanishi kerak. Bu juda muhim. Ushbu ko'rsatmalarga rioya qilmaslik tushunarsiz yorug'lik artefaktlariga olib kelishi mumkin.

Model o‘lchamini o‘zgartirish uchun gl Seal ef usulidan foydalanilganda, uning me’yorlari ham masshtablanadi. Bu yomon, chunki OpenGL ES normalar berilgan birliklarda bo'lishini kutadi. Ushbu muammoni hal qilish uchun siz glEnable(GL10.GL NORMALIZE) buyrug'idan yoki ba'zi hollarda gl Enable(GL10 .GL RESCALE N0RMAL) buyrug'idan foydalanishingiz mumkin. Menimcha, birinchi buyruqdan foydalanish kerak, chunki ikkinchisida cheklovlar va tuzoqlar mavjud. Muammo shundaki, me'yorlarni normallashtirish yoki qayta o'zgartirish juda ko'p ishlov berish quvvatini talab qiladi. Ishlash nuqtai nazaridan eng yaxshi yechim yoritilgan ob'ektlarni masshtablashtirmaslikdir.

Xo'sh, janoblar. So‘nggi paytlarda biz OpenGL haqida juda ko‘p narsalarni o‘rgandik, jumladan, qanday qilishni ham kamerani boshqaring , teksturalar bilan ishlash, shuningdek bilan modellar. Yana qiziqarli narsa, ya'ni yorug'lik haqida gapirish vaqti keldi. Bu mavzu qiziqarli, chunki OpenGL-da yorug'lik bilan ishlashga tayyor narsa yo'q, hamma narsa shaderlarda mustaqil ravishda yozilishi kerak. Ushbu eslatmaning bir qismi sifatida biz Phong yoritishni ko'rib chiqamiz. Bu juda katta mavzu, shuning uchun biz faqat gaplashamiz yoritish. Ular qanday yaratilgan bo'lsa soyalar, buni boshqa safar aniqlashga to'g'ri keladi.

Oddiylarni saqlash va ishlatish

To'g'ridan-to'g'ri yoritishga o'tishdan oldin, biz odatdagidek narsaga muhtojmiz.

Biz allaqachon bilamizki, modellarda bu cho'qqilarga mos keladigan cho'qqilar va UV koordinatalari mavjud. Yoritishni yaratish uchun bizga modellar, ya'ni normallar haqida ko'proq ma'lumot kerak. Oddiy - bu cho'qqiga mos keladigan birlik vektori (yoki muqobil ravishda ko'pburchak, lekin bu bizning holatimizda emas). Yoritishni amalga oshirishda normalar qanday rol o'ynaydi, biz quyida bilib olamiz. Hozircha normalar haqiqatan ham juda muhim ekanligini aytish kifoya. Masalan, ular tufayli yuzalar silliqroq ko'rinadi va siz to'pni ikosahedr kabi oddiy konveks ko'pburchakdan ajrata olasiz. Va normalar juda muhim bo'lgani uchun, biz Blender modellarini o'z formatimizga o'tkazishda ularni qanday saqlashni o'rganishimiz kerak.

Tegishli o'zgarishlar juda ahamiyatsiz. Biz normalarni xuddi tepa koordinatalarini va UV koordinatalarini olgandek olamiz:

// protsedura tanasi qismi importedModelCreate

uchun (imzosiz int j = 0 ; j< face.mNumIndices ; ++ j) {
unsigned int index = face.mIndices[ j] ;
aiVector3D pos = mesh-> mVertices[ indeks] ;
aiVector3D uv = mesh-> mTextureCoords[ 0 ] [indeks] ;
aiVector3D normal = mesh-> 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 ;
}

Modelni optimallashtirish tartibi shunga o'xshash tarzda o'zgaradi. Va modelLoad protsedurasida ikkita atributlar massivi o'rniga bizga uchtasi kerak bo'ladi:

// modelLoad protsedurasining asosiy qismi

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

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

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

Bundan tashqari, bizga qo'shimcha ravishda M matritsali bir xil o'zgaruvchi kerak:

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

// ...

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

... vertex shaderda bo'shliqda normalni to'g'ri aylantirish uchun:

#versiyasi 330 yadro

Layout(joy = 0 ) vec3 vertexPos;
layout(joy = 1 ) vec3 vertexNorm;
layout(joy = 2 ) vec2 vertexUV;

yagona mat4 MVP;
yagona mat4M;

vec2 fragmentUV;
out vec3 fragmentNormal;
vec3 fragmentPos;

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

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

Nihoyat, fragment shaderi uchta cho'qqi ustidagi oddiy interpolyatsiyani oladi:

// ...

void main() (

// ...
}

Ushbu oddiy usulda biz normalarni olamiz parchalar.

Phong yoritish nima

Ta'kidlanganidek, OpenGL-da yoritish dasturchining o'zi tomonidan shaderlarda yoziladi. Ushbu yoritishni amalga oshirishning bir nechta usuli borligi aniq, ularning har biri o'ziga xos realizm darajasi va resurslarga bo'lgan talablarga ega. Va har bir usul hali ham cheksiz miqdordagi o'ziga xos ilovalarga ega bo'lishi mumkin. Mening tushunishimga ko'ra, real vaqt rejimida samarali va real yoritish hali ham faol tadqiqot sohasi hisoblanadi. Ushbu eslatmaning bir qismi sifatida biz Phong yoritishni ko'rib chiqamiz, bu juda real va amalga oshirish oson.

Quyidagi tushunchalar orasidagi farqni tushunish muhimdir:

  • Gouraud soyasi - bu har bir cho'qqining yoritilishini hisoblashda va ular orasidagi bo'laklarning yoritilishi interpolyatsiya qilinadi;
  • Phong shading - yorug'lik har bir parcha uchun alohida hisoblanganda;
  • Phong yoritgichi yoki Phong aks ettirish modeli - bu ushbu eslatmada muhokama qilingan va Gouraud soyasida ham, Phong soyasida ham ishlatilishi mumkin bo'lgan maxsus yoritish usuli;

Phong shading va Phong yoritgichi ko'pincha chalkashib ketishi ajablanarli emas va ba'zi o'quv qo'llanmalarida siz "Telefonni soya qilish g'oyasi uchta komponentdan foydalanishdir ..." kabi bema'ni narsalarni o'qishingiz mumkin, bu sizni darhol hokimiyatga jiddiy shubha tug'diradi. ushbu qo'llanmani yozgan odam.

Men tushunganimdek, Gouraud soyasi zamonaviy ilovalarda deyarli ishlatilmaydi, uning o'rniga Phong soyasi afzallik beriladi. Ushbu postning bir qismi sifatida biz Phong soyasidan ham foydalanamiz, ya'ni yorug'lik har bir parcha uchun alohida hisoblab chiqiladi. Biz foydalanadigan maxsus yoritish usuli - bu Phong yoritish. Bu usul quyidagicha.

Turli formulalarga ko'ra, uchta yoritish komponenti hisoblanadi:

  • Fon yoritgichi (atrof-muhit yoritgichi) - boshqa ob'ektlardan aks ettirilgandan so'ng ma'lum bir nuqtaga etgan yorug'likni taqlid qilish. Fon yoritilishini hisoblashda kameraning normal holati ham, joriy holati ham hisobga olinmaydi;
  • Diffuz yorug'lik - ma'lum bir nuqtaga urilgandan keyin tarqaladigan manbadan yorug'lik. Yorug'lik tushish burchagiga qarab, yorug'lik kuchliroq yoki zaifroq bo'ladi. Bu erda me'yorlar hisobga olinadi, lekin kameraning pozitsiyasi emas;
  • Yansıtiladigan yorug'lik (spekulyar yorug'lik) - ma'lum bir nuqtaga urilgandan keyin aks ettirilgan manbadan yorug'lik. Agar aks ettirilgan yorug'lik kameraga kirsa, ko'rinadi. Shuning uchun, bu erda ham normal, ham kamera holati hisobga olinadi;

Keyin natijalar umumlashtiriladi, natijada to'liq yoritish olinadi.

Buni yanada qiziqarli qilish uchun turli xil yorug'lik manbalari mavjud. Ko'rinib turibdiki, ko'chadagi quyosh va qorong'udagi fonar sahnani juda boshqacha yoritadi. Boshlash uchun biz eng oddiy manba - yo'nalishli yorug'likni ko'rib chiqamiz.

Yo'nalishli yorug'lik

Yo'nalishli yorug'lik cheksiz uzoqdagi yorug'lik manbasini taqlid qilishdir. Masalan, Quyoshni olaylik. Quyosh yerdan juda uzoqda. Shuning uchun Yer yuzasida Quyoshdan keladigan barcha yorug'lik nurlarini katta aniqlik bilan parallel deb hisoblash mumkin. Yo'nalishli yorug'lik uning yo'nalishini, rangini, shuningdek, quyida bizga kerak bo'lgan ba'zi koeffitsientlarni tavsiflaydi:

structDirectionalLight(
vec3 yo'nalishi;

vec3 rangi;
float ambientIntensity;
float diffuseIntensity;
float specularIntensity;
} ;

Fragment shader kodida biz calcDirectionalLight protsedurasini aniqlaymiz, undan quyidagi kabi foydalaniladi:

vec3 fragmentPos da;
yagona vec3 kameraPos;
uniformDirectionalLight directionalLight;

// ...

void main() (
// interpolyatsiyadan so'ng normalni tuzatish kerak
vec3 normal = normalizatsiya (fragmentNormal) ;


yo'nalishli yorug'lik);

// ...
}

Jarayonning bajarilishini ko'rib chiqing.

vec4 calcDirectionalLight(vec3 normal, vec3 fragmentToCamera,
Yo'nalishli yorug'lik) (
vec4 ambientColor = vec4 (yorug'lik. rang , 1 ) * yorug'lik. muhit zichligi;

// ...
}

Birinchidan, birinchi komponent, fon yoritgichi hisoblab chiqiladi. Bu shunchaki chiqarilgan yorug'likning rangi fon yorug'ligining intensivligiga ko'paytiriladi. Hozircha hamma narsa oddiy.

// ...

float diffuseFactor = max (0,0 , nuqta (normal, - yorug'lik. yo'nalish ) );
vec4 diffuseColor = vec4 (yorug'lik. rang , 1 ) * yorug'lik. diffuz intensivlik
* diffuz faktor;

// ...

Tarqalgan yoritish. DiffuseFactor o'zgaruvchisi fragmentga normal va fragmentdan yorug'lik manbasiga yo'naltirilgan vektor orasidagi burchakning kosinusidir. Agar yorug'lik sirtga perpendikulyar tushsa, burchak nolga teng. Bu burchakning kosinusu birga teng va yorug'lik maksimal (Lambert qonuni haqidagi Vikipediya maqolasiga qarang). Burchak kattalashganda, yorug'lik sirtga parallel ravishda tarqalsa, kosinus kamayadi va nolga teng bo'ladi. Agar kosinus manfiy bo'lsa, yorug'lik manbai sirtning orqasida joylashgan va u yoritilmagan, shuning uchun biz salbiy qiymatlarni max(0,0, ...) bilan nolga aylantiramiz. Yorug'lik tushadigan burchakdan tashqari, diffuseIntensity ham hisobga olinadi.

// ...
vec3 lightReflect = normallashtirish (aks ettirish (yorug'lik. yo'nalish , normal) );
float specularFactor = pow(
maksimal (0,0, nuqta (fragmentToCamera, lightReflect) ),
MaterialSpecular Factor
) ;
vec4 specularColor = yorug'lik. specularIntensity * vec4 (yorugʻlik.rang, 1 )
* materialSpecularIntensity * specularFactor;
// ...

Bilvosita yoritish. LightReflect o'zgaruvchisi aks ettirilgan yorug'lik yo'nalishini belgilaydigan birlik vektoridir. SpecularFactor o'zgaruvchisi diffuseFactorga o'xshash tarzda hisoblanadi, faqat bu safar u yorug'lik aks etgan yo'nalish va fragmentdan kameraga yo'nalish o'rtasidagi burchakning kosinusini hisobga oladi. Agar bu burchak nolga teng bo'lsa, u holda aks ettirilgan yorug'lik to'g'ridan-to'g'ri kameraga tushadi va sirtdagi porlash maksimal bo'ladi. Agar burchak katta bo'lsa, unda hech qanday porlash ko'rinmasligi kerak. Bu erda materialSpecularFactor bir xil o'zgaruvchidir. U qanchalik katta bo'lsa, ob'ekt yuzasida porlash maydoni shunchalik kichik bo'ladi. O'zgaruvchan materialSpecularIntensity ham qo'llaniladi, bu diqqatga sazovor joylarning yorqinligini aniqlaydi. E'tibor bering, bularning barchasi yorug'lik xususiyatlari emas, balki moddiy xususiyatlardir. Masalan, metall yorug'likni aks ettiradi va shuning uchun porlashi bor. Va daraxt yorug'likni aks ettirmaydi, keyin esa daraxtlardagi porlashni hech qachon ko'rmaysiz (albatta, agar sirt quruq bo'lsa va hokazo).

Yuqoridagi kodda yorug'lik specularIntensity xususiyatiga ega. Lekin u faqat disk raskadrovka maqsadida, ma'lum bir yorug'lik manbasidan diqqatga sazovor joylarni ta'kidlash uchun ishlatilishi kerak. Kodning chiqarilgan versiyasida bu koeffitsient bittaga teng bo'lishi yoki koddan butunlay chiqarib tashlanishi kerak.

Nihoyat, uchta komponent qo'shiladi va natija qaytariladi:

// ...

ambientColor + diffuseColor + specularColorni qaytarish;
}

Unchalik qiyin emas, to'g'rimi?

Nuqtali yorug'lik manbai

Yorug'likning nuqta manbai, masalan, yonayotgan lampochkadir. Lampochkaning yorug'ligi barcha yo'nalishlarga yo'naltiriladi. Shuning uchun nuqtali yorug'lik manbai yorug'lik yo'nalishi bilan tavsiflanmaydi, lekin manbaning kosmosdagi holati bilan tavsiflanadi:

structPointLight(
vec3 pozitsiyasi;

vec3 rangi;
float ambientIntensity;
float diffuseIntensity;
float specularIntensity; // disk raskadrovka maqsadlari uchun 1.0 ga o'rnatilishi kerak
} ;

Nuqtali yorug'lik manbasidan yorug'lik allaqachon mavjud calcDirectionalLight protsedurasi yordamida osongina hisoblab chiqiladi:

vec4 calcPointLight(vec3 normal, vec3 fragmentToCamera,
PointLight nuri) (
vec3 lightDirection = normallashtirish (fragmentPos - yorug'lik. pozitsiyasi );
float masofa = uzunlik (fragmentPos - yorug'lik. pozitsiyasi );
float pointFactor = 1,0 / (1,0 + pow (masofa, 2));

DirectionalLight tempDirectionalLight = DirectionalLight(
yorug'lik yo'nalishi,
yorug'lik. rang,
yorug'lik. atrof-muhit intensivligi,
yorug'lik. diffuz intensivlik,
yorug'lik. aniq intensivlik
) ;
qaytish nuqtasiFactor * calcDirectionalLight(normal, fragmentToCamera,
tempDirectionalLight);
}

Parcha va yorug'lik manbasining koordinatalariga ega bo'lgan holda, vektorlar farqi orqali yorug'lik yo'nalishini ma'lum bir qismga osongina hisoblash mumkin. PointFactor faktori yorug'lik manbasiga bo'lgan masofaning kvadrati bilan zaiflashishini aks ettiradi (sfera sirtining radiusga bog'liqligi formulasiga muvofiq). Bo'luvchida nuqtaFaktorni hisoblashda nolga bo'linish imkoniyatini oldini olish uchun qo'shimcha bir qo'shiladi. Shundan so'ng, hamma narsa yo'nalishli yorug'lik bilan bir xil tarzda hisoblanadi.

Qidiruv nuri (spot chiroq)

Ushbu yorug'lik manbasiga misol - chiroq. Bu nuqta yorug'lik manbasiga o'xshaydi, faqat u qo'shimcha ravishda yo'nalish va ta'sir burchagiga ega (kesish):

struct SpotLight (
vec3 yo'nalishi;
vec3 pozitsiyasi;
suzuvchi kesish;

vec3 rangi;
float ambientIntensity;
float diffuseIntensity;
float specularIntensity; // disk raskadrovka maqsadlari uchun 1.0 ga o'rnatilishi kerak
} ;

Tegishli protsedura:

vec4 calcSpotLight(vec3 normal, vec3 fragmentToCamera,
Spot nuri) (
vec3 spotLightDirection = normallashtirish (fragmentPos - yorug'lik. pozitsiyasi );
float spotAngleCos = nuqta (spotLightDirection, yorug'lik. yo'nalish );
float zaiflashuvi = (1,0 - 1,0 * (1,0 - spotAngleCos) /
(1,0 - yorug'lik. kesish ) );
float spotFactor = float(spotAngleCos > light. cutoff ) * susaytirish;

PointLight tempPointLight = PointLight(
yorug'lik. pozitsiyasi,
yorug'lik. rang,
yorug'lik. atrof-muhit intensivligi,
yorug'lik. diffuz intensivlik,
yorug'lik. muhit intensivligi
) ;
Qaytish spotFactor * calcPointLight (normal, fragmentToCamera,
tempPointLight);
}

Nurning yo'nalishi nuqta manbai bilan bir xil tarzda hisoblanadi. Keyin bu yo'nalish va yorug'likning o'zida ko'rsatilgan yo'nalish orasidagi burchakning kosinusu hisoblanadi. Ifodasi yordamida float(spotAngleCos > light.cutoff) yorug'lik belgilangan burchakka qattiq kesilgan. Zaiflash ko'paytiruvchisi qo'shiladi silliq parchalar manbaning xususiyatlarida ko'rsatilgan yorug'lik yo'nalishidan uzoqlashganda yorug'likning susayishi. Shundan so'ng, barcha hisob-kitoblar nuqta yorug'lik manbai uchun hisob-kitoblarga qisqartiriladi.

Gamma tuzatish

Fragment shaderidagi barcha asosiy protsedura quyidagicha ko'rinadi:

void main() (
// interpolyatsiyadan so'ng normalni tuzatish kerak
vec3 normal = normalizatsiya (fragmentNormal) ;
vec3 fragmentToCamera = normalizatsiya (cameraPos - fragmentPos) ;

vec4 directColor = calcDirectionalLight(normal, fragmentToCamera,
yo'nalishli yorug'lik);
vec4 pointColor = calcPointLight (normal, fragmentToCamera,
nuqta nuri);
vec4 spotColor = calcSpotLight (normal, fragmentToCamera, spotLight) ;
vec4 linearColor = tekstura (textureSampler, fragmentUV) *
(vec4 (material chiqarish, 1 ) + DirectColor +
pointColor + spotColor);

vec4 gamma = vec4 (vec3 (1,0 / 2,2), 1);
rang = pow (linearColor, gamma); // gamma-tuzatilgan rang
}

MaterialEmissiyaga juda ko'p e'tibor bermang. Bu materialning o'ziga xos yorqinligini qo'shadigan yana bir xususiyatdir. Ko'pgina ob'ektlar o'z-o'zidan porlaydi. Boshqa ob'ektlar uchun yorug'lik manbai bo'lib xizmat qiladigan bir xil lampochkalarni oling. Lampochkalar boshqa yorug'lik manbalari tomonidan yoqilmagan bo'lsa ham, biz ularni to'liq zulmatda ko'rishimiz kerak, shunday emasmi?

Haqiqatan ham e'tiborga loyiq narsa - barcha yorug'lik komponentlarini 1/2,2 quvvatga ko'tarishdan iborat bo'lgan gamma tuzatish. Hozirgacha biz 1,0 yorqinlikdagi rang 0,5 yorqinlikdagi rangdan ikki baravar yorqinroq degan taxminga asoslanib, chiziqli rang maydonida ishladik. Muammo shundaki, inson ko'zi yorqinlikni chiziqli bo'lmagan tarzda qabul qiladi. Shuning uchun, haqiqiy yoritishni olish uchun chiziqli fazoda barcha hisob-kitoblardan so'ng gamma tuzatishni amalga oshirish kerak.

Yodda tutingki, tasvirni saqlashda zamonaviy grafik muharrirlar ham gamma tuzatishni amalga oshiradilar. Shuning uchun, to'qimalarni ishlatishdan oldin, ushbu gamma tuzatishni bekor qilish kerak. Yaxshiyamki, bu qiyin emas.

Teksturani yuklash kodidagi barcha konstantalarni almashtirish kifoya:

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

... mos ravishda. Bu rasmga gamma tuzatish kiritilganligini ko'rsatadi, uni bekor qilish kerak. Qolganlari bilan OpenGL shug'ullanadi.

Haqiqiy ilovalarda gamma parametri (bizda gamma = 2.2) dastur sozlamalariga eng yaxshi joylashtirilgan, shunda foydalanuvchi, agar xohlasa, uni monitoriga moslashtirish uchun biroz sozlashi mumkin.

Xulosa

Rasmlarga qarash vaqti keldi!

Bu erda biz turli xil yoritish komponentlarini ko'ramiz. Chapdan o'ngga, yuqoridan pastga: fon, tarqoq, aks ettirilgan, uchtasi birga. Ko'rib turganingizdek, sahnaga torus modeli qo'shilgan. Oddiylarning murakkab tartibga solinishi tufayli ushbu model yorug'lik sinovi uchun tavsiya etiladi.

Turli xil yorug'lik manbalari. Chapdan o'ngga, yuqoridan pastga: oq yo'nalishli yorug'lik, qizil nuqta yorug'lik, ko'k yorug'lik, uchtasi birga.

Yana shuni ta'kidlaymanki, bir xil yoritish usuli turli xil ilovalarga ega bo'lishi mumkin. Misol uchun, siz materialning xususiyatlarini atrof-muhit, tarqoq va ko'proq rangga aylantirishingiz mumkin, bu sizga yashil rangda tarqaladigan va ko'k rangga ega bo'lgan qizil narsalarni chizish imkonini beradi. Phong yoritishning ba'zi ilovalarida men fon yorug'ligi har bir yorug'lik manbai uchun emas, balki bir marta hisoblanganligini ko'rdim. Men nuqtali manbadan keladigan yorug'lik shunchaki unga bo'lgan masofaning kvadratiga (d * d) mutanosib ravishda emas, balki umumiyroq formula bo'yicha (A + B * d + uslubida) zaiflashtirilgan ilovalarni ham ko'rdim. C * d * d). Kimdir atrof-muhitning intensivligini va tarqoq intensivlikni nafaqat yorug'lik manbai, balki materialning xususiyatiga aylantiradi. Biroq, bularning barchasi yorug'likning realizmiga qanchalik aloqasi borligiga ishonchim komil emas. Ammo uy vazifasi uchun siz hamma narsa bilan o'ynashingiz mumkin.

Yillik asarlar. Voloshin Maksimilian. Shoirning jasorati. 1. She'rni xorijga jo'natilgan matn kabi tahrirlang: Quruqlik, tiniqlik, bosim - har bir so'z ogohlantirishda.

Qattiq va tor toshni kesish uchun harfdan keyin harf: So'zlar qanchalik ziqna bo'lsa, ularning kuchi shunchalik kuchli bo'ladi. Fikrning ixtiyoriy zaryadi jim bo'lgan baytlarga teng.

“Go‘zallik”, “Ilhom” so‘zlarini lug‘atdan o‘chiring – Qofiyalarning o‘rtacha jargoni Shoirga – anglash: Haqiqat, qurilish, reja, tenglik, ixchamlik va aniqlik. Sog'lom, qattiq hunarda - shoirning ilhomi va sharafi: Kar-soqov moddada, transandantal hushyorlikni keskinlashtir. Voloshin M.A. Kutubxona: Oryol viloyat ilmiy universal kutubxonasi. I.A. Bunin. - M.,; Tanlangan asarlar: 2 jildda.

M., ; Qizil tutun: ertaklar. - M.,; Gladishev razvedkadan: Ertaklar. - M.,; Echelon; Muqarrar: romanlar. U Mari va Udmurt shoirlarining ko'plab tarjimalarini qilgan. Vaqti-vaqti bilan u nasrda ham o‘zini sinab ko‘rdi. Op. Maksimilian Aleksandrovich Voloshin () 20-asrning birinchi uchdan birining eng buyuk shoirlaridan biri. Bu iste'dodli rassom, ko'p qirrali lirik, ramziy, ezoterik she'rlardan fuqarolik-publisistik va ilmiy-falsafiy she'riyatga, antroposofik imtiyozlar orqali - "Xudo shahri idealiga" o'tgan.

Taklif etilayotgan nashr o'quvchiga Voloshinning nafaqat eng yaxshi she'riy asarlari, balki uning estetikaga oid eng qiziqarli asarlari, memuar nasri, publitsistikasi va mamlakatlar hayotidagi dramatik voqealarga oid xatlari bilan ham tanishish imkonini beradi. Muallif. Voloshin Maksimilian. Muallifning barcha she'rlari. Ish. Shoirning jasorati. 2. Yulduzlar. Tanlangan mualliflar va she'rlar to'plamlarini yarating!

Hamfikrlar bilan suhbatlashing! Sharhlar yozing, she'riy duel va tanlovlarda qatnashing! Eng yaxshilarga qo'shiling! Poembukga qo'shilganingiz uchun tashakkur! Sizning elektron pochta manzilingizga hisob qaydnomasiga kirish ma'lumotlari bilan xat yuborildi!

24 soat ichida tizimga kirishingiz kerak. Aks holda, hisob o'chiriladi! Ro'yxatdan o'tgan foydalanuvchilar juda ko'p afzalliklarga ega bo'lishadi: she'r nashr eting - o'z iste'dodingizni ro'yobga chiqaring! Tanlangan mualliflar va she'rlar to'plamlarini yarating! Hamfikrlar bilan suhbatlashing! Sharhlar yozing, she'riy duel va tanlovlarda qatnashing!. Maksimilian Voloshin. Tavsif. Maksimilian Aleksandrovich Voloshin - 20-asrning birinchi uchdan bir qismining eng buyuk shoirlaridan biri.

Bu iste'dodli ijodkor, ko'p qirrali lirik, ramziy, ezoterik she'rlardan fuqarolik-publisistik va ilmiy-falsafiy she'riyatga, antroposofik moyilliklar orqali - "Xudo shahri ideali"ga o'tgan. Taklif etilayotgan nashr o'quvchiga Voloshinning nafaqat eng yaxshi she'riy asarlari, balki uning estetikaga oid eng qiziqarli asarlari, memuar nasri, publitsistikasi va dramaturgiyaga oid xatlari bilan ham tanishish imkonini beradi.

Tanlangan asarlar va xatlar. M. A. Voloshin. Narxi. surtish. Maksimilian Aleksandrovich Voloshin - 20-asrning birinchi uchdan bir qismining eng buyuk shoirlaridan biri. Bu iste'dodli ijodkor, ko'p qirrali lirik, ramziy, ezoterik she'rlardan fuqarolik-publisistik va ilmiy-falsafiy she'riyatga, antroposofik moyilliklar orqali - "Xudo shahri ideali"ga o'tgan.

Voloshin M.A., Shoirning jasorati: Tanlangan asarlar va xatlar. seriya: Rus klassiklarining yangi kutubxonasi: majburiy nusxasi Parad, g., p., Kitob tavsifi. Maksimilian Aleksandrovich Voloshin () 20-asrning birinchi uchdan birining eng buyuk shoirlaridan biri. Bu iste'dodli rassom, ko'p qirrali lirik, ramziy, ezoterik she'rlardan fuqarolik-publisistik va ilmiy-falsafiy she'riyatga, antroposofik imtiyozlar orqali - "Xudo shahri idealiga" o'tgan.

toifalar Post navigatsiyasi

Yorug'lik manbai bo'lmasa, tasvir ko'rinmaydi. Manbani ishga tushirish va manbaning ob'ektlarga ta'sirini hisoblash uchun ishlov beruvchini yoqish uchun quyidagi buyruqlarni bajarish kifoya: glEnable(gl_lighting);//yorug'likni tahlil qilish rejimini yoqish

GlEnable(gl_light0); // sahnaga o'ziga xos (null) manbani o'z xususiyatlari bilan qo'shing

Disable() funktsiyasi manbani o'chirish uchun ishlatiladi. Standart yorug'lik manbai koordinatali (0,0,∞) kosmosda joylashgan. Rasm maydonining istalgan nuqtasida yorug'lik manbasini yaratishingiz mumkin.

OpenGl kutubxonasida to'rt turdagi yorug'lik manbalari qo'llab-quvvatlanadi:

  • fon yoritgichi (atrof-muhit yoritilishi),
  • nuqta manbalari,
  • projektorlar (projektorlar),
  • masofaviy yorug'lik manbalari (uzoq yorug'lik).
Har bir yorug'lik manbai o'ziga xos xususiyatlarga ega.
Yorug'lik manbasining xarakteristikalari Phong modelining parametrlariga mos keladi.
Vektor parametrlarini o'rnatish uchun quyidagi formatga ega glLightfv() funksiyasidan foydalaniladi:

glLightfv(manba, parametr, massivga marker);

Manba nurlarining joylashuvi va yo'nalishini va uning tarkibiy qismlarining rang tarkibini aniqlaydigan to'rtta vektor parametrlari mavjud - fon, diffuziya va spekulyar.
OpenGL-da skalyar parametrlarni o'rnatish uchun glLightf() funksiyasidan foydalaning:

glLightf(manba, parametr, qiymat);

Masalan, sahnaga (1.0, 2.0, 3.0) nuqtada joylashgan bo'lishi kerak bo'lgan GL_LIGHT0 manbasini kiritish talab qilinsin. Manbaning joylashuvi dasturda bir hil koordinatalarda nuqta sifatida saqlanadi:

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

Agar ushbu nuqtaning to'rtinchi komponenti nolga teng bo'lsa, u holda nuqta manbai uzoqqa aylanadi, buning uchun faqat nurlarning yo'nalishi muhim:

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

Keyinchalik, manbaning fon, diffuziya va spekulyar tarkibiy qismlarining rang tarkibi aniqlanadi. Agar ushbu misolda manba oq aynali komponentga ega bo'lsa va fon va diffuziya komponentlari qizil bo'lishi kerak bo'lsa, manbani tashkil etuvchi dastur fragmenti quyidagicha ko'rinadi:

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

GlLightfv(GL_LIGHT0, GL_DIFFUSE, diffuz0);

GlLightfv(GL_LIGHT0, GL_SPECULAR, specular0);

Sahnaga biron bir yorug'lik manbai bilan bog'liq bo'lmagan global fon yoritgichini ham qo'shishingiz mumkin. Agar, masalan, siz sahnadagi barcha ob'ektlarni oq rang bilan xira ajratib ko'rsatishni istasangiz, dasturingizga quyidagi kod parchasini kiritishingiz kerak:

GLfloat global_ambient=(0.1, 0.1, 0.1, 1.0);

GlLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient);

Yoritish modelida manbagacha bo'lgan masofani hisobga oladigan atama quyidagi shaklga ega:

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

Va doimiy, chiziqli va kvadratik komponentlar. Har bir manba uchun mos keladigan koeffitsientlar skaler parametrlarni o'rnatish funktsiyasi yordamida alohida o'rnatiladi, masalan:

GlLightf(GL_LIGHT0, GL_CONSTANT_ATTENATION, a);

Nuqta manbasini spotlightga aylantirish uchun siz yorug'lik nurining yo'nalishini (GL_SPOT_DIRECTION), intensivlikni taqsimlash funktsiyasi indeksini (GL_SPOT_EXPONENT) va nurning tarqalish burchagini (GL_SPOT_CUTTOF) belgilashingiz kerak. Bu parametrlar glLightf() va glLightfv() funksiyalari yordamida o'rnatiladi.

Standart yorug'lik manbalari uchun o'rnatilgan parametrlar 3-jadvalda ko'rsatilgan.

Chiroqlar uchun standart sozlamalar

3-jadval

Parametr nomi Standart qiymat Tarkib
GL_AMBIENT (0.0, 0.0, 0.0, 1.0) yorug'likning atrof-muhit RGBA intensivligi
GL_DIFFUSE (1.0, 1.0, 1.0, 1.0) yorug'likning diffuz RGBA intensivligi
GL_SPECULAR (1.0, 1.0, 1.0, 1.0) yorug'likning aniq RGBA intensivligi
GL_POSITION (0.0, 0.0, 1.0, 0.0) (x, y, z, w) yorug'likning holati
GL_SPOT_DIRECTION (0.0, 0.0, -1.0) (x, y, z) yorug'lik yo'nalishi
GL_SPOT_EXPONENT 0.0 spotlight ko'rsatkichi
GL_SPOT_CUTOFF 180.0 spotlightning kesish burchagi
GL_CONSTANT_ATTENUATION 1.0 doimiy susaytirish omili
GL_LINEAR_ATTENUATION 0.0 chiziqli susaytirish omili
GL_QUADRATIC_ATTENUATION 0.0 kvadratik susaytiruvchi omil