OpenGL SuperBible, Graham Sellers, Richard S. Wright, and Nicholas Haemel, 6 th edition, 2014 Poenostavljen cevovod
Enostaven primer // vertex shader uniform mat4 MVProjMat, MVMat, LightPos; in vec4 Position, Normal; out vec4 n, l, e; void main() { n = MVMat * Normal; // good if no non-uniform scaling vec4 view_vertex = MVMat * Position; l = LightPos - view_vertex; e = -view_vertex; gl_position = MVProjMat * Position; } // fragment shader uniform vec4 c, kd, ka, ks; uniform float p; in vec4 n, l, e; out vec4 Out_Color; l c l n k s R a e void main() { vec4 Out_Color = ka; vec4 N = Normalize(n); vec4 L = Normalize(l); float LN = dot(l,n); if (LN > 0.0) { Out_Color += c * kd * LN; c k c k ( l n) k ( R e) p a a d s } } vec4 E = Normalize(e); vec4 R = reflect(-l, N); Out_Color += c * ks * pow( max(dot(r, E), 0.0), p);
Tekstura ne spreminja barve, temveč vpliva na izračun osvetlitve Vrednosti teksture definirajo normale na površino s tem modeliramo hrapavo ploskev Ne spreminjamo geometrije rezultati so vidni zaradi modela osvetljevanja dobro deluje, ko je predmet oddaljen; ko je blizu, opazimo, da predmet ni 3D, problemi tudi pri sencah Lepljenje normal (normal mapping)
V teksturi RGB komponente predstavljajo XYZ normale Imamo lahko torej normale mapirane v (skoraj) vsakem pikslu V katerem prostoru? največkrat se uporablja tangentni prostor za upodabljanje potrebujemo pretvorbo vektorja luči in pogleda v ta prostor ali obratno Lepljenje normal (normal mapping) Isti model, enkrat z lepljenjem normal
Tangentni prostor Tangent space Definiran z N: normala P u : tangenta vzporedna s smerjo teksture u P v : bitangenta (tudi binormala) vzporedna s smerjo teksture v N = P u x P v Kot normale ga lahko izračunamo v ogliščih
Lepljenje normal (normal mapping) Implementacija: tekstura v RGB vsebuje normalo v tangentnem prostoru skaliranje normal iz tekstur [0,255] na [-1,1] pretvorba prostora vektorja luči, pogleda v tangentni prostor (primer); ali normale v prostor pogleda (primer) izračun osvetlitve z novo normalo N // returns normal in view coordinates vec3 getnormal( vec3 N, vec3 V, vec2 uv) { vec3 map = texture(tex1, uv).xyz; map = map * 255./127. - 128./127.; } // tangent=>view matrix helper mat3 CTBN = cotangent_frame(n, -V, uv); return normalize(ctbn * map);
http://amber.rc.arizona.edu/lw/normalmaps.html Lepljenje normal
Podobno kot lepljenje normal tekstura ne spreminja barve, temveč vpliva na izračun osvetlitve Tekstura je navadno sivinska višinska slika predstavlja izbokline na predmetu Lepljenje izboklin (bump mapping)
Lepljenje izboklin Za izračun izboklin vzamemo vrednosti v višinski teksturi b(u, v) Točko P na predmetu bi navidezno spremenili v smeri normale P u, v = P u, v + b u, v n Razlika v višini pove, koliko moramo spremeniti normalo b u = b v = b u,v u b u,v v = b u + 1, v b(u, v) = b u, v + 1 b(u, v)
Lepljenje izboklin Novo normalo izračunamo kot: n = n + b v P u n + b u n P v Težava za implementacijo za odvode teksture potrebujemo dostop do 4 sosednjih pikslov potratno, rešimo raje z lepljenjem normal
Podobno kot pri lepljenju izboklin je tekstura sivinska slika Tekstura dejansko spreminja geometrijo, torej položaj poligonov model mora biti dovolj podroben, da tekstura dovolj dobro deluje Teselacija (tessellation)- GPU podpora za povečevanje ločljivosti poligonov in lepljenje odmika posledično lahko zmanjšamo kompleksnost modelov detajle prepustimo teksturam NVidia Endless City NVidia Alien vs. Triangles Lepljenje odmika (displacement mapping)
Teselacija Deljenje črt in poligonov na manjše dele Uporaba nivoji podrobnosti (LOD) manjša podrobnost bolj oddaljenih modelov lepljenje odmika risanje parametričnih krivulj Dva senčilnika: Tesselation Control Shader Tesselation Evaluation Shader
Tessellation Control Shader Določi kolikokrat delimo poligon/črto inner: število gnezdenih primitivov outer: kolikokrat se deli vsak rob layout(vertices = 3) out; in vec4 Normal[], LightPos[]; // from vertex shader out vec4 Normal_ES[]; // to TES patch out vec4 LightPos; // to TES void main() { gl_tesslevelinner[0] = 3; // inner levels gl_tesslevelouter[0] = 1; // edge subdivisions gl_tesslevelouter[1] = 1; gl_tesslevelouter[2] = 1; } gl_out[gl_invocationid].gl_position = gl_in[gl_invocationid].gl_position; Normal_ES[gl_InvocationID] = Normal[gl_InvocationID]; LightPos = LightPos[gl_InvocationID];
Tessellation Evaluation Shader Dobi položaj novega oglišča v težiščnih koordinatah v gl_tesscoord Lahko interpolira med vrednostmi v ogliščih položaj, normala premika oglišča lepljenje odmika, npr. kot: layout(triangles, equal_spacing, ccw) in; uniform mat4 ProjMat; in vec4 Normal_ES[]; // from TEC patch in vec4 LightPos; // from TEC out vec4 n, l, e; // to fragment shader void main() { // barycentric coordinates float u = gl_tesscoord.x; float v = gl_tesscoord.y; float w = gl_tesscoord.z; vec4 pos = vec4(1); pos.xyz = u*gl_in[0].gl_position.xyz + v*gl_in[1].gl_position.xyz + w*gl_in[2].gl_position.xyz; n = u*normal_es[0]+v*normal_es[1] + w*normal_es[2]; float d = (texture(tex0, TexCoord).x-0.5); pos += n * d * 3.0; } l = LightPos - pos; e = -pos; gl_position = ProjMat * pos;
Senčilnik geometrije Ustvari lahko novo geometrijo Primer: Billboarding Ideja: poligon s teksturo vedno obrnjen proti kameri V programu generiramo točke v senčilniku geometrije točko spremenimo v štirikotnik (quad) s teksturo (billboarding) Implementacija senč. oglišč: točko pretvorimo v prostor kamere geom.: ustvarimo štirikotnik okoli točke in UV koordinate teksture frag.: izrišemo štirikotnik layout (points) in; layout (triangle_strip) out; layout (max_vertices = 4) out; uniform float ParticleSize; uniform mat4 gxl3d_projectionmatrix; out vec2 Vertex_UV; void main() { vec4 P = gl_in[0].gl_position; // a: left-bottom vec4 va = P + vec4(-0.5,-0.5,0,0) * ParticleSize; gl_position = gxl3d_projectionmatrix * va; Vertex_UV = vec2(0.0, 0.0); EmitVertex(); // b: left-top vec4 vb = P + vec4(-0.5, 0.5,0,0) * ParticleSize; gl_position = gxl3d_projectionmatrix * vb; Vertex_UV = vec2(0.0, 1.0); EmitVertex(); // d: right-bottom vec4 vd = P + vec4(0.5,-0.5,0,0) * ParticleSize; gl_position = gxl3d_projectionmatrix * vd; Vertex_UV = vec2(1.0, 0.0); EmitVertex(); // c: right-top vec4 vc = P + vec4(0.5,0.5,0,0) * ParticleSize; gl_position = gxl3d_projectionmatrix * vc; Vertex_UV = vec2(1.0, 1.0); EmitVertex(); EndPrimitive(); }
Z lepljenjem okolice lahko simuliramo odboje svetlobe imenujemo ga lahko tudi reflection mapping Smer odbite svetlobe določa teksle na teksturi Lepljenje okolice environment mapping Image by Henrik Wann Jensen, Environment map: Paul Debevec
CubeMap tekstura predstavlja vseh 6 smeri pogleda nalepimo na kocko, predstavlja okolico (SkyBox) Upodabljanje okoli scene postavimo kocko transformacije po z koordinati (globina) izničimo UV == položaj oglišča (lastnost vpogleda v cubemap texturo) izrišemo najprej, brez testa globine Okolica // vertex uniform mat4 MVMat, ProjMat; in vec4 Position; out vec4 VertexUV; void main() { mat4 r = MVMat; // no translations r[3][0] = 0.0; r[3][1] = 0.0; r[3][2] = 0.0; } Vertex_UV = gxl3d_position; gl_position = (ProjMat * r) * gxl3d_position; // fragment uniform samplercube cubemap; in vec4 VertexUV; out vec4 Out_Color; void main() { vec3 uv = VertexUV.xyz; vec3 t = texture(cubemap, normalize(uv.xyz)).rgb; Out_Color = vec4(t, 1.0); } http://learnopengl.com/#!advanced-opengl/cubemaps
Barvo predmeta računamo kot odboj žarka iz kamere na skybox teksturo Upodabljanje izračunamo odboj vektorja pogleda preko normale pretvorimo v koordinate sveta, preberemo teksturo Lepljenje okolice //fragment uniform samplercube cubemap; uniform mat4 VMat; // view matrix in vec4 n, e; out vec4 Out_Color; void main() { vec4 N = normalize(n); // normal vec4 E = normalize(e); // eye vec4 reflected = reflect (-E, N); reflected = inverse(vmat)*reflected; // to world } Out_Color= texture(cubemap, vec3(reflected)); http://antongerdelan.net/opengl/cubemaps.html demo
Sence Sence povečajo realizem, dajo občutek globine Več možnosti za sence: vnaprej izračunane za statične predmete in zapečene v teksture lightmaps računanje med izrisovanjem shadow mapping Unity Lightmaps
Osnovna ideja : točka je osvetljena, če je vidna iz luči vidnost iz luči izračunamo s postavitvijo kamere na položaj luči in izrisom scene Lepljenje senc (shadow mapping) Točka je osvetljena, če je vidna iz luči Vidnost lahko določimo s postavitvijo kamere na položaj luči
Lepljenje senc Prvi korak: izris scene s postavitvijo kamere na položaj luči shrani dobljeno globinsko sliko (razdaljo do luči), ki ji rečemo zemljevid senc (shadow map) pri izrisu shranimo depth buffer v teksturo luč = kamera zemljevid senc (shadow map) zemljevid hrani razdaljo od predmeta do luči globinska slika, kot jo vidimo iz luči
Lepljenje senc Drugi korak: luč kamera izris scene s položaja kamere na vsakem pikslu razdaljo do luči primerjamo z razdaljo shranjeno v zemljevidu senc b a v a ni v senci če je daljša, smo v senci (v b na sliki) če je enaka oz. krajša, je piksel osvetljen (v a na sliki) v b je v senci slika s sencami
Lepljenje senc Implementacija 2. koraka senčilnik oglišč vsako oglišče pretvorimo tudi v prostor luči s transformacijsko matriko luči senčilnik fragmentov primerjamo z zemljevidom senc upoštevamo korekcijski faktor Podrobnejši opis... // shadow map uniform sampler2dshadow shadow_map; // vertex in light coordinates from vertex shader in vec4 V_Shadow; out vec4 Out_Color; void main() { // shadow factor float shadow = 1.0; // check if within light volume if (V_Shadow.w > 0.0 && V_Shadow.w < 190) { vec4 fragdepth = V_Shadow / V_Shadow.w ; fragdepth.z -= 0.0005; float lightdist = texture(shadow_map,fragdepth.xyz); // in shadow if depth larger than in shadow map shadow = lightdist < fragdepth.z? 0.5 : 1.0 ; } vec4 final_color;... calculate final color } Out_Color.rgb = final_color * shadow; // use shadow Out_Color.a = 1.0;
Ambientno zastiranje Ambient occlusion Deli predmetov so zastrti zaradi bližine drugih delov posledično so temnejši npr. mehke sence v kotih ali v ozkih predelih zastrti deli. Vir
Ambientno zastiranje Ideja: screen-space AO izračun faktorja zastiranja v vsakem fragmentu V vsakem fragmentu vzorčimo okolico npr. v polkrogli usmerjeni kot normala odstotek točk, ki je pod površino je faktor zastiranja ugotovimo iz globinske slike z njim potemnimo sliko Primer implementacije zastrti deli. Vir
Deferred rendering (shading) Standardno Phongovo senčenje: osvetlitev O(št_geom_fragmentov * št_luči) Odloženo senčenje: osvetlitev izvedemo na zaslonskih pikslih O(ločljivost_zaslona * št_luči) Dva prehoda prvi: izračun podatkov za osvetljevanje (barva, globina,normale) v medpomnilnike drugi: uporaba shranjenih podatkov in izračun osvetlitve v prostoru slike Prednost: hitrost - osvetljevanje je ločeno od geometrije Težave osvetlitev računamo na koncu, za vsako luč le za piksle, ki jih osvetli različni materiali zahtevajo več medpomnilnikov težje mehčanje robov (detekcija robov ) ni transparence Odloženo upodabljanje Odloženo senčenje
Implementacija V 1. koraku v medpomnilnike (G-buffer) shranimo vsaj barvo, normale, globino (ali položaj) Odloženo upodabljanje V 2. koraku za vsak viden piksel vemo globino, barvo in normalo izračunamo osvetlitev končno barvo upoštevamo le luči, ki dosežejo piksel (luči imajo omejen domet) celo sceno lahko izrišemo npr. na en pravokotnik globina barva normale zrcalni odsev končna slika
Dobra diploma Marko Tatić: Odloženo upodabljanje opis postopkov odloženega upodabljanja, implementacija z različnimi tipi luči
Rockstar GTA V (vir) Upodabljanje v igri
Upodabljanje v igri 1. Cubemap okolja (za odboje lepljenje okolice) 2. Pretvorba v dve polkrogli (hitreje)
3. Izločanje Level of Detail Upodabljanje v igri odvisno od razdalje, se predmet izriše v visoki ali nizki ločljivosti ali pa se sploh ne (npr. trava v daljavi)
4. Odloženo upodabljanje 1. del G buffers Upodabljanje v igri
4. Odloženo upodabljanje 1. del G buffers Upodabljanje v igri globina se hrani obrnjeno (logaritmični z buffer), več poudarka na oddaljenih predmetih stencil buffer segmentira različne objekte (vsak ima svojo vrednost oz. id
Upodabljanje v igri 5. Sence 4 zemljevidi senc (bolj natančni blizu, manj daleč)
6. Odsev v vodi Upodabljanje v igri scena izrisana obrnjeno (po y) v teksturo, ki bo nalepljena na vodo kot odsev
7. Ambientno zastiranje Upodabljanje v igri
8. Sestava slike Upodabljanje v igri
Upodabljanje v igri 9. Boljša koža subsurface scattering prej po SSS
Upodabljanje v igri 10. Voda odsev, lom svetlobe, lepljenje odmika (za valove)
11. Atmosfera (volumetrične sence, megla, nebo, oblaki) Upodabljanje v igri
12. Prosojni predmeti Upodabljanje v igri
13. HDR v LDR vse teksture, ki so 16 bit float (HDR), se pretvorijo v 8 bitne Upodabljanje v igri
14. Mehčanje robov in popačenje leče Upodabljanje v igri
15. UI (minimap) Upodabljanje v igri
REFERENCE Klemens Jahrmann: Hardware-Tessellation (slides) John Chapman: SSAO Tutorial Adrian Courreges: GTA V - Graphics Study