Changes between Version 7 and Version 8 of opengl-intro
- Timestamp:
- Feb 12, 2009, 1:12:52 PM (16 years ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
opengl-intro
v7 v8 104 104 minimalnega programa, ki nariše črto, je naslednji: 105 105 106 {\scriptsize\begin{verbatim} 107 subroutine display 108 include 'GL/fgl.h' 109 implicit none 110 call fglClear(GL_COLOR_BUFFER_BIT) 111 call fglColor3f(1.0, 0.4, 1.0) 112 call fglBegin(GL_LINES) 113 call fglVertex2f(0.1,0.1) 114 call fglVertex3f(0.8,0.8,1.0) 115 call fglEnd 116 call fglFlush 117 end 118 119 program crta 120 external display 121 include 'GL/fglut.h' 122 call fglutInit 123 call fglutInitDisplayMode(GLUT_SINGLE + GLUT_RGB) 124 call fglutCreateWindow('Fortran GLUT program') 125 call fglutDisplayFunc(display) 126 call fglutMainLoop 127 end 128 \end{verbatim} 106 107 {{{ 108 #!c 109 #include <GL/glut.h> 110 111 void display() 112 { 113 glClear(GL_COLOR_BUFFER_BIT); 114 glColor3f(1.0, 0.4, 1.0); 115 glBegin(GL_LINES); 116 glVertex2f(0.1, 0.1); 117 glVertex3f(0.8, 0.8, 1.0); 118 glEnd(); 119 glFlush(); 129 120 } 121 122 int main(int argc, char *argv[]) 123 { 124 glutInit(&argc,argv); 125 glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); 126 glutCreateWindow("C GLUT program"); 127 glutDisplayFunc(display); 128 glutMainLoop(); 129 return 0; 130 } 131 }}} 132 130 133 131 Fortranskiprogram je sestavljen iz dveh delov: glavnega programa132 \texttt{crta} in podprograma display. Z ukazom \texttt{fglutInit} 134 C program je sestavljen iz dveh delov: glavnega programa 135 ''main'' in podprograma ''display''. Z ukazom ''glutInit'' 133 136 inicializiramo GLUT knjižnico podprogramov. Sledi zahteva po vrsti 134 okna. S konstantama GLUT \_SINGLE in GLUT\_RGB povemo, da želimo137 okna. S konstantama GLUT_SINGLE in GLUT_RGB povemo, da želimo 135 138 okno z eno ravnino tribarvnega RGB prostora. spremenljivka 136 \texttt{window}hrani številko okna, ki jo naredi137 \texttt{fglutCreateWindow}in hkrati pove OS, kakšen naj bo napis139 ''window'' hrani številko okna, ki jo naredi 140 ''glutCreateWindow'' in hkrati pove OS, kakšen naj bo napis 138 141 na oknu. Okenskemu sistemu moramo še dopovedati, katere dogodke bo 139 142 program prestrezal. Za podani primer je to le prikaz vsebine okna. S 140 klicem podprograma \texttt{fglutDisplayFunc}prijavimo OS, da naj143 klicem podprograma ''glutDisplayFunc'' prijavimo OS, da naj 141 144 pošilja sporočila za izris, knjižnici GLUT pa s tem 142 145 dopovemo, da ob zahtevi za ponovni izris pokliče podprogram 143 \texttt{display}.144 145 Zadnji klic v glavnem programu je vedno \texttt{fglutMainLoop}. Ta146 podprogram se konča le takrat se konča celoten program. Kot že146 ''display''. 147 148 Zadnji klic v glavnem programu je vedno ''glutMainLoop''. Ta 149 podprogram se konča le takrat, ko se konča celoten program. Kot že 147 150 ime podprograma govori, je to glavna zanka programa, v kateri GLUT 148 151 sistematično sprejema sporočila in kliče naše 149 152 podprograme za dogodke. V podanem primeru je to le en tip dogodkov, ki 150 je tudi najbolj uporaben - \texttt{display}. Ostale tipe dogodkov pa151 \texttt{fglutMainLoop}obdeluje na privzeti način, ki je lahko153 je tudi najbolj uporaben - ''display''. Ostale tipe dogodkov pa 154 ''glutMainLoop'' obdeluje na privzeti način, ki je lahko 152 155 preprosto ignoriranje sporočila ali pa klicanje vgrajenega 153 156 podprograma, ki obdela sporočilo. Izgled glavnega programa je tako 154 običajno zelo podoben za vse tipe GLUT programov v katerem si157 običajno zelo podoben za vse tipe GLUT programov, v katerem si 155 158 sledijo ukazi v naslednjem zaporedju: 156 \begin{enumerate} 157 \item Vključi definicije konstant \texttt{GLUT} z ukazom 158 \texttt{include 'GL/glut.h'} 159 \item Dopovej Fortranu, da so imena, kot je npr. \texttt{display}, 160 podprogrami in ne spremenljivke. To se naredi z ukazom \texttt{external} 161 \item Inicializiraj GLUT 162 \item Nastavi parametre okna (položaj, velikost, tip, bitne 159 160 '''1.''' Vključi definicije konstant ''GLUT'' z ukazom 161 ''include 'GL/glut.h' '' 162 163 {{{ 164 2. Dopovej Fortranu, da so imena, kot je npr. ''display'', 165 podprogrami in ne spremenljivke. To se naredi z ukazom ''external'' 166 }}} 167 168 '''2.''' Inicializiraj GLUT 169 170 '''3.''' Nastavi parametre okna (položaj, velikost, tip, bitne 163 171 ravnine, pomnilnik) 164 \item Naredi okno in ga poimenuj 165 \item Prijavi podprograme, ki jih bo program izvajal ob 166 dogodkih. Obvezno prestrezanje je le za \emph{display}. Ostali so poljubni. 167 \item Nastavi lastnosti OpenGL stroja. To so običajno ukazi 168 \texttt{fglEnable} ali pa kakšna nastavitev luči, materialov 172 173 '''4.''' Naredi okno in ga poimenuj 174 175 '''5.''' Prijavi podprograme, ki jih bo program izvajal ob 176 dogodkih. Obvezno prestrezanje je le za ''display''. Ostali so poljubni. 177 178 '''6.''' Nastavi lastnosti OpenGL stroja. To so običajno ukazi 179 ''glEnable'' ali pa kakšna nastavitev luči, materialov 169 180 in obnašanja GL stroja. V tem področju se običajno 170 181 nastavi tudi ostale spremenljivke, ki niso neposredno vezane na 171 182 OpenGL, ampak na samo delovanje programa, ki poleg prikaza dela 172 183 še kaj drugega. 173 \item Zadnji je klic \texttt{fglutMainLoop}, iz katerega se program 184 185 '''7.''' Zadnji je klic ''glutMainLoop'', iz katerega se program 174 186 vrne, ko zapremo okno. Ob tem glavni program konča. 175 \end{enumerate} 176 177 178 \subsection{Izris v jeziku OpenGL} 179 V podprogramu \texttt{display} se morajo torej nahajati ukazi, ki 187 188 == Izris v jeziku OpenGL == 189 190 V podprogramu ''display'' se morajo torej nahajati ukazi, ki 180 191 nekaj narišejo v okno. To so ukazi v jeziku OpenGL ali krajše 181 192 v jeziku GL. Vsi podprogrami ali funkcije v GL imajo predpono pri 182 imenu \emph{gl} oziroma za Fortran \emph{fgl}. Te predpone so potrebne193 imenu ''gl'' oziroma za Fortran ''fgl''. Te predpone so potrebne 183 194 zaradi možnega prekrivanja z imeni v drugih knjižnicah in 184 195 jezikih. Za razumevanje jezika se lahko funkcije razlaga brez teh 185 196 predpon, saj je OpenGL koncipiran tako, da so tipi argumentov za vse 186 197 jezike podobni. Za posamezen jezik se predpostavi prefiks (za Fortran 187 je to \texttt{fgl}, za C pa \texttt{gl})188 189 Podprogram \texttt{display}torej skrbi za izris vsebine okna. Z190 ukazom \emph{Clear}se briše celotno področje okna. Kaj198 je to ''fgl'', za C pa ''gl'') 199 200 Podprogram ''display'' torej skrbi za izris vsebine okna. Z 201 ukazom ''Clear'' se briše celotno področje okna. Kaj 191 202 konkretno se briše povemo z argumentom. V našem primeru je to 192 \texttt{GL\_COLOR\_BUFFER\_BIT}, kar pomeni brisanje vseh točk v203 ''GL_COLOR_BUFFER_BIT'', kar pomeni brisanje vseh točk v 193 204 barvnem pomnilniku. 194 205 195 Z ukazom \emph{Color}se nastavi trenutna barva grafičnih206 Z ukazom ''Color'' se nastavi trenutna barva grafičnih 196 207 gradnikov, ki se bodo izrisovali v nadaljnih ukazih. Kot argument se 197 208 podaja barva v RGB komponentah. Običajno imajo GL ukazi na koncu … … 199 210 podprograma. To je običaj za skoraj vse jezike. Tako imamo za 200 211 Fortran in za C pri podprogramih, kot končnico imena še oznako o 201 številu argumentov in tip argumentov. Podprogram \emph{fglColor3f}202 torej pomeni, da zahteva podprogram tri argumente tipa \texttt{float},203 kar je ekvivalentno v fortranu tipu \emph{real} ali \texttt{real*4}.212 številu argumentov in tip argumentov. Podprogram ''glColor3f'' 213 torej pomeni, da zahteva podprogram tri argumente tipa ''float'', 214 kar je ekvivalentno v fortranu tipu ''real'' ali ''real*4''. 204 215 Najbolj uporabljane GL ukaze lahko torej podamo z različnimi tipi 205 216 argumentov za isti ukaz. Izbor tipa argumentov je odvisen od 206 217 programerja in njegovih zahtev. Tako so argumenti za isto funkcijo 207 218 izbrani glede na priročnost. Za podani primer imamo ukaz 208 \emph{Vertex} v dveh oblikah in isti tip argumentov. \texttt{Vertex2f} 219 ''Vertex'' v dveh oblikah in isti tip argumentov. ''Vertex2f'' 209 220 pomeni, da podajamo kordinate vozlišča z dvema argumentoma. 210 221 Tipi argumentov (končnic) so naslednji: 211 \begin{description} 212 \item[f] V jeziku C float in real ali real*4 za Fortran 213 \item[d] double za C in real*8 za Fortran 214 \item[i] integer 215 \item[s] short integer v C-ju ali integer*2 za F 216 \end{description} 222 223 '''f''' V jeziku C float in real ali real*4 za Fortran 224 225 '''d''' double za C in real*8 za Fortran 226 227 '''i''' integer 228 229 '''s''' short integer v C-ju ali integer*2 za F 230 217 231 Namesto fiksiranega števila argumentov obstajajo tudi funkcije, ki 218 232 imajo podan argument v obliki vektorja. Za to se uporabi končnica 219 \texttt{v}. Nekaj primerov končnic: 220 \begin{description} 221 \item[3f] Sledijo trije argumenti realnih števil 222 \item[3i] Sledijo trije argumenti celih števil 223 \item[3fv] Sledi vektor treh realnih števil 224 \end{description} 225 226 Ker je GL v osnovi 3D pomeni, da so argumenti če sta podani le dve 227 koordinati $x$ in $y$ v ravnini $z=0$. Torej je to ekvivalentno klicu 228 podprograma \emph{Vertex(x, y, 0)}. V našem primeru imamo 233 ''v''. Nekaj primerov končnic: 234 235 '''3f''' Sledijo trije argumenti realnih števil 236 237 '''3i''' Sledijo trije argumenti celih števil 238 239 '''3fv''' Sledi vektor treh realnih števil 240 241 Ker je GL v osnovi 3D, pomeni, da so argumenti, če sta podani le dve 242 koordinati ''x'' in ''y'' v ravnini ''z=0''. Torej je to ekvivalentno klicu 243 podprograma ''Vertex(x, y, 0)''. V našem primeru imamo 229 244 tudi nastavitev vozlišča z ukazom 230 \texttt{Vertex3f(0.8,0.8,1.0)}, ki podaja vse tri koordinate v231 prostoru. Koordinata $z=1$je torej podana, vendar je zaradi245 ''Vertex3f(0.8,0.8,1.0)'', ki podaja vse tri koordinate v 246 prostoru. Koordinata ''z=1'' je torej podana, vendar je zaradi 232 247 privzetega začetnega ortografskega pogleda v prostor ravnine (x,y) 233 koordinata $z$ po globini neopazna. če pa bi bila projekcija248 koordinata ''z'' po globini neopazna. Če pa bi bila projekcija 234 249 perspekvivna in ne ortogonalna, bi opazili tudi vpliv 235 koordinate $z$. Raznolikost tipov argumentov se pokaže ravno pri250 koordinate ''z''. Raznolikost tipov argumentov se pokaže ravno pri 236 251 podajanju vozlišč, saj obstajajo naslednjji podprogrami: 237 \emph{glVertex2d, glVertex2f, glVertex2i, glVertex2s, glVertex3d,238 239 240 241 glVertex4dv, glVertex4fv, glVertex4iv, glVertex4sv}. In vse to za252 ''glVertex2d, glVertex2f, glVertex2i, glVertex2s, glVertex3d, 253 glVertex3f, glVertex3i, glVertex3s, glVertex4d, glVertex4f, 254 glVertex4i, glVertex4s, glVertex2dv, glVertex2fv, glVertex2iv, 255 glVertex2sv, glVertex3dv, glVertex3fv, glVertex3iv, glVertex3sv, 256 glVertex4dv, glVertex4fv, glVertex4iv, glVertex4sv''. In vse to za 242 257 en sam ukaz. 243 258 … … 246 261 in hitrejše kode. V jeziku C++ ali Java, ki pa sam dodaja ustrezne 247 262 argumente k imenom funkcij, pa bi lahko obstajal le en podprogram (npr. 248 \emph{glVertex}), jezik pa bi sam dodal ustrezne končnice in s tem263 ''glVertex''), jezik pa bi sam dodal ustrezne končnice in s tem 249 264 klical ustrezno funkcijo. 250 265 251 266 Izris grafičnih elementov risbe se v GL podaja med ukazoma 252 \emph{glBegin} in \emph{glEnd}. Predmet risanja podamo kot argument v253 ukazu \texttt{Begin}. Na splošno velja, da funkcije brez končnic254 zahtevajo en sam argument s konstanto, ki je podana v \emph{header}255 datoteki s končnico \texttt{.h}in se vključuje za začetek256 programske enote s stavkom \texttt{include 'GL/fgl.h'}. Za fortran je267 ''glBegin'' in ''glEnd''. Predmet risanja podamo kot argument v 268 ukazu ''Begin''. Na splošno velja, da funkcije brez končnic 269 zahtevajo en sam argument s konstanto, ki je podana v ''header'' 270 datoteki s končnico ''.h'' in se vključuje za začetek 271 programske enote s stavkom ''#include <GL/glut.h>''. Za Fortran je 257 272 programska enota vsak podprogram, zato moramo pri vsakem 258 273 podprogramu, ki uporablja te konstante, na začetku dopisati 259 še vključevanje teh konstant. Za C je modul \emph{.c}274 še vključevanje teh konstant. Za C je modul ''.c'' 260 275 datoteka, in ni potrebno vključevanje definicij konstant za vsak 261 276 podprogram, kot je to nujno za Fortran. 262 277 263 Vse te GL konstante, ki so napisane v \emph{fgl.h} in \emph{fglu.h}264 imajo standardno predpono \texttt{GL\_}in je za vse jezike278 Vse te GL konstante, ki so napisane v ''gl.h'' in ''glu.h'' 279 imajo standardno predpono ''GL_'' in je za vse jezike 265 280 enoznačen. Ker pa Fortran ne zahteva deklaracje spremenljivk in 266 281 ima implicitno definirane tipe je prav možno, da se zatipkamo pri 267 282 imenu konstante, kar za Fortran pomeni realno številko z 268 283 vrednostjo 0.0. Da se izognemo takim težavam, se priporoča 269 ukaz \emph{implicit none}, s katerim izključimo predpostavljene284 ukaz ''implicit none'', s katerim izključimo predpostavljene 270 285 tipe in moramo za vsako spremenljivko povedati, kakšnega tipa je. 271 286 žal pa F77 ne omogoča prototipov tako, da je še vedno 272 287 potrebna pazljivost, kakšne tipe podajamo kot argumente 273 podprogramom. Posebno to velja za podprograme \emph{GLU}, ki288 podprogramom. Posebno to velja za podprograme ''GLU'', ki 274 289 običajno nimajo tako razvejanih možnosti argumentov, kot 275 knjižnica \emph{GL}.276 277 Zadnji ukaz \texttt{glFlush}dopove GL stroju naj vse te ukaze, ki jih290 knjižnica ''GL''. 291 292 Zadnji ukaz ''glFlush'' dopove GL stroju naj vse te ukaze, ki jih 278 293 je sprejel do sedaj, spravi iz svojih internih pomnilnikov v okno 279 294 okenskega sistema. Ker imamo v našem primeru le enostaven izris, 280 295 smo se odločili le za en slikovni pomnilnik 281 ( \texttt{GLUT\_SINGLE}), ki je primeren le za statične slike. Za296 (''GLUT\_SINGLE''), ki je primeren le za statične slike. Za 282 297 aplikacije pri katerih se vsebina zaslona pogosto spreminja, je 283 298 primerneje uporabiti okno z dvema grafičnima pomnilnikoma 284 \texttt{GLUT\_DOUBLE}. Prednost slednjega je v tem, da v en pomnilnik299 ''GLUT\_DOUBLE''. Prednost slednjega je v tem, da v en pomnilnik 285 300 rišemo, drugega pa prikazujemo. Rišemo v ravnino, ki je v ozadju. 286 301 Ob koncu risanja pa le zamenjamo ravnini. Ker pa je to odvisno od 287 sistema se ukaz za zamenjavo risalnih ravnin imenuje288 \texttt{glutSwapBuffers}. Prednost takega načina se pokaže pri302 sistema, se ukaz za zamenjavo risalnih ravnin imenuje 303 ''glutSwapBuffers''. Prednost takega načina se pokaže pri 289 304 animacijah. 290 305 291 306 = Geometrijski primitivi = 307 292 308 Uporabiti je mogoče le enostavne primitive. To pa predvsem zaradi 293 309 zahtevane hitrosti in enostavosti izdelave strojnega pospeševanja. 294 310 Ločimo tri vrste teh enostavnih primitivov: 295 \begin{itemize} 296 \item točke ali pike 297 \item črte 298 \item ploskvice konveksnega tipa 299 \end{itemize} 311 312 * točke ali pike 313 314 * črte 315 316 * ploskvice konveksnega tipa 317 318 300 319 Bolj zahtevne predstavitve izvedemo z kombiniranjem teh primitivov. Tako 301 320 krivulje različnih tipov aproksimiramo z lomljenkami, površine 302 321 pa s ploskvicami. Za najbolj razširjene kompleksne tipe se že 303 nahajajo podprogrami v knjižnici \emph{GLU}. Obstajajo tudi322 nahajajo podprogrami v knjižnici ''GLU''. Obstajajo tudi 304 323 možnosti sestavljenih enostavnih gradnikov za črte in 305 324 ploskvice. Za črte poznamo tako naslednje možnosti: 306 \begin{description} 307 \item[GL\_LINES] Pari vozlišč podajajo posamezne segmente 308 \item[GL\_LINE\_STRIP] Zaporedje povezanih vozlišč podaja 325 326 '''GL_LINES''' Pari vozlišč podajajo posamezne segmente 327 328 '''GL_LINE_STRIP''' Zaporedje povezanih vozlišč podaja 309 329 lomljenko 310 \item[GL\_LINE\_LOOP] Lomljenka se zaključi tako, da poveže 330 331 '''GL_LINE_LOOP''' Lomljenka se zaključi tako, da poveže 311 332 prvo in zadnje vozlišče. 312 \end{description} 313 Konstante so podane kot argument za podprogram \emph{Begin}. Za333 334 Konstante so podane kot argument za podprogram ''Begin''. Za 314 335 ploskve se podaja več točk. Najenostavnejše ploskve so 315 336 trikotniki. Možni so še ravninski štirikotniki in konveksni 316 337 ravninski mnogokotniki. Enostavne elemente lahko podajamo tudi v 317 338 pasovih in trikotnike v pahljačah: 318 \begin{description} 319 \item[GL\_TRIANGLES] Tri vozlišča za en trikotnik 320 \item[GL\_TRIANGLE\_STRIP] Pas trikotnikov. Tri vozlišča za 339 340 '''GL_TRIANGLES''' Tri vozlišča za en trikotnik 341 342 '''GL_TRIANGLE_STRIP''' Pas trikotnikov. Tri vozlišča za 321 343 prvi in nato vsako nadaljnje vozlišče k prejšnjemo 322 trikotniku doda nov trikotnik. 323 \item[GL\_TRIANGLE\_FAN] Pahljača: vsako dodatno vozlišče 344 trikotniku doda nov trikotnik. 345 346 '''GL_TRIANGLE_FAN''' Pahljača: vsako dodatno vozlišče 324 347 naredi dodaten trikotnik v smislu dežnika. 325 \item[GL\_QUADS] Ravninski štirikotnik se podaja s štirimi 348 349 '''GL_QUADS''' Ravninski štirikotnik se podaja s štirimi 326 350 vozlišči. 327 \item[GL\_QUAD\_STRIP] Dodatni štirikotniki gradijo pas z 351 352 '''GL_QUAD_STRIP''' Dodatni štirikotniki gradijo pas z 328 353 dodajanjem parov vozlišč. 329 \item[GL\_POLYGON] En sam konveksni mogokotnik poljubnega števila 330 vozlišč. 331 \end{description} 332 Za nesestavljeni tipe gradnikov lahko med \emph{Begin} in \emph{End} 354 355 '''GL_POLYGON''' En sam konveksni mogokotnik poljubnega števila 356 vozlišč. 357 358 Za nesestavljeni tipe gradnikov lahko med ''Begin'' in ''End'' 333 359 podamo tudi več vozlišč. Tip gradnika se pri pri tem 334 avtomatsko ponovi. Med \emph{Begin} in \emph{End}se lahko uporabljajo335 še ukazi za barvo \emph{glColor} in normale \emph{glNormal}. Ti360 avtomatsko ponovi. Med ''Begin'' in ''End'' se lahko uporabljajo 361 še ukazi za barvo ''glColor'' in normale ''glNormal''. Ti 336 362 ukazi nastavljajo trenutno stanje, ki velja za vsa naslednja 337 363 vozlišča. Primer podprograma za prikaz enega trikotnika v 338 364 ravnini je naslednji: 339 {\scriptsize 340 \begin{verbatim} 341 subroutine display 342 implicit none 343 include 'GL/fgl.h' 344 call fglClear(GL_COLOR_BUFFER_BIT) 345 call fglBegin(GL_TRIANGLES) 346 call fglColor3f(1.0, 0.0, 0.0) 347 call fglVertex2f(-1.0, -1.0) 348 call fglColor3f(0.0, 1.0, 0.0) 349 call fglVertex2f(0.0, 1.0) 350 call fglColor3f(0.0, 0.0, 1.0) 351 call fglVertex2f(1.0, 0.0) 352 call fglEnd 353 call fglFlush 354 end 355 \end{verbatim} 365 366 367 {{{ 368 #!c 369 void display() 370 { 371 glClear(GL_COLOR_BUFFER_BIT); 372 glBegin(GL_TRIANGLES); 373 glColor3f(1.0, 0.0, 0.0); 374 glVertex2f(-1.0, -1.0); 375 glColor3f(0.0, 1.0, 0.0); 376 glVertex2f(0.0, 1.0); 377 glColor3f(0.0, 0.0, 1.0); 378 glVertex2f(1.0, 0.0); 379 glEnd(); 380 glFlush(); 356 381 } 382 }}} 383 384 385 357 386 Pred vsako točko je podana še trenutna barva. Izrisani 358 387 trikotnik tako ni enotne barve ampak se njegova notranjost preliva iz