Miten OpenGllän saisi toimimaan kunnolla Code::Blocksissa. Latasin paketin jossa oli tarvittavat tiedostot(luultavasti) ja laitoin ne mielestäni oikeisiin paikkoihin(lib-kansion tiedostot kääntäjän lib-kansioon ja include-kansion tiedostot kääntäjän include-kansioon ja dll-tiedostot projektin kansioon). Sitten menin Markus Ilmolan OpenGL-sivuille, mutta yksikään esimerkeistä ei toiminut. Esimerkiksi seuraava koodi aiheuttaa virheet:
#include <windows.h> #include <gl\gl.h> #include <gl\glu.h> #include <math.h> //#include <gl\glext.h> // Ei tarvita tässä ohjelmassa // Määrittele laitekonteksti globaaliksi sitä nimittäin tarvitaan myös pääfunktiossa. HDC hdcs; // Valon sijainti float lightPos[4]={ 0, 5, 0, 1 }; // Viestinkäsittelijä LRESULT CALLBACK WindowProc(HWND hwnds, UINT uMsg, WPARAM wParams, LPARAM lParams){ switch (uMsg) { // Koska piirrämme ikkunan sisällön pääsilmukassa jatkuvasti uudelleen // reakoimme WM_PAINT-viestiin vain tyhjentämällä ikkunan mustaksi. case WM_PAINT: { PAINTSTRUCT p; BeginPaint(hwnds, &p); glClear(GL_COLOR_BUFFER_BIT); SwapBuffers(hdcs); EndPaint(hwnds, &p); return 0; } // Ikkuna yritetään sulkea kutsu PostQuitMessage()-funktiota. case WM_CLOSE: { PostQuitMessage(0); return 0; } // Käsittele myös WM_SIZE se lähetetään ikkunalle aina kun sen kokoa muutetaan. // Tämä on oiva tilaisuus muuttaa viewport // oikean kokoiseksi peittämään koko ikkuna. case WM_SIZE: { // Ikkunan uusi koko saadaan lParam parametrista LOWORD ja HIWORD makroilla. glViewport(0, 0, LOWORD(lParams), HIWORD(lParams)); return 0; } } // Viestiä ei käsitelty kutsu DefWindowProc()-funktiota. return DefWindowProc(hwnds, uMsg, wParams, lParams); } int luoIkkuna(unsigned int leveys, unsigned int korkeus, char *otsikko){ // Rekisteröi ikkunaluokka WNDCLASS wc; memset(&wc, 0, sizeof(WNDCLASS)); wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wc.hCursor= LoadCursor(NULL, IDC_ARROW); wc.lpfnWndProc = (WNDPROC) WindowProc; wc.hInstance = GetModuleHandle(NULL); wc.lpszClassName = "OpenGLtutoriaali"; if (!RegisterClass(&wc)) return 0; // Luo ikkuna RECT r; r.left=GetSystemMetrics(SM_CXSCREEN)/2-leveys/2; r.top=GetSystemMetrics(SM_CYSCREEN)/2-korkeus/2; r.right=r.left+leveys; r.bottom=r.top+korkeus; AdjustWindowRectEx(&r, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW); HWND hwnds; hwnds=CreateWindowEx(WS_EX_APPWINDOW, "OpenGLtutoriaali", otsikko, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW, r.left, r.top, r.right-r.left, r.bottom-r.top, NULL, NULL, GetModuleHandle(NULL), NULL); // Luo laitekonteksti hdcs=GetDC(hwnds); if (!hdcs) return 0; // Valitse pikseliformaatti PIXELFORMATDESCRIPTOR pfds; memset(&pfds, 0, sizeof(PIXELFORMATDESCRIPTOR)); pfds.nSize=sizeof(PIXELFORMATDESCRIPTOR); pfds.nVersion=1; pfds.dwFlags=PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER; pfds.iPixelType=PFD_TYPE_RGBA; pfds.cRedBits=16; pfds.cGreenBits=16; pfds.cBlueBits=16; pfds.cAlphaBits=16; pfds.cStencilBits=16; pfds.cDepthBits=32; pfds.iLayerType=PFD_MAIN_PLANE; int pixelFormat; pixelFormat = ChoosePixelFormat(hdcs, &pfds); if (!pixelFormat) return 0; if (!SetPixelFormat(hdcs, pixelFormat, &pfds)) return 0; // Luo renderöintikonteksti HGLRC hrc; hrc=wglCreateContext(hdcs); if (!hrc) return 0; if (!wglMakeCurrent(hdcs, hrc)) return 0; // Tuo ikkuna näkyviin ShowWindow(hwnds, SW_SHOW); SetForegroundWindow(hwnds); SetFocus(hwnds); // Palauta onnistuminen return 1; } // Laskee kahden vektorin pistetulon float pistetulo(float v1[3], float v2[3]){ return v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2]; } // Taso piirretään käyttäen useita pieniä nelikulmioita // paremman valaistuksen saavuttamiseksi void piirraTaso(void){ int x, z; glBegin(GL_QUADS); glNormal3f(0,1,0); for (z=0; z<22; z+=2){ for (x=0; x<22; x+=2){ glVertex3f(-10+x, 0, -10+z); glVertex3f(-10+x, 0, -10+z+2); glVertex3f(-10+x+2, 0, -10+z+2); glVertex3f(-10+x+2, 0, -10+z); } } glEnd(); } // Piirtää kuution tai sen katvetilan, jos katvetila-parametri on TRUE void piirraKuutio(BOOL katvetila){ // Data piirrettävää kuutiota varten static float vertex[8][3]={{-1,0,-1},{1,0,-1},{-1,2,-1},{1,2,-1},{-1,0,1}, {1,0, 1},{-1,2, 1},{1,2, 1}}; static int index[6][4]={ {0,2,3,1}, {4,5,7,6}, {5,1,3,7},{4,6,2,0}, {7,3,2,6}, {4,0,1,5} }; // Tahojen normaalit static float normal[6][3]={{0,0,-1},{0,0,1},{1,0,0},{-1,0,0},{0,1,0},{0,-1,0}}; // Katvetilan muodostusta varten jokaisen tahon on tiedettävä naapurinsa. static int naapuri[6][4]={{3,4,2,5},{5,2,4,3},{5,0,4,1},{1,4,0,5},{2,0,3,1},{3,0,2,1}}; // Jokaiselle verteksille valoa kohti osoittava vektori. static float L[8][3]; if (!katvetila){ // Piirrä kuutio glBegin(GL_QUADS); int i, j; for (i=0; i<6; i++){ glNormal3f(normal[i][0], normal[i][1], normal[i][2]); for (j=0; j<4; j++){ glVertex3f(vertex[ index[i][j] ][0], vertex[ index[i][j] ][1], vertex[ index[i][j] ][2]); } } glEnd(); } else{ int i,j; // Laske valoa kohti osoittavat vektorit. for (i=0; i<8; i++){ L[i][0]=lightPos[0]-vertex[i][0]; L[i][1]=lightPos[1]-vertex[i][1]; L[i][2]=lightPos[2]-vertex[i][2]; } // Piirrä katvetila. // Tässä tulee sairaan paljon indeksointia, joka olisi voitu välttää // jonkinlaisen verteksi-structuren ja osoittimien käytöllä. glBegin(GL_QUADS); // Jokaiselle taholle for (i=0; i<6; i++){ // Jos tämä taho osoittaa kohti valoa if (pistetulo( normal[i], L[ index[i][0] ] )>=0){ // Jokaiselle vierustaholle for (j=0; j<4; j++){ // Jos tämä vierustaho EI osoita kohti valoa if (pistetulo(normal[ naapuri[i][j] ], L[ index[ naapuri[i][j] ][0] ])<0){ // Tahojen välinen särmä kuuluu silhuettiin // venytä se nelikulmioksi poispäin valosta. glVertex3f(vertex[ index[i][j] ][0], vertex[ index[i][j] ][1], vertex[ index[i][j] ][2]); glVertex3f(vertex[ index[i][(j+1)%4] ][0], vertex[ index[i][(j+1)%4] ][1], vertex[ index[i][(j+1)%4] ][2]); glVertex3f(vertex[ index[i][(j+1)%4] ][0]-100*L[ index[i][(j+1)%4] ][0], vertex[ index[i][(j+1)%4] ][1]-100*L[ index[i][(j+1)%4] ][1], vertex[ index[i][(j+1)%4] ][2]-100*L[ index[i][(j+1)%4] ][2]); glVertex3f(vertex[ index[i][j] ][0]-100*L[ index[i][j] ][0], vertex[ index[i][j] ][1]-100*L[ index[i][j] ][1], vertex[ index[i][j] ][2]-100*L[ index[i][j] ][2]); } } } } glEnd(); } } // Pääfunktio int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){ float angle=0; // Luo ikkuna if (!luoIkkuna(800, 600, "OpenGL:n perusteet - Osa 4: Valot ja varjot")) return 0; // Määrittele viewport koko ikkunan kokoiseksi glViewport(0, 0, 800, 600); // Koska koordinaatisto on itseasiassa matriisi täytyy meidän ottaa // projektiomatriisi käsiteltäväksi ennen gluPerspective-kutsua. glMatrixMode(GL_PROJECTION); gluPerspective(60, 800.0/600.0, 1, 100); // Kaikki matriisia muuttavat käskyt vaikuttavat tämän jälkeen modelview-matriisiin glMatrixMode(GL_MODELVIEW); // Laita näkymättömien pintojen poisto ja sysyyspuskurialgoritmi päälle. glEnable(GL_CULL_FACE); // Valitse syvyystestausfunktio "<=" oletuksena olevan "<" tilalle. glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); // Aseta valo nro. 0 päälle float Cl[4]={0.8,0.8,0.8,1}; float A[4]={0.2,0.2,0.2,1}; float Cd[4]={1,1,1,1}; glLightfv(GL_LIGHT0, GL_DIFFUSE, Cl); // Väri glLightfv(GL_LIGHT0, GL_AMBIENT, A); // Ympätisrövalon määrä glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Cd); // Pinnan väri glEnable(GL_LIGHT0); // OpenGL lisää valaistukseen vielä yhden valonlähteistä // riippumattoman ympäristövalon, josta haluamme päästä eroon. float nolla[4]={0,0,0,1}; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, nolla); // Viestinkäsittelysilmukka MSG msg; while(1){ if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){ if (msg.message==WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } else{ // Tyhjennä väripuskuri, syvyyspuskuri ja sapluunapuskuri glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // Aseta modelview-matriisi glLoadIdentity(); // "Resetoi" matriisi yksikkömatriisiksi glTranslatef(0, -3, -10); // Siirrä hieman kauemmaksi kamerasta glRotatef(angle, 0, 1, 0); // Pyöritä hieman Y-akselin ympäri // Kasvata pyörityskulmaa hieman angle+=0.05; // Siirrä valoa lightPos[0]=5*sin(angle*-0.2); lightPos[1]=5+sin(angle*0.5); lightPos[2]=5*cos(angle*-0.2); glLightfv(GL_LIGHT0, GL_POSITION, lightPos); // Ensimmäinen vaihe. // täytetään syvyyspuskuri ja piirretään kuva käyttäen pelkkää ympäristövaloa glDisable(GL_LIGHTING); glDisable(GL_STENCIL_TEST); glColor3f(A[0], A[1], A[2]); piirraTaso(); piirraKuutio(FALSE); // Toinen vaihe // Piirrä katvetila sapluunapuskuriin // Jos haluat päästä eroon varjoista kommentoi tämä toinen vaihe pois glDisable(GL_CULL_FACE); // Katvetilasta pitää piirtää kaikki osat glEnable(GL_STENCIL_TEST); // Sapluunapuskuri päälle glColorMask(0, 0, 0, 0); // Emme halua päivittää väripuskuria glDepthMask(0); // Emmekä syvyyspuskuria glStencilFunc(GL_ALWAYS, 0, 0); glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); // Käännä bitit piirtäessä piirraKuutio(TRUE); glEnable(GL_CULL_FACE); glColorMask(1, 1, 1, 1); glDepthMask(1); // Viimeinen vaihe // Piirrä lopullinen kuva kohtiin, jossa sapluunapuskurin arvo on 0 glEnable(GL_LIGHTING); glStencilFunc(GL_EQUAL, 0, ~0); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); piirraTaso(); piirraKuutio(FALSE); // Piirrä vielä valonlähde glDisable(GL_LIGHTING); glDisable(GL_STENCIL_TEST); glPointSize(5); glBegin(GL_POINTS); glColor3f(1,1,0); glVertex3f(lightPos[0], lightPos[1], lightPos[2]); glEnd(); // Vaihda puskuri näytölle. SwapBuffers(hdcs); } } return 0; }
Tiedättekö mikä on ongelma?
Thanks
Onko tarvittavat kirjastot linkattu mukaan ohjelmaan?
on.
Ei ole, näkeehän sen noista virheistäkin. Tarvitset gdi32-kirjaston.
Vielä fiksumpaa olisi heivata nuo Windows-riippuvaiset asiat kokonaan pois ja käyttää OpenGL:ää yhdessä vaikka SDL:n kanssa. Siitä on opaskin. Säästyy paljon vaivaa, ja oikein tehdyn ohjelman voi kääntää Linuxille ja Macille ilman muutoksia.
Aihe on jo aika vanha, joten et voi enää vastata siihen.