OpenGL AGI HT05 Gustav Taxén gustavt@nada.kth.se
OpenGL-översikt Geometri Operationer på hörn Rastrering Operationer på fragment Bilddata Operationer på bildelement Texturminne Framebuffert (bildbuffert + hjälpbuffertar)
Geometrispecifikation glbegin(gl_quads); glvertex3f(...);... glend(); 6 sidor, 4 hörn per sida ger 24 hörn skickade till OpenGL för transformation och ljussättning. Också 24 anrop till glvertex().
Vertex arrays Steg 1: Lagra positionsdata för hörnen i en C-array. 6 1 Hörn 0 1 2 3 4 5 6 7 7 0 Array index 012345... 5 2 x y z 4 3
Indexerade primitiver Steg 2: Lagra index för primitiverna i en annan C-array. 6 1 Hörn 0 1 2 3 4 5 6 7 7 0 Array index 012345... 5 2 7 4 3 0 4 3 Array index 012345... Quad 0 1 2 3 4 5
Indexerade primitiver GLfloat positions[] = {... }; GLfloat normals[] = {... }; GLuint indices[] = {... }; glenableclientstate(gl_vertex_array); glvertexpointer(3, GL_FLOAT, 0, positions); glenableclientstate(gl_normal_array); glnormalpointer(gl_float, 0, normals); x, y, z gldrawelements(gl_quads, 6, Antal primitiver GL_UNSIGNED_INT, indices); gldisableclientstate(gl_vertex_array); gldisableclientstate(gl_normal_array);
Indexerade primitiver Klassiska varianten: 6 sidor, 4 hörn per sida: 24 hörn skickade till OpenGL för transformation och ljussättning. 24 funktionsanrop. Indexerade primitiver: 8 hörn skickade till OpenGL för transformation och ljussättning. 2 funktionsanrop.
Interleaved vertex arrays Hörn 0 1 2 3 Array index 012345... x y z nx ny nz stride = 6 st floats GLfloat posandnorm[] = {... }; int stride = 6 * sizeof(glfloat); glenableclientstate(gl_vertex_array); glvertexpointer(3, GL_FLOAT, stride, posandnorm); glenableclientstate(gl_normal_array); glnormalpointer(gl_float, stride, &posandnorm[3]);
Texturer t 1 0 0 1 s
Förstoring och förminskning Texelstorlek = pixelstorlek (inträffar i princip aldrig) Textur Förstoring Pixelpunkter på skärmen Förminskning Textur Pixelpunkter på skärmen
MIP-maps Teknik för att undvika aliasing-problem vid texturförminskning.
MIP-maps Filtrera ett antal texturer i förväg och lagra dem effektivt. Anropa glteximage2d() för varje MIP-mapnivå eller använd glubuild2dmipmaps(). Vid texturering väljs automatiskt den textur som passar bäst m.a.p. avstånd från kameran (om MIP-mapping är aktiverat).
MIP-maps Exempel på olika filteralternativ Visualisering av MIP-mapnivåerna: polygon som sträcker sig bort från kameran
Reflection mapping (R x R y R z ) Samla ljus som anländer från omgivningen och lagra m.a.p. riktning i någon lämplig datastruktur Vid rendering, beräkna reflektionsriktningen (R x R y R z ) och hämta dess färg från datastrukturen
Reflection mapping Algoritmen introducerades av Jim Blinn 1976 Blinn valde en cylinder som datastruktur
Reflection mapping Gene Miller, Michael Shou m.fl. 1982-1983
Reflection mapping Interface, Lance Williams, 1985
Reflection mapping Terminator 2, 1991
Reflection mapping Vi vill hitta ett sätt att transformera riktningar på enhetssfären till en eller flera 2-dimensionella bilder (som grafikkortet kan använda).
Sphere mapping bildplan Antag att vi har en blank sfär och placerar den i en omgivning. Krymp sedan sfären till en punkt. Antag till sist att vi står oändligt långt bort och betraktar sfären (ortogonalprojektion). Vi har nu fångat ljuset i varje riktning på ett bildplan! Observera singulariteten för riktningar rakt bort från bildplanet.
Sphere mapping Givet en reflektionsvektor R = (R x R y R z ) kan vi göra den omvända transformationen och få ut texturkoordinaterna (s, t): s m = = Rx m 2 + 1 2, = + 1 2 ( ( ) ) 1 2 2 2 R + R + R + 1 2 x y t R y m z Sphere mapping stöds direkt i OpenGL. När sphere mapping är aktivt genererar OpenGL själv R och texturkoordinater.
Sphere mapping - problem Riktningar framåt får högre upplösning än riktningar bakåt, och riktningar rakt bort från bildplanet ger en singularitet. Bilden stämmer bara om man roterar ett föremål med statisk kamera. Metoden fungerar inte för en rörlig kamera. Problem vid texturinterpolation för riktningar bakåt. Övre bilden: önskad interpolation. Nedre bilden: hur hårdvaran gör
Sphere mapping - demo
Cube mapping Löser problemen med låg upplösning men använder 6 gånger mer texturminne. Stöds av modern hårdvara.
Bufferttester i OpenGL Djuptest Alphatest Stenciltest Färgbuffert
Alphatest glalphafunc(gl_greater,0.5); glenable(gl_alpha_test); Släpper igenom fragment vars alpha-värde är större än 0.5. Det finns andra alternativ än GL_GREATER (t.ex. GL_LESS). RGBA = (1, 1, 1, 0.7) RGBA = (1, 1, 1, 0.2) Alphatestet behöver ingen egen associerad buffer.
Stenciltest Släpper igenom fragment på de positioner i stencilbufferten där ett (på förhand givet) referensvärde står skrivet. Stencilbuffert Fragment Stenciltestet kräver en egen buffert (oftast 8 bitar).
Stenciltest glstencilfunc() - konfigurerar stenciltestet. glstencilop() - bestämmer vad som ska hända med referensvärdet i fallen då Stenciltestet är FALSKT. Stenciltestet är SANT och djuptestet är FALSKT. Stenciltestet är SANT och djuptestet är SANT.
Stenciltest glstencilfunc(gl_equal, 1, ~0); anger att stenciltestet ska returnera SANT om referensvärdet i stencilbufferten på fragmentets (x, y)-position är lika med 1. ~0 är en bitmask och anger här att alla bitar i referensvärdet ska tas med i testet (~0 = 0xFF för 8 bitar).
Stenciltest glclear(gl_stencil_buffer_bit); glenable(gl_stencil_test); glstencilfunc(gl_always, 1, ~0); glstencilop(gl_replace, GL_REPLACE, GL_REPLACE); glcolormask(gl_false, GL_FALSE, GL_FALSE, GL_FALSE); /* draw something here */ glcolormask(gl_true, GL_TRUE, GL_TRUE, GL_TRUE); glstencilfunc(gl_equal, 1, ~0); glstencilop(gl_keep, GL_KEEP, GL_KEEP); glcolormask(gl_true, GL_TRUE, GL_TRUE, GL_TRUE); /* draw something else here */ Fyll i stencilbufferten utan att uppdatera färgbufferten Rita scenen utan att uppdatera stencilbufferten
Stenciltest och labben Denna del måste klippas bort...
Färgblandning Färg på anländande fragment blandas med färgen på det fragment som redan finns i bildbufferten. R out = R in S R + R bildbuffert D R G out = G in S G + G bildbuffert D G B out = B in S B + B bildbuffert D B där (S R,D R ), (S G,D G ) och (S B,D B ) kallas blandningsfaktorer.
Färgblandning, exempel glblendfunc(gl_src_alpha, GL_ONE_MINUS_SRC_ALPHA); S R D R R out = R in A in + R bildbuffert (1 A in ) Steg 1: Rita gul triangel. Steg 2: glenable(gl_blend); Rita blå triangel med A < 1.
Multitexturing Ofta vill man lägga på mer än en textur på varje polygon: Modern grafikhårdvara stöder att man kombinerar texturerna på olika sätt, t.ex. addition och multiplikation.
Multitexturing GL_REPLACE GL_MODULATE GL_ADD... RGBA från ljussättning (eller glcolor) RGBA från textur 0 Texture Unit 0 GL_REPLACE GL_MODULATE GL_ADD... RGBA från textur 1 Texture Unit 1... Det är inte ovanligt att PC-grafikkort har 8-16 Tetxure Units
Extensions Multitexturing är en s.k. extension. Extensions är utökningar av OpenGL som inte ännu blivit officiella delar av standarden. Lista och dokumentation finns på http://www.opengl.org/ Kräver en ny header-fil: #include <GL/glext.h> (Brukar tillhandahållas av grafikkortstillverkaren, kan annars hämtas från ovanstående webbplats.) Kolla om en extension finns: glutextensionsupported();
Extensions #include <GL/glext.h> #define ARB_ENABLE true ger tillgång till s.k. ARB extensions. Dessa har godkänts av ARB men har inte hamnat i standarden ännu. Ex: GL_ARB_multitexture fanns som ARB extension i OpenGL 1.1 men är standard f.o.m. OpenGL 1.2. Övriga extensions måste man söka funktionspekare till. Se www.opengl.org för exempel.
Multitexturing #include <glext.h> #define ARB_ENABLE true /* Aktivera enhet 0 och ladda textur */ glactivetexturearb(gl_texture0_arb); glenable(gl_texture_2d); glbindtexture(gl_texture_2d,...); /* Aktivera enhet 1 och ladda textur */ glactivetexturearb(gl_texture1_arb); glenable(gl_texture_2d); glbindtexture(gl_texture_2d,...);
Multitexturing (forts.) glbegin(gl_triangles); glmultitexcoord2farb(gl_texture0_arb, 0.0, 0.0); glmultitexcoord2farb(gl_texture1_arb, 0.1, 0.2); glvertex3f(0.0, 0.0, 0.0); glmultitexcoord2farb(gl_texture0_arb, 1.0, 0.0); glmultitexcoord2farb(gl_texture1_arb, 0.6, 0.2); glvertex3f(1.0, 0.0, 0.0); glmultitexcoord2farb(gl_texture0_arb, 0.5, 1.0); glmultitexcoord2farb(gl_texture1_arb, 0.3, 0.5); glvertex3f(0.5, 1.0, 0.0); glend();
Hämta OpenGL-tillst tillstånd Man kan ta reda på vilket värde samtliga tillstånd i OpenGL har genom att använda glget...(); Exempel: aktuell modelview-matris: GLfloat m[16]; glgetfloatv(gl_modelview_matrix, m); (Se OpenGL-specifikationen för mer info.)
Debugging Kan ofta vara klurigt. Man kan dock kolla om man angett ett felaktigt värde till OpenGL genom att använda if (glgeterror()!= GL_NO_ERROR) { /* Något är fel! */ } (Se OpenGL-specifikationen för mer info.)
Labben På Mac (äntligen)! Maya lagrar absoluta sökvägar till texturfiler ändra i RTG-filen om det behövs (eller skriv kod som hanterar det!). Se till att dina texturer är 2 n x 2 m Om din modell inte funkar, pröva med brood.rtg i kurskatalogen (glöm inte att kopiera texturen!). Läs all dokumentation som hör till labben (inkl hela labbpeket) innan du börjar! Dokumenten finns också i kurskatalogen.