Tietokonegrafiikka / perusteet Ako/T-111.300/301 4 ov / 2 ov OpenGL 2 Display Listat Tekstitys GLUT:lla Teksturointi Varjot Lopuista harjoituksista Valaistus ja materiaalit GLUT Sisällys Marko Myllymaa 06/04 OpenGL / 1 OpenGL / 2 Display-Listat Cache (kätkö) OpenGL-kutsuille Sopii objektien tallettamiseen geometria attribuutit Yleisesti tehokkaampaa kuin yksittäiset OpenGL-kutsut talletetaan näytönohjaimen muistiin riippuu näytönohjaimesta ja sen ajurista Voidaan tehdä monimutkaisia hierarkisia objekteja Älä käytä turhaan! Ei yksittäisiä kolmioita Ei muuttuvia objekteja Kovin suuri malleja ei kannata laittaa yhteen display-listaan, kannattaa mieluummin jakaa malli pienempiin osiin ja sitten poistaa siitä näkymättömät osat, esim. BSP tai dpvs Display-listaa ei voi muuttaa, se pitää tuhota ja luoda uudestaan OpenGL / 3 Display-listan luominen: glnewlist() tässä kaikki display-listaan tulevat OpenGL-kutsut glendlist() Display-listan numero luodaan funktiolla glgenlists() Display-listaa käytetään funktiolla glcalllist() Display-lista voi sisältää kutsuja muihin display listoihin WV_list = glgenlists(1); glnewlist(wv_list, GL_COMPILE);//GL_COMPILE_AND_EXECUTE glcalllist(wv_hull_list); glcalllist(wv_tires_list); glcalllist(wv_list); glislist() - tarkistaa onko lista olemassa gldeletelists() - tuhoa listan (listat) OpenGL / 4 Listaa tehtäessä voidaan käyttää mitä tahansa algoritmeja ja laskutoimituksia: buildcircle(int circle_list) { Glint I; Glfloat x, y; glnewlist(circle_list, GL_COMPILE); glbegin(gl_line_loop); for(i=0; i<8; i++) { x = cos(i*2*m_pi/8.0); y = sin(i*2*m_pi/8.0); glvertex2f(x, y); Vain lopulliset arvot ja OpenGL-kutsut talletaan display-listaan OpenGL / 5 Listaa kutsuttaessa se muuttaa OpenGL:n tilaa ja nykyistä matriisipinoa, aivan kuten tavalliset OpenGL-kutsut Attribuutit ja nykyinen matriisi voidaan tallettaa glpush*():lla ja palauttaa taas glpop*():llä glnewlist(indexi, GL_COMPILE); glpushmatrix(); glpushattrib(gl_current_bit); gltranslatef(1.5,0.0,0.0); glcolor3f(1.0,0.0,0.0); glbegin(gl_triangles); glvertex2f(0.0,0.0); glvertex2f(1.0,0.0); glvertex2f(0.0,1.0); glpopattrib(); glpopmatrix(); OpenGL / 6 20 erilaista attribuuttiryhmää (bufferit, valaistus, enabloidut bitit, sumu, jne) GL_CURRENT_BIT = color, normal, texture coords, edge_flag, rasterization info 1
GLUT:in fontit Viiva fontti (stroke font) Kirjaimet tehdään viivoilla Skaalattavia void glutstrokecharacter(void *font, int character); GLUT_STROKE_ROMAN, GLUT_STROKE_MONO_ROMAN void *font = GLUT_STROKE_ROMAN; char message[] = Hello World! ; glenable(gl_line_smooth); glblendfunc(gl_src_alpha, GL_ONE_MINUS_SRC_ALPHA); gllinewidth(3.0); glrotatef(45, 0.0,0.0,1.0); Bittikarttafontti 1-bittinen rasterikuva Nopea Ei skaalattavissa, vakio koko GLUT:n fontit void glutbitmapcharacter(void *font, int character); GLUT_BITMAP_8_BY_13, GLUT_BITMAP_9_BY_15, GLUT_BITMAP_TIMES_ROMAN_10, _24, GLUT_BITMAP_HELVETICA_10, _12, _18 for(int i=0;i < len; i++) glutstrokecharacter(font, message[i]); OpenGL / 7 OpenGL / 8 GLUT-menut Yksinkertainen menumekanismi: void controllights(int value) { switch(value) { case 1: glutfullscreen(); case 2: lightswitch =!lightswitch; if(lightswitch) glenable(gl_light0); else gldisable(gl_light0); case 3: exit(0); glutpostredisplay(); glutcreatemenu(controllights); glutaddmenuentry( Full Screen, 1); glutaddmenuentry( Toggle light, 2); glutaddmenuentry( Quit, 3); glutattachmenu(glut_right_button); GLUT-dino OpenGL / 9 OpenGL / 10 Teksturointi Liimataan kuvia pintoihin Helposti ja halvalla yksityiskohtia sama kuva voidaan kopioida monta kertaa, esim. Tiiliseinä mäppäys : annetaan polygonin vertexeille tekstuurikoordinaatit Tekstuurin koko on aina kahden potensseja OpenGL:ssä 16x16, 32x32, 64x64, 128x128, Tekstuurit voidaan luoda kahdella tapaa: 1. Ladataan tekstuuri tiedostosta, käyttäen esim. readtex.c:tä GLubyte *LoadRGBImage(const cahr *file, GLint *width, GLint *height, GLenum *format) 2. Luodaan tekstuuri sopivalla algoritmilla suoraan muistiin sopii yksikertaisiin tekstuureihin, kuten shakkikuvioon OpenGL / 11 Tekstuurit Tekstuurit ja niiden parametrit voidaan koota nimettyyn tekstuuriobjektiin luo tekstuurien nimet liitä nimi ja kuva sekä parametrit yhteen priorisoi, mikäli tarpeellista laita tekstuurikoordinaatit vertexeihin (eli käytä tekstuuria) tuhoa tekstuuri GLuint texnames[2]; GLubyte *image=null;... glgentextures(2, texnames); glbindtexture(gl_texture_2d, texnames[0]); gltexparameteri(gl_texture_2d, GL_TEXTURE_WRAP_S, GL_CLAMP); gltexparameteri(gl_texture_2d, GL_TEXTURE_WRAP_S, GL_CLAMP); glteximage2d(gltexture_2d, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);... gldeletetextures(2, texnames); OpenGL / 12 2
Tekstuurin parametrit Muistiin talletettavan tekstuurin formaatti: glpixelstorei(gl_unpack_alignment, 1); Textuurin wräppäys : gltexparameteri(gl_texture_2d, GL_TEXTURE_WRAP_S, GL_WRAP); gltexparameteri(gl_texture_2d, GL_TEXTURE_WRAP_S, GL_WRAP); Teksturointitapa (decal, modulate, blend): gltexenvf(gl_texture_env, GL_TEXTURE_ENV_MODE, GL_DECAL); Muista enabloida teksturointi! glenable(gl_texture_2d); Tekstuurin määritykset glteximage2d: halutun tekstuurin tyyppi (GL_TEXTURE_2D) mipmap:n taso sisäinen esitysmuoto (R, G, B, A) leveys ja korkeus reuna (0 tai 1) kuvan formaatti ja tyyppi (RGB, unsigned byte) pointteri kuva dataan glteximage2d(gl_texture_2d, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, &checkimage[0][0][0]); OpenGL / 13 OpenGL / 14 Tekstuurikoordinaatit Määritä jokaiselle vertexille tekstuuri koordinaatti! void display(void) { glclear(gl_color_buffer_bit GL_DEPTH_BUFFE_BIT); glbegin(gl_quads); gltexcoord2f(0.0,0.0; glvertex3f(-2.0,-1.0,0.0); gltexcoord2f(0.0,1.0; glvertex3f(-2.0, 1.0,0.0); gltexcoord2f(1.0,1.0; glvertex3f( 0.0, 1.0,0.0); gltexcoord2f(1.0,0.0; glvertex3f( 0.0,-1.0,0.0); gltexcoord2f(0.0,0.0; glvertex3f(1.0,-1.0,0.0); gltexcoord2f(0.0,1.0; glvertex3f(1.0, 1.0,0.0); gltexcoord2f(1.0,1.0; glvertex3f(2.4, 1.0,-1.4); gltexcoord2f(1.0,0.0; glvertex3f(2.4,-1.0,-1.4); glflush(); Mipmap:t Erikokoisia tekstuureita samasta kuvasta, originaali, 1/4, 1/16, 1/64,..., 1 pikseli Optimointia, käytetään pienempiä tekstuureita pienemmille polygoneille Maksimi detaljit vain lähietäisyydeltä katsottaessa Esifiltteröinti: gltexparameteri(gl_texture_2d,gl_texure_min_filter,gl_nearest); pistemittaus: GL_NEAREST_MIPMAP_NEAREST bilinear: GL_LINEAR_MIPMAP_NEAREST trilinear: GL_LINEAR_MIPMAP_LINEAR OpenGL / 15 OpenGL / 16 Blendaus Värien sekoitusta alpha-kanavan mukaan Läpinäkyvyys: Muista disabloida Z-bufferi ja enabloida blendaus gldisable(gl_depth_test); Blendausfunktio voidaan valita: pikseli = f(source target) f = glblendfunc(sfactor, dfactor) Tyypillinen käyttötapa: 1. piirrä ensimmäinen objekti seuraavilla tekijöillä: sfactor = GL_ONE dfactor = GL_ZERO 2. Piirrä seuraava objekti puolella alphalla glcolor(0.0,1.0,0.0,0.5); sfactor = GL_SRC_ALPHA dfactor = GL_ONE_MINUS_SRC_ALPHA OpenGL / 17 Antialiasointi Poistaa liian pienestä sämpläystaajuudesta (eli resoluutiosta) johtuvaa porrasmaisuutta Alpha-kanavaa voidaan käyttää peittävyyden laskentaan Käytännössä blendataan vierekkäiset pikselit Melko helppoa pisteille ja viivoille: glenable(gl_line_smooth); glblendfunc(gl_src_alpha,gl_one_minus_src_alpha); glhint(gl_line_smooth_hint, GL_DONT_CARE); gllinewidth(1.5); Polygoneille on olemassa erilaisia antialiasointitapoja OpenGL / 18 3
Antialiasointi Yksi tapa antialiasoida polygoni: 1. Reunapikselien alphaan pienet arvot glenable(gl_polygon_smooth); 2. Poista syvyys testi käytöstä gldisable(gl_depth_test); 3. Valitse blendausfunktio reunapikseleille glblendfunc(gl_src_alpha_saturate, GL_ONE); 4. Piirrä syvyysjärjestyksessä (takaa eteen) Antialiasointia voidaan tehdä myös supersampling:llä Tai accumulation bufferia voidaan käyttää tähän tarkoitukseen Sumu Sumu hävittää (fading) objectit etäisyyden funktiona Sillä saadaan lisää syvyysvaikutelmaa Implementaatio käyttää Z-bufferia sumun laskentaan Sumun ominaisuuksia: void glfog*(glenum pname, TYPE param); pname: param: GL_FOG_MODE GL_EXP,GL_EXP2,GL_LINEAR (GL_EXP) GL_FOG_COLOR RGBA arvo (0.0,0.0,0.0,0.0) GL_FOG_DENSITY sumun tiheys (EXP) (1) GL_FOG_START sumun aloitusetäisyys (LINEAR) (0) GL_FOG_END sumun lopetusetäisyys (LINEAR)(1) OpenGL / 19 OpenGL / 20 Objektin valinta (picking) Objektin valinta htedään yleensä jonkin eventin tapahtuessa, esim. hiiren nappulaa painettaessa OpenGL antaa melko karun tavan toteuttaa tämä: 1. Luo taulukko osumille, tai select bufferi 2. alusta nimipino 3. rajoita piirtoalue kursorin lähelle (glupickmatrix()) 4. Piirrä GL_SELECT -tilassa, anna piirron aikana objekteille nimet (kokonaisluvut) 5. Palaa GL_RENDER -tilaan 6. Hae osumataulukosta lähin objekti Osumataulukko (select bufferi) sisältää: indexi zmin zmax objektin nimi (kokonaisluku) OpenGL / 21 Objektin valinta (glpuzzle.c) int selectpiece(int mousex, int mousey) { long hits; GLuint selectbuf[1024], closest dist; glselectbuffer(1024, selectbuf); glrendermode(gl_select); glinitnames(); glpushname(-1); glmatrixmode(gl_projection); glloadidentity(); glupickmatrix(mousex,h-mousey,4,4,viewport); gluperspective(45,1.0,0.1,100.0); drawall(); hits = glrendermode(gl_render); if(hits <= 0) return 0; closest = 0; while(hits) { if(selecbuf[(hits-1)*4+1] < dist) { dist = selecbuf[(hits-1)*4+1]; closest = selecbuf[(hits-1)*4+3]; hits--; return closest; OpenGL / 22 Tekstuurit ja kiilto Valaistuslaskut tehdään ennen teksturointia, joten tekstuureja ei saa kiiltämään ratkaisu: piirretään kahteen kertaan ja yhdeistetään tulokset static void display(void) { glclear(gl_color_buffer_bit GL_DEPTH_BUFFER_BIT); glpushmatrix(); /* diffuusi texturoitu */ glenable(gl_texture_2d); gllightfv(gl_light0, GL_DIFFUSE, White); gllightfv(gl_light0, GL_SPECULAR, Black); glcalllist(sphere); Tekstuuri ja kiilto /* blendataan kiilto mukaan */ gldepthfunc(gl_equal); gldisable(gl_texture_2d); /* redraw same pixels */ glblendfunc(gl_one, GL_ONE); /* adding */ gllightfv(gl_light0,gl_diffuse,black); gllightfv(gl_light0,gl_specular,white); glcalllist(sphere); gldepthfunc(gl_less); gldisable(gl_blend); glpopmatrix(); glutswapbuffers(); OpenGL 1.2:ssa: gllightmodeli(gl_light_model_control_color, GL_SEPARATE_SPECULAR_COLOR); OpenGL / 23 OpenGL / 24 4
Optimointia Kaikki keinot sallittuja fps:n nostamiseksi! Yleensä: Älä piirrä mitään mikä ei näy ruudussa Kaikki on sallittua, kunhan se näyttää hyvältä Tarkennuksia: Tee usein käytetyistä objekteista display-listoja Käytä yksipuolista valaistusta Käytä ainoastaan yhtä tai kahta valonlähdettä Disabloi LOCAL_VIEWER valaistuksessa Poista (cull) taustapinnat O2:lla, käytä cc:tä Optimointia Minimoi geometria, käytä tekstuureita yksityiskohtiin Käytä GL_TRIANGLE_STRIP:jä, ne ovat nopeimpia Vältä yksittäisiä polygoneja Laita vertexit vertexitaulukkoon Vältä turhaa tilojen vaihtoa Pyri ryhmittelemään objektit saman ominaisuuden mukaan, esim. tekstuuri, väri, materiaali Käytä vain nimettyjä textuureita glcullface(gl_back); gllightmodelf(gl_light_model_two_side, GL_FALSE); gllightmodelf(gl_light_model_local_viewer,gl_false); OpenGL / 25 OpenGL / 26 5