Hlavne menu We are sorry, but magazine AMMO is suspended. Here is just read-only access to the articles archive. Some features are removed because they were outdated, pointless in read-only (voting and pools), or it was missused by spammers (comments) etc. Now the webpages aren't maintained so when something will get broken most probably it won't be fixed at all. If you liked our magazine then please make donation with paypal so we can pay for traffic on this server.

TOP Výuka
01 Maľované krížovky 103 bodov
02 OpenGL, lákadlo 38 bodov
03 MySQL (+ použitie Visual C++ a PHP) 28 bodov
04 OpenGL, časť 1 21 bodov
05 Huffmanove kódovanie 19 bodov
06 Pascal, časť 1 18 bodov
07 Ako tlačiť s HP 16 bodov
08 Základy HTML časť 2 16 bodov
09 Základy HTML časť 3 13 bodov
10 Hry pre nenáročných + zdrojáky 10 bodov
11 OpenGL, úvod 8 bodov
12 Faktúrka v4.0 + zdrojáky v MS Visual C++ 6.0 7 bodov
13 OpenGL – Intermezzo 1 7 bodov
14 OpenGL povinná literatúra 6 bodov
15 Základy HTML časť 1 6 bodov
Najnovsie clanky
Kvalitné služby podľa skúseností iných - TopSlužby.sk
LOTR - Dve veže - Parodia - Scénka 2. časť
Neverwinter nights
Children Of Bodom-Hatebreeder
Kult Duny - 6. časť (Bonus)
Kult Duny - 5. časť (Filmy, Hry)
Dobré ráno. (morc certa, hora incerta...)
Kult Duny - 4. časť (Knihy 2/2)
Stretnutie Spoločenstva Tolkiena
GRAVE DIGGER – Knights Of The Cross
Kult Duny - 3. časť (Knihy 1/2)
Kult Duny - 2. časť (Pojmy)
Kult Duny - 1. časť (Úvod)
LOTR - Dve veže - Parodia - Scénka
Jackass
Vsetky clanky
Airsoft - Specnaz [4 clanky]
Básne [6 clankov]
Fantázia [4 clanky]
Filmy a DVD [51 clankov]
Hardware [10 clankov]
Hry [170 clankov]
Hry, návody [6 clankov]
Hudba [8 clankov]
Internet [7 clankov]
Knihy [6 clankov]
O AMME [4 clanky]
Pandemonium [10 clankov]
Poviedky [14 clankov]
Programy [18 clankov]
Rôzne [8 clankov]
Technické [3 clanky]
Úvahy [8 clankov]
Výuka [50 clankov]
Ako tlačiť s HP
Algoritmy v grafoch
Fake2
Faktúrka
Faktúrka v4.0 + zdrojáky v MS Visual C++ 6.0
Fract
HLSaver
Hry pre nenáročných + zdrojáky
Huffmanove kódovanie
IPicture2 & aggresiveoptimize.h
Maľované krížovky
MySQL (+ použitie Visual C++ a PHP)
OpenGL - GLWnd
OpenGL AMMO Saver
OpenGL povinná literatúra
OpenGL – Intermezzo 1
OpenGL, časť 10
OpenGL, časť 11
OpenGL, časť 12
OpenGL, časť 13
OpenGL, časť 14
OpenGL, časť 15
OpenGL, časť 16
OpenGL, časť 17
OpenGL, časť 18
OpenGL, časť 8
OpenGL, časť 9
Opengl – Cloth Simulation
RenameR
SkinMagic
WinSocket Communication via VC++
Údajové štruktúry
viac...
Zábava [5 clankov]
Zdravie [15 clankov]
Celkovy pocet clankov: 407
OpenGL, časť 6 
Výuka | Dna 22.3.2002 | Johny | 3 znamky, priemer 2.33 | 6173 videni | 1008 WAP videni

Textúrovanie a jednoduchý gem súbor s objektom.

Tak sme sa konečne dopracovali ku textúram. Vedieť ako používať textúry ma veľa výhod. Napríklad chcete aby nejaký objekt lietal okolo obrazovky. Ten objekt by mohol byť napríklad monitor od počítača. Keby ste každý polygón len nejako vyfarbili, asi by to nevyzeralo nejako extra super. A keby ste chceli napríklad, aby niečo bolo na obrazovke ? Tak to už by ste sa pomocou farieb asi hodne natrápili. Ale to by snáď nikoho nenapadlo tak komplikovane robiť. ;o) S textúrami je všetko krajšie a hlavne všetko vyzerá viac realisticky, ako len nejaké farby.
V tejto časti si ukážeme ako urobiť jednoduchý textúrovací program. Obsahom celého programu bude jedna kocka, ktorá sa bude točiť okolo všetkých svojich osí a každá jej strana bude textúrovaná.

Na začiatok programu pár nových riadkov.

#include <windows.h> // hlav. súbor windows.h
#include <stdio.h> // Standard Input/Output
#include <glgl.h> // OpenGL32 Library
#include <glglu.h> // GLu32 Library
#include <glglaux.h> // GLaux Library

HDC hDC=NULL; // GDI Device Context
HGLRC hRC=NULL; // Rendering Context
HWND hWnd=NULL; // Window Handle
HINSTANCE hInstance; // Instance aplikácie

bool keys[256]; // pole pre klávesy
bool active=TRUE;
bool fullscreen=TRUE;

GLfloat xrot; // rotácia X
GLfloat yrot; // rotácia Y
GLfloat zrot; // rotácia Z

GLuint texture[1]; // 1 textúra

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
A teraz hneď pod toto a pred ReSizeGLScene() napíšeme nasledujúcu časť. Pridáme kúsok kódu, ktorý nám načíta nejaký obrázok a spraví z neho textúru. Ak súbor s obrázkom neexistuje, tak funkcia vráti NULL. NULL je pointer, ktorý neukazuje vlastne nikam.
Ešte predtým, však musíte vedieť o obrázkoch jednu dôležitú vec. Týka sa to obrázkov, ktoré chcete použiť ako textúry. Ich šírka a výška musí byť vždy mocninou 2. A šírka a výška musí byť aspoň 64 pixelov. Pre väčšiu kompatibilitu by to nemalo byť viac ako 256 pixelov. Ale niekedy sa nedá ubrániť väčším textúram. Napríklad, keď robíte nejaký šetrič a chcete si uložiť obrazovku pozadia. Ak si to uložíte do textúry 256x256 pixelov, tak to bude jasne vidno. Nebude to také pekné, ako to, čo ste videli predtým. Ale napríklad ak máte rozlíšenie 800x600, tak sa dajú spraviť 4 textúry: 256+256+256+32 = 800 a podobne aj na výšku. Ak chcete použiť ako obrázok textúru napríklad 123x123 pixelov, tak si ju otvorte v nejakom editore obrázkov a zmeňte veľkosť na 128x128 a už to pôjde. Na tieto riadky si spomeňte vždy, keď si už budete trhať vlasy z hlavy, lebo váš program nechce vytextúrovať nejaký polygón. Toto býva jeden z častých dôvodov prečo to nejde.

Takže môžeme prejsť na funkciu, ktorá načíta obrázok. Tu už sa objavujú nejaké hviezdičky. Tie hviezdičky označujú pointre. Predstavte si, že máte premenné A a B, ktoré sú neskutočne veľké. V pamäti zaberajú veľmi veľa, aj niekoľko MB, alebo aj viac. A teraz máte premenné pA a pB, čo sú pointre na premenné A a B. Pointer je niekde v pämati, zaberá tam len niekoľko bytov. Myslím, že je to 32bitov. V Dose je to o čosi menej, len 20 bitov. Teda v porovnaní s premennými A a B sú to maličké kúsky pamäti. Na tomto mieste v pamäti je uložená nejaká adresa. A tá adresa vyjadruje, kde v pamäti sa nachádza premenná A. Váš program pristupuje k premennej A cez pointer, teda cez pA. A teraz si predstavte situáciu, že chcete vymeniť premenné A a B. Kopírovať to fyzicky v pamäti je veľmi náročné. Riešenie je vymeniť len pointre, ktoré ukazujú na premenné. Spravíte ešte nejaký tretí pointer, taký pomocný. Presne ako keď chcete vymeniť 2 premenné. Cez nejakú pomocnú to zrealizujete. A vymeníte takto len pár bytov. Nie je dôvod presúvať niekoľko MB v pamäti hore dolu, keď stačí vymeniť len pointre. Fyzicky premenné A a B ostanú tak ako boli, len pA už ukazuje na B. A váš program, ktorý pristupuje k dátam cez pointer ten si nevšimne rozdiel. Použijete pA ale už to budú dáta z premennej B.
Pointre sú náročné, ale tiež veľmi užitočné. A hovorí sa, že sú akousi dušou alebo srdcom jazyka C. To som niekde čítal. Je to veľmi užitočná vec, s tým súvisia potom dynamické premenné. Statické premenné zaberajú miesto v pamäti počas celého behu programu a napríklad do 100 prvkového poľa už nepridáte 101. prvok. Dynamická premenná si vezme toľko pamäti koľko potrebuje.
Ale dosť už teórie, nakoniec je to seriál o Opengl.

AUX_RGBImageRec je štruktúra s obrázkom.

AUX_RGBImageRec *LoadBMP(char *Filename) // nahrá obrázok z bmp
{
FILE *File=NULL; // File Handle


2 riadky a už sú tam 3 pointre. ;o). Filename je meno súboru. Je to pointer na char. Meno súboru je nejaký reťazec, teda pole znakov, teda charov. Bude nám stačiť pointer na toto pole.

if (!Filename) // máme meno súboru ?
{
return NULL; // ak nie, tak končíme
}


Ak máme meno súboru, tak ho otvoríme pre čítanie. Tu prichádza využitie knižnice stdio.h

File=fopen(Filename,"r");




if (File) // existuje ten súbor ?
{
fclose(File); // zatvor súbor
return auxDIBImageLoad(Filename);
// nahraj obrázok a vráť pointer
}


Ak sa nám to nepodarilo, tak vrátime NULL.

return NULL;
}


Ďalšia časť kódu nahrá obrázok a vytvorí z neho textúru.

int LoadGLTextures()
{

Status nám bude sledovať či sa nám podarilo spraviť textúru.
int Status=FALSE;


Teraz si vytvoríme premennú, kde uložíme našu bitmapu. Ako vidíte je to pointer na AUXRGBImageRec. Ten obsahuje šírku, výšku a dáta. TextureImage je pole. Ma len jeden prvok. V tejto časti by to kľudne mohla byť aj samostatná premenná, ale nabudúce už budeme potrebovať viac textúr.

AUX_RGBImageRec *TextureImage[1];

Pre istotu vyčistíme, aby sme mali istotu, že tam nič nie je.
memset(TextureImage,0,sizeof(void *)*1); // nastaví pointer na NULL


Teraz nahráme obrázok a konvertujeme ho na textúru.
TextureImage[0]=LoadBMP("Data/ammo.bmp") skočí na LoadBMP(). Nahrá sa obrázok z adresára Data ammo.bmp. Ak všetko pôjde dobre, tak v TextureImage[0] bude náš obrázok.

// nahraj obrázok, a skontroluj či nedošlo ku chybe
if (TextureImage[0]=LoadBMP("Data/ammo.bmp"))
{
Status=TRUE;

Teraz už máme obrázok v TextureImage[0] a môžeme začať budovať textúru. Prvý riadok je glGenTextures(1, &texture[0]), ktorý hovorí Opengl koľko textúr chceme. Neskôr toto číslo zvýšime, lebo budeme robiť viac textúr. Ešte si dajte pozor na to, že v C každé pole začína prvkom s indexom 0. Teda pole napríklad meno char[5] má 5 prvkov, a sú to prvky meno[0], meno[1], meno[2], meno[3], meno[4]. Na toto si dajte pozor.
Ďalší riadok glBindTexture(GL_TEXTURE_2D, texture[0]) hovorí Opengl, nech zobere textúru texture[0] ako cieľovú textúru, teda tú s ktorou ideme teraz pracovať.
2D textúry majú šírku a výšku. Sú aj iné typy textúr, ale táto je používaná asi najčastejšie.

glGenTextures(1, &texture[0]); // sprav textúru

// vyber našu textúru
glBindTexture(GL_TEXTURE_2D, texture[0]);

Ďalej vytvoríme našu aktuálnu textúru z nášho obrázku. Ďalší riadok povie Opengl, že textúra bude 2D textúra (GL_TEXTURE_2D), 0 hovorí o úrovni detailov, 3 je počet dátových komponentov, náš obrázok je RGB, teda Red Green Blue. To sú 3 zložky.
TextureImage[0]->sizeX je šírka textúry, TextureImage[0]->sizey je výška. 0 za tým hovorí, že okraj je široký 0. GL_RGB povie Opengl, že obrázok, ktorý používame má zložky RGB. Niektoré obrázky môžu mať ešte aj 4. parameter Alpha, ktorý hovorí o priesvitnosti. GL_UNSIGNED_BYTE znamená, že jednotlivé zložky sú unsigned byte.
TextureImage[0]->data hovorí Opengl, kde sú dáta nášho obrázku.

// sprav textúru
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);


Ďaľšie 2 riadky hovoria o type filtrovania, keď je obrázok väčší (GL_TEXTURE_MAG_FILTER) ako originál. Vtedy keď ho vykreslíme väčší ako jeho pôvodná veľkosť.
(GL_TEXTURE_MIN_FILTER) vtedy keď je menší ako jeho originálne veľkosť.
Použijeme GL_LINEAR pre oba typy. Takto bude textúra vyzerať pekne zahladená. Ak je váš systém slabší môžete použiť napríklad GL_NEAREST. Takto budú vyzerať vaše textúry síce kockato, ale pôjde to rýchlejšie.

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Linear Filtering
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering
}

A teraz uvoľníme pamäť, ktorú sme používali pre náš obrázok.


if (TextureImage[0]) // ak existuje
{
if (TextureImage[0]->data) // ak existujú dáta
{
free(TextureImage[0]->data);// uvoľni
}

free(TextureImage[0]); // uvoľni
}



return Status;
}


Do InitGL ešte príde riadok, ktorý overí či sa nám podarilo nahrať textúru v poriadku. A ešte musíme zapnúť, že chceme používať textúry.


int InitGL(GLvoid)
{
if (!LoadGLTextures())
{
return FALSE;
}

glEnable(GL_TEXTURE_2D); // zapneme textúry
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
return TRUE;
}


A teraz nakreslíme kocku a použijeme našu textúru.

int DrawGLScene(GLvoid)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-5.0f); // dozadu o 5


Otočíme sa podľa jednotlivých osí.

glRotatef(xrot,1.0f,0.0f,0.0f);
glRotatef(yrot,0.0f,1.0f,0.0f);
glRotatef(zrot,0.0f,0.0f,1.0f);


Teraz zvolíme, ktorú textúru chceme používať. A táto textúra bude použitá pri textúrovaní.

glBindTexture(GL_TEXTURE_2D, texture[0]);

Musíme dať pozor, aby sme na každý roh kocku dali správny roh textúry, inak môže byť textúra hore nohami alebo nejako inak pokazená.

Budeme používať funckiu glTexCoord2f, ktorá hovorí, ktoré koordináty z textúry pôjdu na nejaký bod v priestore. Sú to čísla od 0.0 do 1.0. Teda napríklad 0.0 je na našej textúre tiež 0.0, ale 1.0 je na našej textúre už 256. 0.5 je napríklad stred textúry.

Skúste sa pohrať s tými hodnotami a môžete vytextúrovať len časť nejakého obrázka na nejaký polygón.


glBegin(GL_QUADS);
// predná strana
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
// zadná strana
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
// vrchná strana
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
// zadná strana
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
// pravá strana
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
// ľavá strana
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glEnd();

Teraz ešte zvýšime xrot, yrot a zrot a kocka sa bude aj točiť.


xrot+=0.3f;
yrot+=0.2f;
zrot+=0.4f;
return true;
}


Teraz už viete, ako textúrovať nejaký ten obrázok na polygón. A teoreticky by ste si už mohli urobiť aj nejaký vlastný prehliadač objektov. Odporúčal by som vám začať z formátom gem, ktorý je vlastne celý ASCII, máte tam len napísané nejaké body a popísané, ktorú stranu tvoria ktoré body.
Napríklad:
10 7 30
1 -1 -1
-1 -1 -1
-1 -1 0
0 -1 1
1 -1 1
-1 0 1
-1 1 -1
1 1 -1
1 1 1
-1 1 1
5 1 2 3 4 5
4 8 1 5 9
4 7 8 9 10
5 2 7 10 6 3
4 8 7 2 1
5 5 4 6 10 9
3 3 6 4

Toto je príklad gem súboru. Prvé tri čísla označujú počet bodov, počet stien alebo tiež polygónov. Tretie číslo počet potrebných premenných napríklad na súradnice bodu. Je to skôr zbytočný údaj, lebo viete, že máte 10 bodov a každý má 3 súradnice. X Y Z.
Ďalej ide 10 riadkov, ktoré predstavujú tie body, a máte tam 3 údaje, a to pozícia X, Y a Z v 3D priestore. A nakoniec ide 7 polygónov. Prvý sa skladá z 5 vrcholov a tie sú vypísané za tým.

Ak by ste si to skúsili nakresliť, možno niektorý aj predstaviť, tak by ste mali dostať kocku, ktorá ma z jedného rohu trochu skrojené.
Pre záujemcov môžem dať niekam na web viac gem súborov, podstatne väčších.
Asi ste si všimli, že o textúrach tu nie je ani zmienka, správne gem objekty sú bez nich.
Potom by som Vám odporučil prechod na jednoduchý ASE súbor, kde by ste si dali len jeden objekt, môžete bez textúr, neskôr aj s nimi a neskôr aj viac objektov s viacerými textúrami.
Tieto typy súborov sa čítajú pomerne ľahko.
Neviem Vám povedať v ktorom programe sa dajú editovať gem súbory, ešte som sa s takým nestretol, ale ASE súbory môžete pomerne ľahko exportovať z 3Dstudia MAX. A dá sa tam zvoliť pár parametrov, či chcete aj textúry alebo nie.
A neskôr už môžete rozmýšľať o 3DS, MD2,MD3,... atď. MD3 sú napríklad quake 3 modely. No a pre extra super pokročilých: skúste načítať napr. MDC, to už sú modely napr. z Maxa Payna. Ale tie už sú zložitejšie, lebo sú robené inak, myslím, že sa to volá skeletal animation. Ak by ste sa stretli niekde z ich popisom alebo nejakým konvertovačom, tak mi dajte vedieť.

To je všetko z dnešnej časti.
Nabudúce si ukážeme trošku viac ohľadom textúrovania, napríklad MIPMAP.
http://www.softsklad.host.sk/opengl/lesson06.zip


Najnovsie clanky od tohto redaktora
Podobne clanky