Teksturer i (V)C++
KVIL
Poenget med KVIL er at man skal slippe å tenke på lasting av ulike filformat i applikasjonen sin. KVIL støtter lasting av JPG, PNG, TGA og BMP-filer fra samme grensesnitt. Under følger en rask innføring med kodeeksempler på hvordan du kan benytte deg av KVIL i din applikasjon (KVIL krever ikke MFC).
Oppsett
Første punkt er å inkludere kvil.h, slik at klassen blir tilgjenglig. I tillegg må kvil.cpp legges til prosjektet eller kompileres for egen hånd. Koden er skrevet under MSVC++, så jeg har _ingen_ anelse om hvordan GCC eller andre avarter liker den.
#include "kvil.h"
Ulike funksjoner som KVIL bruker til lasting av PNG- og JPG-bilder er tilgjenglige fra libjpeg og libpng. Disse bibliotekene skal ligge pre- kompilerte i zipfilen. Husk å linke til disse (hvis du ikke gjør dette, vil du få masse udefinerte funksjoner som ikke blir funnet). Du må i tillegg også linke mot zlibstat (libpng bruker zlib).
Lasting av filer med KVIL
For å bruke kvil, trenger du først et kvil-objekt. Definer en peker til et kvil-objekt ved å gjøre:
kvil *kv;
Opprett deretter kvil-objektet under initialiseringen av programmet ditt;
kv = new kvil();
Det kan være en god idé å gjøre dette ETTER at opengl har blitt initialisert (dvs, så etter at du har en rendering-kontekst).
Deretter er det strengt tatt bare småsaker igjen. Generer texture-id'er på vanlig måte (glGenTexture()) og bruk deretter kv->LoadGL(textureid, "filnavn.jpg"); for å laste et bilde til den omtalte textureid'en.
Eksempel:
glGenTextures(1, &texture); kv->LoadGL(texture, "filnavn.bmp");
Dette er den enkleste måten å gjøre lasting av filer på. I tillegg tilbyr KVIL et par snarveier for å gjøre lastingen av flere textures enklere:
Eksempel:
GLint textures[3]; glGenTextures(3, textures); kv->LoadGL(textures, 3, "filnavn1.tga", "filnavn2.bmp", "filnavn3.png");
Loaderene for de to filformatene som støtter alphakanaler (TGA og PNG) skal også sørge for at disse beholder alphakanalen i OpenGL. Dette kan brukes til å gjøre enkelte deler av flatene mer eller mindre gjennomsiktige etter behov.
Dersom du har bruk for å få tak i rådataene fra bildet direkte, kan dette hentes ut ved å bruke kv->Load() direkte. Jeg anbefaler deg å ta en titt på kildekoden for å se hvordan du kan gjøre dette (og hvilke muligheter du har videre). Dataene fra bildefilen bør være tilgjenglig i kv->data etter dette. Det er også gitt et par eksempler i kommentarene på toppen av kvil.cpp.
Lagring av filer med KVIL
KVIL støtter fra versjon 0.0.6 også lagring av BMP-filer. En BMP-fil kan lagres ved et kall til funksjonen "WriteBMP()". Dette forutsetter imidlertid at du har rådataene som skal skrives ut klare (i RGB-format). I samspill med OpenGL er det imidlertid to andre funksjoner som kan være mer nyttige, DumpBMP() og DumpSequenceBMP(). DumpBMP() lagrer et skjermbilde til en bmp-fil mens DumpSequenceBMP() lagrer et skjermbilde med en økende id i navnet.
Eksempel:
kv->DumpSequenceBMP("c:\\eksempel", 640, 480);
Første gang denne funksjonen blir kalt, opprettes filen 'eksempel_001.bmp' og innholdet i skjermbufferen lagres. Neste gang funksjonen kalles blir filnavnet 'eksempel_002.bmp' osv. Dette gjør at man har muligheten til å dumpe opptil 999 frames ved å bare kalle funksjonen på de tidspunktene man ønsker å dumpe skjermbildet. Dette kan så settes sammen til en hel animasjon i f.eks. VirtualDub eller med bmp2avi. Det skal i utgangspunktet ikke være noe i veien med at man dumper over 999 bilder, men filnavnene er i utgangspunktet definert til å være navn_XXX. '640' og '480' i eksemplet overfor er størrelsen på bufferet som skal dumpes. Sett denne til å være størrelsen på vinduet ditt.
For å lagre et enkelt screenshot er prosedyren veldig lik:
kv->DumpBMP("c:\\eksempel.bmp", 640, 480);
Lisensvilkårene for koden er angitt i kvil.cpp og kvil.h, men det skal stort sett være fritt fram for å bruke koden til alt du måtte føle for - og for all del, her er det bare til å legge til, fikse problemer og nyte alt etter hjertet egen lyst.
CGLImage
CGLImage er begrenset til å laste BMP eller DIB-filer og slik de er lagt ut er de begrenset til 8-bits bilder. Basisen er modifiserte utdrag fra kildekoden til to dynamiske biblioteker som er distribuert i sammenheng med Visual C++:
- Nigel Thomsens Animation Engine: Animation Technics for Win 32 Microsoft press 1995. Development Library. Books and Periodicals
- Dale Rogersons GLIB.DLL: Development Library, Technical articles OpenGL I- VII, 1995
For å nytte disse må følgende filer inkluderes i prosjektet:
- winmm.lib
- animate.h
- image.h
- dib.cpp
- dibpal.cpp
- image.cpp
- winmm.lib
i tillegg til de som allerede er inkludert i standardprogrammet std som er introdusert i modulen OpenGL og MFC. De nødvendige filene kan tas fra VC++ prosjektet textur: txtur.zip(VC++/gml) eller txtur.zip(VC++/.Net). Du kan inkludere følgende linjer i stdafx.h
// bitmap and image classes #include "animate.h" #include "image.h"
Dette gir oss tilgang til følgende tre klasser:
class CDIB : public CObject class CDIBPal : public CPalette class CGLImage
CDIB holder og manipulerer en device independant bitmap, CDIBPAL holder og manipulerer en palett, mens CGImage kan holde en struktur som fungerer som en bitmap i et format OpenGL forstår. Vi går ikke i detalj om funksjonaliteten i disse klassene.
De viktigste funksjonene som involverer imagestrukturen som vil bli brukt i demonstrasjonsprogrammet textur er demonstrert ved følgende kodebiter:
Oppsett av en tekstur:
CGLImage m_theImage; ... m_theImage.Load(< filename>,< translationmode>); ... glTexImage2D( GL_TEXTURE_2D,0,3, m_theImage.GetWidth(), m_theImage.GetHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, m_theImage.GetBitsPtr());
Å vise en bitmap
Vi kan vise fram bitmaps uten at disse skal legges på overflater som tekstur. Det vil si at vi kan legge ut bitmaps som bakgrunn eller som som enkle kulisser. Strategien er rimelig enkel og framgår i hovedsak av kodeeksempelet nedenfor. Koden viser også bruken av verktøyene for å håndtere bitmaps.
CGLImage m_theImage; ... m_theImage.Load(< filename>,< translationmode>); ... glRasterPos3f(-dx,-dy,-50.0f); glDrawPixels( m_theImage.GetWidth(), m_theImage.GetHeight(), GL_RGB, GL_UNSIGNED_BYTE, m_theImage.GetBitsPtr() );