Kirjautuminen

Haku

Tehtävät

Opasarkisto: SDL ja OpenGL yhdessä: Osa 1 - Yksinkertainen alustus ja käyttö

  1. Osa 1 - Yksinkertainen alustus ja käyttö
  2. Osa 2 - Tekstuurien ja funktioiden lataus ajon aikana

Kirjoittaja: Metabolix (2007).

Legenda kertoo, että SDL:ää (Simple DirectMedia Layer) ja OpenGL:ää on mahdollista käyttää yhdessä, jolloin syntyy monella alustalla toimivia ohjelmia, jotka käyttävät tehokasta grafiikkakirjastoa. Usein on kysytty, kuinka tämä salaperäinen poppakonsti onnistuu. Nyt on aika paljastaa tuo salaisuus. Ensin on syytä tuntea hieman SDL:n perusteita, eikä OpenGL-tuntemuskaan ole pahasta. Esimerkeissä käytetään C-kieltä, mutta koska samat funktiot ovat kuitenkin pääosassa, jokainen osannee kääntää asiat omalle ohjelmointikielelleen. Muilta osin oppaan kieli on suomi.

Perusajatus

OpenGL on vain grafiikkakirjasto, joskin erittäin hyvä sellainen. Sen sijaan SDL on poikkeuksellisen näppärä kirjasto ikkunan luomiseen ja käsittelyyn. Miksi näitä kahta ei voisi yhdistää? Ajatuksena yhdistelmässä on, että piirtäminen tapahtuu viime kädessä täysin OpenGL:llä. SDL puolestaan hoitaa ikkunan ja syötteet sekä mahdollisesti kaikkea muutakin, mutta ei grafiikkaa. Helposti tuntuu, että SDL ei tee juuri mitään, koska OpenGL:llä tehtävä piirtokoodi yleensä vie paljon enemmän tilaa kuin ne kymmenen pikkujuttua, jotka SDL hoitaa. Tosiasiassa SDL piilottaa suuren määrän vaikeasti hallittavaa koodia ja on erittäin tervetullut apu.

Kuinka kaikki toimii?

Tärkein asia on kertoa SDL:lle, että OpenGL pitää alustaa. Tämä onnistuukin vaivatta yhdellä lipulla näyttötilan alustuksessa.

SDL_SetVideoMode(LEVEYS, KORKEUS, 0, SDL_OPENGL);

SDL sisältää viisi funktiota OpenGL:n käyttöä varten. SDL_GL_SwapBuffers on kaksoispuskuroidussa piirrossa välttämätön, sillä saa taideteoksensa ilmestymään ruudulle. SDL_GL_SetAttribute tulee tarpeeseen perusasetuksia asetettaessa, ja SDL_GL_GetAttribute auttaa tarkistamaan, tukiko järjestelmä noita asetuksia. SDL_GL_GetProcAddress hakee pyydetyn GL-funktion, tätä siis tarvitaan esimerkiksi OpenGL:n laajennusten käytössä. SDL_GL_LoadLibrary antaa toisinaan tarpeellisen mahdollisuuden ladata OpenGL vasta ajon aikana, jolloin voi sen puuttuessa turvautua vaikkapa SDL:n tavallisiin piirtofunktioihin.

SDL_GL_SetAttribute

OpenGL toimii toki ilmankin sen ihmeempiä määreitä, mutta tämä ei välttämättä ole suotavaa, koska tällöin lopputulos on täysin kiinni käyttäjän koneella olevista oletusasetuksista. Merkittäviä tekijöitä ovat värisyvyys ja syvyyspuskuri, mutkikkaammissa ohjelmissa myös sapluunapuskuri (stencil buffer) ja kertymäpuskuri (accumulation buffer). Itse puskurien käyttöä ei tässä oppaassa selosteta, koska se ei varsinaisesti kuulu tämän oppaan aihepiiriin vaan on OpenGL:n asia. Lista eri määreistä on SDL:n otsikkotiedostossa SDL_video.h.

Asetukset täytyy säätää ennen SDL_SetVideoModen kutsumista. SDL_GL_SetAttribute ottaa parametreinaan muutettavan attribuutin tunnuksen ja arvon. Tunnukset on määritelty numeroidussa tyypissä SDL_GLattr, arvo on kokonaisluku. Palautusarvona on nolla, jos funktio onnistui, ja -1, jos ei. Tämä siis kertoo käytännössä, onnistuiko funktio sijoittamaan annetun arvon SDL:n sisäiseen muuttujaan. Arvon kelpoisuudesta se ei kerro mitään.

// Funktion prototyyppi on siis seuraava:
// int SDL_GL_SetAttribute(SDL_GLattr attr, int value);

// Väreille tietty bittimäärä
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, VARIN_BITIT);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, VARIN_BITIT);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, VARIN_BITIT);
// Syvyyspuskurille jotain...
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, SYVYYS);
// Kaksoispuskurointi käyttöön
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

SDL_GL_GetAttribute

Koska äsken esitellyn SDL_GL_SetAttribute-funktion palautusarvo kertoo vain, onnistuiko se sijoittamaan annetun arvon jonnekin, SDL_GL_GetAttribute voi olla hyvinkin hyödyllinen. Sillä voi tarkistaa, millaiset asetukset ovatkaan käytössä. SDL_SetVideoModen jälkeen se palauttaa asetukset sen mukaan, mihin järjestelmä on päätynyt. Parametriksi se ottaa attribuutin tunnuksen ja osoittimen muuttujaan, johon arvo palautetaan. Palautusarvo toimii samoin kuin edelliselläkin funktiolla: palautetaan nolla, jos funktio onnistui, ja -1, jos ei.

SDL_SetVideoMode(LEVEYS, KORKEUS, 0, SDL_OPENGL);

int syvyys, kaksoispuskurointi;
SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &syvyys);
SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &kaksoispuskurointi);

if (syvyys != haluttu_syvyys) {
    printf("Syvyys ei ole oikea, haluttiin %d saatiinkin %d\n", haluttu_syvyys, syvyys);
}
if (!kaksoispuskurointi) {
    printf("Ei ole kaksoispuskuria! Qu'est-ce que c'est que cela? O_o\n");
}

SDL_GL_SwapBuffers

Kun kaksoispuskurointi on käytössä, kuten tapaa yleensä olla, piirretyt asiat eivät siirry ruudulle omin voimin. SDL:n kanssa käytettiin funktiota SDL_Flip, mutta kun OpenGL on käytössä, korvikkeena onkin SDL_GL_SwapBuffers. Toiminta on aivan sama, mutta mitään parametria ei tarvita.

SDL_GL_SwapBuffers();

Esimerkkiohjelma palasina

Esimerkkiohjelma ei ole järin ihmeellinen. Siinä ruudulle piirretään kolmio, jonka kulmien väriä voi muuttaa. Kulmat on numeroitu yhdestä kolmeen, kunkin kulman väristä voi vapaasti muuttaa jokaista kolmea komponenttia eli punaista (R), vihreää (G) ja sinistä (B). Muuttaminen tapahtuu painamalla samanaikaisesti kulman numeroa, värin kirjainta ja nuolta ylös tai alas. Esimerkkiohjelman voi ladata myös kokonaisena.

SDL:n ja OpenGL:n käyttöön tarvitsee luonnollisesti niiden omat otsikot. SDL on helpottanut tätäkin vielä vähän: siinä on mukana OpenGL-otsikko, joka hoitaa oikeat otsikot mukaan. Esimerkkiohjelma käyttää myös standardikirjastoa.

#include <stdlib.h>
#include <stdio.h>

// Näihin on ehkä lisättävä SDL/-etuliite, jos include-polkuja ei ole säädetty.
#include <SDL.h>
#include <SDL_opengl.h>

Jos ohjelmaan ei tule asetustiedostoa tai muuta vastaavaa, asetukset on syytä määritellä vakioiksi, jottei niiden kanssa satu vahinkoja.

// Asetukset
const int VARIN_BITIT = 8; // 8 bittiä jokaiselle värin komponentille
const int SYVYYS = 16;     // 16-bittinen syvyyspuskuri (turha tällä kertaa)
const int LEVEYS = 320;    // Ikkunan mittoja voi huoletta muuttaa
const int KORKEUS = 240;   // Tällä kertaa kuitenkin pieni ikkuna riittää
const int IKKUNALIPPU = 0; // tai SDL_FULLSCREEN

// Tarkistusta varten, jotta saadaan selville, mitä asetuksista tulikaan.
int syvyys, kaksoispuskurointi;

Funktioita ei kannata kaihtaa. Selvä funktiorakenne auttaa ohjelmaa huomattavasti. Tässä ovat esimerkkiohjelman funktioiden esittelyt sekä jokunen tarpeellinen makro.

// Funktiot
int hoida_viestit(void);
void laske_kulunut_aika(void);
void alusta(void);
void toimi(void);
void piirra(void);
void lopetusfunktio(void);

// Jos a ei osu välille [min, max], palautetaan min tai max
// ehto ? palautus_jos_tosi : palautus_jos_epatosi
#define valille(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a)))

Ohjelmassa on vain muutama muuttuja. Kulunut aika täytyy tietenkin säilyttää olla tiedossa, samaten ohjelman virhetilanne. Toiminnallisuutta varten ohjelmassa on taulu tietueita, joihin on tallennettu kolmion kulmien värit.

// Ohjelman kierrokseen kulunut aika (millisekunteina)
Uint32 kulunut_aika;

// Virhemuuttuja, jotta lopetusfunktio hoitaa oikeat asiat
int virhe = 0;

// Kolmion kulmien värit
struct rgb_t {
	GLfloat r, g, b;
};
struct rgb_t kulman_varit[3] = {
	{1.0f, 1.0f, 0.0f},
	{0.0f, 1.0f, 1.0f},
	{1.0f, 0.0f, 1.0f},
};

Animaatioiden ja muun vastaavan on yleensä suotavaa toimia eri tietokoneilla yhtä nopeasti. Sitä varten otetaan aikaa ja tehdään muutoksia kuluneen ajan mukaan. Joskus voi olla käytännöllistä pitää laskuria esimerkiksi animaation alusta laskettuna, mutta tällä kertaa on tarpeen tietää vain, kauanko on kulunut edellisestä päivityksestä. SDL tarjoaa riittävät välineet ajanottoon.

void laske_kulunut_aika(void)
{
	// SDL osaa näppärästi ottaa aikaa
	static Uint32 vanha_aika, uusi_aika;
	vanha_aika = uusi_aika;

	// Pitää olla eri aika kuin viimeksi
	while (vanha_aika == uusi_aika) {
		uusi_aika = SDL_GetTicks();
	}

	// Kauanko on kulunut viime kutsusta?
	kulunut_aika = uusi_aika - vanha_aika;
}

SDL:n merkittävimpiä tehtäviä on syötteiden luku ja muiden viestien hallinta. Sitä varten on hyvä tehdä erillinen funktio, joka ilmoittaa palautusarvollaan, onko kaikki kunnossa. Jos funktio palauttaa muuta kuin nollan, ohjelma lopetetaan.

int hoida_viestit(void)
{
	// SDL hoitaa viestit - aivan kuten yleensäkin
	SDL_Event event;

	// Tutkitaan kaikki tapahtumat jonosta
	while (SDL_PollEvent(&event)) {
		// Rastin painamisesta aiheutuu yleensä tällainen
		if (event.type == SDL_QUIT) {
			return -1;
		}
		// Esc sulkee myös
		if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE) {
			return -1;
		}
	}

	// Nolla on onnistuminen.
	return 0;
}

Ohjelman alustus on hyvä keskittää mahdollisimman selkeästi osa-alueittain. Tällä kertaa alustettavana ei ole kuin graafinen puoli, joten yksi funktio riittää oivallisesti. Ensin alustetaan SDL, sitten asetetaan OpenGL:lle tarvittavat attribuutit ja luodaan ikkuna. Seuraavaksi tarkistetaan, millainen ikkuna saatiin, ja tarvittaessa säädetään OpenGL:n sisäisiä asetuksia.

void alusta(void)
{
	// Ensin pitää hoitaa SDL aluilleen
	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) {
		printf("Virhe: SDL_Init: %s\n", SDL_GetError());
		exit(virhe = 1);
	}

	// Sitten asetetaan OpenGL:lle parametrit
	// Väreille tietty bittimäärä
	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, VARIN_BITIT);
	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, VARIN_BITIT);
	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, VARIN_BITIT);
	// Syvyyspuskurille jotain...
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, SYVYYS);
	// Kaksoispuskurointi käyttöön
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

	// Käynnistetään video. Pintaa ei tarvitse ottaa muistiin.
	if (SDL_SetVideoMode(LEVEYS, KORKEUS, 0, SDL_OPENGL | IKKUNALIPPU) == NULL) {
		printf("Virhe: SDL_SetVideoMode: %s\n", SDL_GetError());
		exit(virhe = 2);
	}

	// Katsellaan, millaiset asetukset saatiin aikaan
	SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &syvyys);
	SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &kaksoispuskurointi);
	if (syvyys > SYVYYS) {
		printf("Syvyys on toivottua suurempi \\o/. Pyydettiin %d, saatiinkin %d...\n", SYVYYS, syvyys);
	} else if (syvyys < SYVYYS) {
		printf("Syvyys on toivottua pienempi :(. Haluttiin %d, saatiinkin %d...\n", SYVYYS, syvyys);
	}
	if (!kaksoispuskurointi) {
		printf("Ei ole kaksoispuskuria! Qu'est-ce que c'est que cela? O_o\n");
		printf("Nyt voi sattua hassuja...\n");
	}

	// Tässä voisi säätää OpenGL:n asetuksia kuntoon aivan normaalisti,
	// siis glEnablella ja muilla OpenGL:n säätöfunktioilla.
	// Asetetaan taustaväriksi tylsä harmaa
	glClearColor(0.5, 0.5, 0.5, 1.0);

	// Rullataan vielä viestit läpi ja nollataan aikalaskuri
	if (hoida_viestit() != 0) {
		exit(virhe = 0);
	}
	laske_kulunut_aika();
}

Ohjelman varsinaiset omat laskelmat voi hyvin keskittää tiettyyn paikkaan. Jos ohjelman pitää toimia yhtä nopeasti kaikilla, toiminnan voi nyt suhteuttaa kuluneeseen aikaan.

void toimi(void)
{
	int i;
	GLfloat muutos;
	// SDL:ää voi käyttää syötteissä
	Uint8 *napit = SDL_GetKeyState(0);

	// Muutos on 1, jos painetaan vain plussaa, -1, jos vain miinusta, ja 0, jos kumpaakin. Tämä kerrotaan sitten ajalla ja jaetaan sopivalla luvulla, jotta muutosnopeudesta tulee hyvä.
	muutos = napit[SDLK_UP] - (GLfloat)napit[SDLK_DOWN];
	muutos = muutos * kulunut_aika / 1000.0f;

	for (i = 0; i < 3; ++i) {
		// Jos painetaan oikeaa numeroa (tämä + 1)
		if (napit[SDLK_1 + i]) {
			// Kukin osaväri erikseen
			if (napit[SDLK_r]) kulman_varit[i].r += muutos;
			if (napit[SDLK_g]) kulman_varit[i].g += muutos;
			if (napit[SDLK_b]) kulman_varit[i].b += muutos;

			// Varmistetaan, ettei mene sallitun lukualueen yli
			kulman_varit[i].r = valille(kulman_varit[i].r, 0.0f, 1.0f);
			kulman_varit[i].g = valille(kulman_varit[i].g, 0.0f, 1.0f);
			kulman_varit[i].b = valille(kulman_varit[i].b, 0.0f, 1.0f);
		}
	}
}

Piirtäminen on järkevää tehdä selkeästi yhdessä paikassa – tai ainakin aloittaa selkeästi yhdestä paikasta. Toki jos piirrettävää on paljon, on selkeämpi siirtyä piirtofunktiosta tilanteen mukaan pienempää kokonaisuutta käsittelevään funktioon.

void piirra(void)
{
	// OpenGL:llä voi piirtää aivan normaaliin tapaan
	glClear(GL_COLOR_BUFFER_BIT);

	// Kolmio; kulmien värit annetaan näppärästi osoittimena
	glBegin(GL_TRIANGLES);
	glColor3fv((GLfloat*)&kulman_varit[0]); glVertex2f(-0.9f, -0.9f);
	glColor3fv((GLfloat*)&kulman_varit[1]); glVertex2f( 0.9f, -0.9f);
	glColor3fv((GLfloat*)&kulman_varit[2]); glVertex2f( 0.0f,  0.9f);
	glEnd();

	// Piirrokset esille
	if (kaksoispuskurointi) {
		SDL_GL_SwapBuffers();
	}
}

Lopuksi täytyy luonnollisesti sulkea SDL ja mahdollisesti tehdä muitakin sulkutoimenpiteitä.

void lopetusfunktio(void)
{
	// Nerokasta käyttöä tällekin rakenteelle...
	switch (virhe) {
		// case 0 - normaali lopetus. Kaikki sulkemistoimenpiteet on tehtävä.
		case 0:

		// case 2 - ohjelma loppui kesken ja virhekoodi on 2.
		case 2:
			SDL_Quit();

		// case 1 - SDL:ää ei saatu alustettua. Alustamattomia osia ei tietenkään tarvitse sulkeakaan.
		case 1:
			break;

		// Muu virhekoodi - tämähän voi olla vaikka bugi, on unohtunut lisätä tänne listaan jokin virhekoodi.
		default:
			printf("Ja virhekoodikin pieleen... %d xD\n", virhe);
	}
}

Pääfunktiosta tulee tällä tavalla lyhyt ja ytimekäs.

// SDL kaipaa toisinaan mainille parametreja, vaikkei niitä käytettäisi
int main(int argc, char **argv)
{
	// Lopetusfunktio suoritetaan automaattisesti lopuksi.
	atexit(lopetusfunktio);
	alusta();

	while (hoida_viestit() == 0) {
		laske_kulunut_aika();
		toimi();
		piirra();
	}
	return virhe = 0;
}

Ohjelman linkittämiseen tarvitaan SDL ja OpenGL. SDL:n linkkeriparametrit ovat normaalisti GCC:llä -lSDL -lSDLmain ja OpenGL:lle kelvannee Linuxissa -lGL ja Windowsissa -lopengl32. VC++:lla vastaavat kirjastotiedostot ovat SDL.lib, SDLmain.lib ja opengl32.lib. Esimerkkiohjelman voi tosiaan ladata myös kokonaisena. Toiminnassa tämä taideteos voisi näyttää vaikkapa tältä:

Kuva ohjelmasta

Oppaan seuraavassa osassa käytetään SDL:ää tekstuurien lataamiseen sekä ladataan OpenGL dynaamisesti.

Lauri Kenttä, 4.1.2007


Kommentit

tejeez [05.01.2007 23:15:57]

#

eka 8D

BlueByte [06.01.2007 13:06:09]

#

toka :--DDD

tejeez [06.01.2007 19:57:21]

#

ihkudaa opas

moptim [07.01.2007 09:10:24]

#

neljäs xo

verho88 [10.01.2007 23:40:29]

#

Opas on hyvä ja seuraavaa osaa odotellaan.. :P

thefox [13.01.2007 10:50:55]

#

C-kielessä tyhjä parametrilista (esim. int hoida_viestit();) tarkoittaa, että funktion parametreja ei ole määritelty (sille voi syöttää niin monta parametria kuin huvittaa). Oikeaoppinen tapa esitellä funktio, joka ei ota yhtään parametria, on käyttää avainsanaa void, esimerkiksi int hoida_viestit(void);.

Pilkunviilausta tämäkin, mutta oppaan alussa olisi ehkä voinut mainita mitä ohjelmointikieltä esimerkeissä käytetään :)

(EDIT: nämä näemmä korjattu ;-)

DrDeath [01.02.2007 12:04:26]

#

ehehehhee seitsemäs... Tällästä opasta oonki oottanu...

moptim [04.02.2007 08:01:38]

#

> Metabolix

Tuli se opas sittenkin (lainaus on tästä threadista):

Metabolix toiseen threadiin kirjoitti:

Tuosta SDL + OpenGL -yhdistelmästä voisin laittaa vaikka koodivinkin, ei siitä oppaaksi asti taida riittää, kun oikeastaan kyseessä on vain selvä rajaus, mitä SDL:stä käytetään, yksi oikea lippu näyttötilaa asetettaessa ja pari ylimääräistä säätöfunktiota alussa.

Metabolix [04.02.2007 19:50:50]

#

KingOfTheWorld kirjoitti:

Tuli se opas sittenkin

Niinpä taisi tullakin. Pääasia on kuitenkin vain tuon alusta-funktion mittainen ja olisi mahtunut hyvin pelkkään koodivinkkiinkin.

jones7 [18.02.2007 01:54:13]

#

Mahtava opas! Mitä nuo SDL ja OpenGL on? En aivan ymmärtänyt sitä opasta lukiessani.

moptim [19.02.2007 17:16:28]

#

SDL luo hieanon ackunan, joka toimii vaikka millä alustoilla. SDL hoitelee myös syötteenluvun ja mahd. metelin ym. shittiä (kaiken, mikä ei liity chrafiickaan). OpenGL on hieano kraaffikakirjasto.

Ja suomeksi sama:

SDL luo ikkunan, joka toimii vaikka millä alustalla. Se lukee myös syötteitä ja tekee kaiken, mikä ei liity grafiikkaan. OpenGL luo grafiikan (2D / 3D)

jones7 [19.02.2007 18:59:13]

#

OK! Kiitti Kingi! Oot ihan Ringi lol xD

moptim [25.02.2007 08:17:22]

#

*heh*

osku91 [27.02.2007 14:03:54]

#

Mistä johtuu että kun dev-c++:alla aloitan uuden projektin ja kopioin esimerkki ohjelman ja laitan linkkeriin nuo asetukset ja laitan ne SDL/ jutut includeihin alussa ja sitten yritän kääntää ohjalman, niin siinnä vain vilahtaa se kääntämis ikkuna ja sitten se menee pois ekä ohjelma käynnisty eikä näy mitään virhe ilmoitusta?

moptim [24.03.2007 18:32:12]

#

Hmm. Suosittelen command promptiin kajoamista. gcc auttanee sinua. Muista nämä parametrit: "-lSDL -lSDLmain -lopengl32" sinne lophuun.

EDIT: Ubsis, muisti pätki. Kyllä se on "-lopengl32". :/

Metabolix [24.03.2007 21:46:24]

#

Kirjoita projektin asetuksissa olevaan linkkerin parametrilistaan oppaan lopussa mainitut parametrit.

InvalidCo [01.05.2007 13:58:19]

#

Hyvä opas!
Voisiko ensi oppaassa sitten myös käsitellä PNG-kuvatiedostojen lataamiset? (Mikäli siihen sisältyy muutakin kuin SDL_LoadBMP-funktion IMG_Load-funktioon vaihtaminen)

Metabolix [01.05.2007 21:45:49]

#

Eipä siihen mitään kummempaa tarvita. SDL-pinnan siirtämiseksi OpenGL-tekstuuriksi on myös koodivinkki, siitä voi ottaa mallia (tai vaikka kopioida, ei se niin ihmeellinen ole).

kayttaja-4976 [02.05.2007 17:02:32]

#

PC-Master: Tutustu SDL_Imageen.

Mega-Ohjelmoija [29.08.2007 17:37:08]

#

Ihan hyvä opas.
Odotan innolla jatko-osaa.

vehkis91 [17.06.2008 14:41:30]

#

Täähän on tarpeellinen opas, toivottavasti tulee jatkoa...

tkok [24.06.2008 12:41:49]

#

hyvä opas, milloin jatkoa?

punppis [24.06.2008 13:29:13]

#

Mistähän nuo tarvittavat (OpenGL) tiedostot saa ladattua Visual C++:lle. Tuolta sivuilta kattelin niin kaikkea muuta tuntuu pystyvän lataamaan, mutta ei itse OpenGL-tiedostoja.

Metabolix [26.06.2008 17:28:16]

#

OpenGL tulee useimpien valtakääntäjien mukana, sitä ei luultavasti tarvitse erikseen ladata.

punppis [27.06.2008 01:33:14]

#

Itsellä heittää tuo esimerkkikoodi ainakin virheilmoitusta VC++ Express 2008:ssa.

error LNK2019: unresolved external symbol __imp__glEnd@0 referenced in function "void __cdecl piirra(void)" (?piirra@@YAXXZ)

Mistähän tuo voisi johtua? Noita erroreita tulee muutama, ja jokaisessa valitetaan tuosta unresolved external symbolista.

Googlettelin, ja tuo virheilmoitus kuulemma johtuu ettei ole linkattu opengl-tiedostoja. "You need to link against the OpenGL import library (something.lib). Add the name of this file to your linker settings."

En löydä mistään opengl.lib tiedostoja.

Metabolix [27.06.2008 11:14:36]

#

http://www.mrmoen.com/2008/03/30/opengl-with-visual-c-express-edition/:

OpenGL comes with implementations on most operating systems and many compilers, including Visual C++ 2008 Express Edition.
— —
Type "opengl32.lib glu32.lib" in Additional Dependencies and click OK.

Lisäsin vileä VC++:sta maininnan oppaaseen. Yleensä lippu -ljotain tarkoittaa VC++:ssa kirjastoa jotain.lib, joten -lopengl32 tarkoittaa kirjastoa opengl32.lib. Esimerkkiohjelma ei tarvitse GLUta.

Grayling [30.06.2010 13:58:41]

#

Täällähän on paljon mielenkintoista juttua. Hyvä opas.

Itsellä meni kauan aikaa OpenGL:n toimintaan saamisessa. (VC++ 2008 Express Edition ja Vista)
Error: Access violation 0xC0000005

Ongelma ratkesi seuraavasti: project properties -> linker -> advanced -> data execution prevention vaihda tähän /NXCOMPAT:NO

Kirjoita kommentti

Huomio! Kommentoi tässä ainoastaan tämän oppaan hyviä ja huonoja puolia. Älä kirjoita muita kysymyksiä tähän. Jos koodisi ei toimi tai tarvitset muuten vain apua ohjelmoinnissa, lähetä viesti keskusteluun.

Muista lukea kirjoitusohjeet.
Tietoa sivustosta