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.