PV112 – Programování grafických aplikací 5. přednáška – Osvětlení a materiály Osvětlení • OpenGL již nepodporuje osvětlení pomocí vestavěných funkcí, je třeba vše nadefinovat • Pozor na to, ve kterém souřadném systému budete osvětlení počítat • Zásadní roli hrají normály Normálové vektory • Zásadní pro práci s osvětlením • Pro trojúhelník lze spočítat pomocí vektorového součinu dvou jeho hran a následné normalizace triangle (v1, v2, v3); edge1 = v2 - v1; edge2 = v3 - v1; triangle.normal = cross(edge1, edge2).normalize(); Normálové vektory vrcholu • Lze spočítat z normál okolních trojúhelníků vertex v1, v2, v3, ....; triangle tr1, tr2, tr3; // všechny sdílí vrchol v1 v1.normal = normalize(tr1.normal + tr2.normal + tr3.normal); Normály v OpenGL • Zachází se s nimi stejně jako s dalšími parametry vrcholů (pozice, barva, …) GLuint normalbuffer; glGenBuffers(1, &normalbuffer); glBindBuffer(GL_ARRAY_BUFFER, normalbuffer); glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), &normals[0], GL_STATIC_DRAW); Normály v OpenGL glEnableVertexAttribArray(2); glBindBuffer(GL_ARRAY_BUFFER, normalbuffer); glVertexAttribPointer( 2, // attribute 3, // size GL_FLOAT, // type GL_FALSE, // normalized? 0, // stride (void*)0 // array buffer offset ); Normálová matice • Matice 3x3 reprezentující inverzní transponovanou matici transformující vrcholy • Jak je to možné? – Trocha matematiky… Normálová matice • Normálové vektory si představíme jako roviny kolmé k těmto vektorům – převedeme transformace normálových vektorů na transformace těchto kolmých rovin • Homogenní rovina = řádkový vektor (a, b, c, d), alespoň jedna z proměnných je nenulová • q != 0, pak (qa, qb, qc, qd) reprezentuje stejnou rovinu Normálová matice • Bod (x, y, z, w)T leží v rovině (a, b, c, d), pokud ax+by+cz+dw = 0 – w = 1, jde o rovnici Euklidovské roviny (jedna z hodnot a, b, c musí být nenulová) – (0, 0, 0, d) reprezentuje nekonečnou rovinu obsahující všechny body v nekonečnu Normálová matice • Je-li p homogenní rovina a v homogenní vrchol, pak v leží na p zapíšeme jako pv = 0 • Vezměme transformaci M (matice 4x4 mající inverzní matici M-1) • pv = 0 je ekvivalentní k pM-1Mv = 0 – tedy Mv leží v rovině pM-1 • pM-1 je tedy obrazem roviny p transformované pomocí M Normálová matice • Reprezentujeme-li normálový vektor pomocí vektoru, pak uvažujme vzájemně kolmé vektory v a n, pak nTv = 0 • Pro libovolnou transformaci M máme nTM-1Mv = 0 – nTM-1 je transponovaná matice transformovaného normálového vektoru (M-1)Tn • Normálové vektory jsou tedy transformovány inverzní transponovanou maticí transformace aplikované na vrcholy Osvětlení a materiály • Phongův osvětlovací model – Rychlý výpočet osvětlení – Výsledný obrázek se snaží co nejvíce přiblížit realitě • 3 světelné složky: – Ambientní – Difúzní – Spekulární Ambientní složka • Všesměrové světlo – nezávislé na poloze a orientaci zdrojů světla • Objekt se jeví jako plošný – ztrácíme prostorový vjem Difúzní složka • Světlo dopadající na povrch objektu z konkrétního světelného zdroje • Od povrchu objektu se odráží do všech směrů se stejnou intenzitou – matné materiály • Poloha kamery nemá vliv na barvu ani intenzitu difúzní složky Spekulární složka • Paprsek světla se od povrchu tělesa odráží podle zákona odrazu a lomu • Paprsek se neodráží ideálně – bereme v úvahu koeficient změny intenzity odraženého světla Kombinace světelných složek Materiály v OpenGL • Používají se často v kombinaci se světly • Pro výpočet difúzní a spekulární složky světla nutné znát normály ve vrcholech • Vlastnost materiálu se může měnit pro přední a zadní stranu vykreslovaných polygonů (musíme si to ale nadefinovat sami) Materiály • Objekt může mít různý materiál uvnitř a vně (musíme si nadefinovat sami) • Difúzní složka je pro rozpoznávání barev nejdůležitější • Difúzní odrazivost (reflectance) nezávisí na pozici pozorovatele • Spekulární odrazivost závisí na pozici pozorovatele • V reálném světě je difuzní a ambientní světlo ekvivalentní Typy světel v OpenGL • Defaultně nejsou podporována žádná světla, mezi nejjednodušší typy patří: – Směrová – Bodová – Reflektorová Směrová světla • Nemají žádný pevně daný světelný zdroj • Šíří se z jednoho směru nezávisle na vzájemné poloze a vzdálenosti objektů ve scéně • Např. slunce – paprsky téměř paralelní Ambientní složka směrového světla ambient = light_ambient_color * material_ambient_color Jak je počítána barva? - difúze nezáleží na pozici pozorovatele - difúze je největší, když světlo dopadá kolmo na plochu ambient = ambient light * ambient material diffuse = (max{l.n,0}) diffuse light * diffuse material Vertex shader in vec4 position; in vec3 normal; out vec3 N; out vec3 v; uniform mat4 myModelViewMatrix; uniform mat4 myModelViewProjectionMatrix; uniform mat3 myNormalMatrix; void main() { v = vec3(myModelViewMatrix * position); N = normalize(myNormalMatrix * normal); gl_Position = myModelViewProjectionMatrix * position; } in vec3 N; in vec3 v; out vec4 final_color; uniform vec3 material_diffuse_color; uniform vec4 light_position; uniform vec3 light_diffuse_color; void main() { vec3 L = normalize(light_position.xyz); // Toto platí pro směrové světlo, tedy za předpokladu, že light_position je místo v nekonečnu, ODKUD světlo svítí vec3 normN = normalize(N); vec3 Idiff = light_diffuse_color * material_diffuse_color * max(dot(normN, L), 0.0); Idiff = clamp(Idiff, 0.0, 1.0); final_color = vec4(Idiff, 1.0); } Fragment shader Spekulární složka směrového světla • Phongův model Spekulární složka směrového světla • L = vektor směřující od zdroje světla do vrcholu na povrchu objektu • N = normálový vektor • Eye = vektor směřující od vrcholu do oka pozorovatele (nebo kamery) • R = vektor odrazu (světla ze směru vektoru L) • Spekulární složka je úměrná kosinu úhlu α Spekulární složka směrového světla • Pokud má Eye vektor stejný směr jako R, je intenzita spekulárního odrazu největší • Úbytek intenzity (útlum) je úměrný vektoru mezi Eye a R • Útlum je řízen parametrem shininess Spekulární složka směrového světla • Rovnice pro vektor odrazu • Spekulární složka Phongova modelu: • Exponent s = hodnota shininess • Ls = intenzita spekulárního světla • Ms = spekulární koeficient materiálu Blinn-Phongův model • Zjednodušený Phongův model • Využívá tzv. half-vektor = vektor se směrem mezi Eye vektorem a vektorem světla Blinn-Phongův model • Intenzita spekulární složky = cos úhlu mezi half-vektorem a normálou povrchu • Vektory musí být normalizovány • Spekulární složka Blinn-Phongova modelu: Osvětlení – jak je počítána barva? - spekulární odraz záleží na pozici pozorovatele specular = (max{s.n,0}) shininess specular light * specular material Bodová světla • Point light – žárovka v prostoru, která vyzařuje světlo na všechny strany se stejnou intenzitou • Intenzita klesá se vzdáleností • Dva parametry: – w = pozice světla (hodnota 0 odpovídá směrovému světlu) – attenuation = útlum světla (konstatní, lineární, kvadratický) Útlum • Snižování intenzity světla se vzrůstající vzdáleností od světelného zdroje • Jednoduchá simulace kombinuje konstantní c1, lineární c2 a kvadratický c3 útlum • Tyto koeficienty jsou kombinovány v rovnici: • d = vzdálenost světla od vrcholu  2 321 1 dcdcc nattenuatio   Jak je počítána barva? • Pro červenou, zelenou, a modrou komponentu odděleně (Toto je zjednodušení! V reálném světě je spektrum spojité.) • Ambientní, difuzní, a spekulární části jsou sečteny. • Poté jsou sevřeny (clamped) do rozsahu [0,1]. color = global ambientlight*ambientmaterial + light light = attenuation*(ambient+diffuse+specular) attenuation = 1/(const+d*linear+d2*quadratic) Reflektorová světla • Nejsložitější světlo • Světlo se šíří z jednoho bodu pouze v předem zadaném kuželu • Musíme zadat více parametrů: – Pozice světla – Směr šíření světelných paprsků – Úhel šíření světla, kde intenzita světla postupně klesá směrem k nule Reflektorová světla spotDirection směr reflektor. světla (0,0,-1) spotCosCutoff cos úhlu ořezání refl. světla spotExponent jak se intenzita světla snižuje od středu světelného kužele k jeho stěnám Reflektorová světla • Útlum se musí vynásobit následujícím efektem: • spotDirection = definovaný parametr světla • lightDir = vektor od zdroje světla k vrcholu • spotExp = útlum v rámci kužele světla (parametr spotExponent světla) Jak je počítána barva? • ve skutečnosti se provádí kontrola, jestli je vrchol mimo kužel a provádí skalární součin dvou vektorů spot = 1 jestliže světlo není reflektorové (CUTOFF je 180o) 0 jestliže je bodové a vrchol je mimo kužel max{v.d,0}GL_SPOT_EXPONENT Interaktivní ukázka Toon shading • Nefotorealistické zobrazení využívající často pouze tóny jedné barvy • Výpočet kosinu úhlu mezi směrem světla a normálou povrchu Toon shading • Ve vertex shaderu: – Směr světla • Uložení výpočtu kosinu úhlu do proměnné intensity: Toon shading • Fragment shader – spočtení barvy fragmentu s ohledem na intenzitu světla Výsledek Materiály