Koodasin tuossa SDL & OpenGL ohjelmaa (kiitos Metabolixille tutoriaalista) ja kun käänsin ja ajoin, ei näytölle ilmestynytkään tarkoituksenmukaisia kymmentä viivaa. Mikäs tässä on siis vikana?
#include <SDL/SDL.h> #include <SDL/SDL_opengl.h> #include <cmath> //milliseconds per frame tai jotain sen suuntaista #define WANTED_MSPF 50 //screen-surfeissi SDL_Surface *screen; //aikasäädöt static Uint32 wanha,uusi; //pelin sisälläololoopin tarkistusbittisäätöjutskafoo bool ingame; //vähän niinku viewport, emt class camera { public: int x,y,w,h,s; void translate(); camera(); ~camera(); }; void camera::translate() { glLoadIdentity(); } camera::camera() { } camera::~camera() { } //ukkeli, eli sellane viiva class dude { public: int x,y,a; void draw(camera Kamera); dude(); dude(int x,int y); ~dude(); }; //piirtofunktio void dude::draw(camera Kamera) { glBegin(GL_LINES); glVertex3i(x,y,0); glVertex3i(x+(cos(a)*10),y+(sin(a)*10),0); glEnd(); } dude::dude() { } dude::dude(int x,int y) { } dude::~dude() { } //tyypit dude dudes[10]; camera viewiportti; SDL_Event tapahtuma; Uint8 *napit; void handleEvents() { SDL_PollEvent(&tapahtuma); if (tapahtuma.type==SDL_QUIT) exit(0); } //aika kesken TODO: cos&sinfunktiosäädöt void handleKeyPresses() { napit=SDL_GetKeyState(NULL); if(napit[SDLK_UP]) dudes[0].y--; if(napit[SDLK_DOWN]) dudes[0].y++; if(napit[SDLK_LEFT]) dudes[0].x--; if(napit[SDLK_RIGHT]) dudes[0].x++; if(napit[SDLK_ESCAPE]) ingame=false; } //funktio jonka pitäis piirtää sälät näytölle void drawStuff() { for(int i=0;i<10;i++) dudes[i].draw(viewiportti); } //ladataan säädöt void loadglstuff() { glViewport(0,0,800,600); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f,800.0f/600.0f,0.1f,100.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); viewiportti.x=0; viewiportti.y=0; viewiportti.w=800; viewiportti.h=600; viewiportti.s=0; for(int i=0;i<10;i++) dudes[i] = dude(i,i); } int main(int argc,char *argv[]) { printf("Starting...\n"); if(SDL_Init(SDL_INIT_VIDEO)) { fprintf(stderr,"SDL didn't work! %s\n",SDL_GetError()); exit(1); } atexit(SDL_Quit); screen=SDL_SetVideoMode(800,600,0,SDL_FULLSCREEN|SDL_OPENGL); printf("Screen has been set.\n"); SDL_GL_SetAttribute(SDL_GL_RED_SIZE,8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,8); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,16); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1); printf("Attributes have been set.\n"); glShadeModel(GL_SMOOTH); glClearColor(0.0f,0.0f,0.0f,0.0f); glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); loadglstuff(); printf("GL funcs have been set.\n"); ingame=true; while(ingame) { drawStuff(); SDL_GL_SwapBuffers(); //Wait a second. wanha=uusi; handleKeyPresses(); handleEvents(); while((uusi-wanha)<WANTED_MSPF) { //handleKeyPresses(); //handleEvents(); uusi=SDL_GetTicks(); } } exit(1); return 0; }
Pikaisella vilkaisulla näyttäisi, että z-koordinaatti piirtovaiheessa on nolla. Perspektiivi kuitenkin alkaa vasta 0.1:stä (kuten sen itse asetat). Täytyy siis piirtää z-koordinaattien 0.1 ja 100.0 väliin. (Suosittelen noiden vaihtamista hieman lähemmäs ykköstä, vaikkapa 0.2 ja 16.0.)
Jos et kaipaa perspektiiviä (jos teet 2D:tä), kannattaa ottaa selvää glOrtho-funktion toiminnasta.
Kiitos todella, todella paljon! Sain ansiostasi tietää, miksi kaikki projektini, joissa olen yrittänyt käyttää OpenGL:ää ovat menneet nurin! :DD Kiitos!
Miksi muuten suosittelet että vaihtaisin nuo luvut lähemmäksi ykköstä? Onko siitä jotakin muutakin hyötyä kuin se, ettei kone piirrä niitä aivan kauimpina olevia objekteja?
Syvyyspuskurissa arvot skaalataan välille [0, 1] käsittääkseni jokseenkin tällaisella kaavalla:
z = (1/Zn - 1/Z) / (1/Zn - 1/Zf)
, missä Zn ja Zf ovat siis nuo annettavat arvot ja iso Z on piirrettävän pisteen z-koordinaatti (ja pieni z syvyyspuskuriin laitettava arvo).
Luonnollisesti lukujen tarkkuus on rajallinen. Parhaimmillaankin 8-bittiseen syvyyspuskuriin saa enintään 256 eri arvoa, 16-bittiseen 65536 ja 24-bittiseen 16777216. Jos tuo äsken skaalattu arvo laajennetaan näille lukualueille suoralla kertolaskulla, tulee tällaisia tuloksia:
Zn = 0.1, Zf = 100.0, Syvyyspuskuri 8 bittiä: 0.1 => 0 0.5 => 204 1.0 => 229 20.0 => 253 21.0 => 254 100.0 => 255
Näissä nyt oli vain 8-bittinen syvyyspuskuri, isommilla tietenkin tarkkuus paranee. Kuitenkin tästä selviää ajatus. 8-bittisellä puskurilla ja noilla perspektiiviarvoilla kaikki 20:tä syvemmällä olevat kappaleet menevät jo päällekkäin. 16-bittiselläkin puskurilla näyttäisi tulevan arvoja tuossa kohti niin harvakseltaan, että kappaleet voivat piirtyä vähän niin ja näin. Zn-arvon nostaminen vaikkapa 0.5:een näyttäisi suunnilleen viisinkertaistavan tarkkuuden tuossa 20:n kohdalla. Nykyään toki 24-bittisetkin syvyyspuskurit ovat yleisiä, ja niillä ongelma on taas vain yhden kahdessadasviideskymmeneskuudesosan entisestä, mutta ei ole kauan siitäkään, kun 16-bittinen puskuri piti erikseen napsauttaa asetuksista käyttöön.
No, itse varmasti huomaat, jos säätöön tulee tarvetta. Nytpä ainakin tiedät, mistä on kyse, jos tulee vastaan tapauksia, jossa kaukana olevista kappaleista näkyy vääriä asioita toisten läpi. Voi olla, ettei tuota edes tule vastaan - ennen kuin joku kokeilee vanhemmalla näytönohjaimella, joka tukee vain 8- tai 16-bittistä puskuria. ;)
Sellainen vielä, että OpenGL:n kanssa SDL_SetVideoModen palautusarvo on jokseenkin turha ottaa talteen. :)
Aihe on jo aika vanha, joten et voi enää vastata siihen.