Sunteți pe pagina 1din 19

MINISTERUL DE EDUCAŢIE DIN REPUBLICA MOLDOVA UNIVERSITATEA DE STAT DIN MOLDOVA

Departamentul de Informatică

Conf. doct. S. Pereteatcu Mag. în inf. A. Pereteatcu

Grafica 3D pe calculator

(Suport de curs în baza Direct 3D)

Chişinău - 2014

Grafica 3D (Suport de curs în baza Direct3D), S.Pereteatcu, A.Pereteatcu

C U P R I N S

INTRODUCERE

4

1. Bazele programării sub Windows

8

Noţiune de aplicaţie tip fereastră

8

Crearea aplicaţieiei în Visual C++ .NET

8

Modelul general de mesaje în Windows

10

Funcţia principală WinMain()

10

Tratarea evenimentelor în Windows

16

Prelucrătorul principal de evenimente

17

2. DirectX 9

20

Destinaţia DirectX 9

20

Componente DirectX 9

21

HAL

22

СОМ

22

Interfaţa IUnknown

22

Direct3D 9

23

Crearea scenei în Direct3D

24

Interfeţe Direct3D 9

25

Crearea pointerului spre interfaţă

26

Instalarea DirectX 9

SDK

27

3. Iniţializarea Direct3D

29

Noţiune de iniţializare

29

Crearea funcţiei de iniţializare Direct3D

29

Prelucrarea erorilor în DirectX

39

Rendering, sau desenarea în cadrul ferestrei a aplicaţiei

40

Eliberarea resurselor, ocupate de Direct3D

43

4. Desenarea obiectelor

2D

45

2

Grafica 3D (Suport de curs în baza Direct3D), S.Pereteatcu, A.Pereteatcu

Etape

45

Setarea formatului vertexurilor

45

Crearea bufferuluii vertexurilor

47

Renderingul obiectului

52

Desenarea pătratului

57

5. Matrice în Direct3D

 

59

Utilizarea matricelor

59

Matricea globală

 

59

Matricea de vizualizare (view matrix)

61

Matricea de proiecţie

62

6. Afişarea pe ecran a obiectului 3D

66

Crearea vertexurilor

66

Matrice

de

transformări

68

Desenarea

cubului

73

Indexarea vertexurilor

75

7. Bufferul de adâncime (Z-buffer)

79

Crearea bufferului de adâncime

79

Legarea părţilor

 

83

8. Lumini şi materiale

85

Noţiune de material

85

Lumină

86

Normală

 

88

Iniţializarea luminii şi materialului

91

3

Grafica 3D (Suport de curs în baza Direct3D), S.Pereteatcu, A.Pereteatcu

INTRODUCERE

DirectX (de la engl. direct direct, nemijlocit) este un set de API, elaborat pentru rezolvarea problemelor legate de programare sub Microsoft Windows. Cel mai larg se foloseşte pentru scrierea jocurilor pe calculator. Pachetul instrumental DirectX pentru Microsoft Windows este disponibil gratis pe siteul companiei Microsoft. De obicei cu versiunile reînoite DirectX sunt dotate aplicaţii noi de joc.

Tehnologia DirectX de la corporaţia Microsoft practic reprezintă un standard de instrumente pentru programarea graficii, mai ales jocurilor, pentru platforma Windows. Mai mult de 90% jocuri computerizate se scriu în limbajul C++ cu utilizarea bibliotecii DirectX. Împreună cu apariţia primului sistem de operare grafic puternic Windows 95, corporaţia Microsoft elaborează paralel bibliotecile multimedia, cu ajutorul cărora pot fi elaborate diferite aplicaţii grafice. Primul pachet instrumental se numea Game SDK. El a apărut aproximativ în acel timp, când Windows 95 cucerea piaţa mondială. Pachetul Game SDK a fost bazat pe grafică de rastru, în acel moment încă nu existau video plăci grafice 3D puternice. Pachetul susţinea şi sunetul şi unităţi de intrare. Un an după asta apar una după alta versiunile DirectX 2 şi DirectX 3, in componenţa lor prezintă şi biblioteca Direct3D. După apariţia sistemului Windows 98 biblioteca DirectX a fost completată cu versiunile 5 şi 6. În anul 1999 apare DirectX 7, care a semnalat epoca noua de jocuri computerizate 3D. Peste un an se lansează DirectX 8, după ce devine evident în bază cărui instrumentar trebuie de elaborat aplicaţii grafice sub SO Windows.

În 2002 firma Microsoft a lansat DirectX 9 cu susţinerea îmbunătăţită şi extinsă a shaderilor. Din anul 2002 DirectX se reînnoieşte de mai multe ori. În august 2004 în DirectX a fost adăugată susţinerea shaderilor de versiune 3.0 (DirectX 9.0c).

In aprilie 2005 interfaţa DirectShow a fost mutată în Microsoft Platform SDK.

Cronologia versiunilor DirectX

Versiunea DirectX

Numărul vrsiunii

Sistemul de operare

 

Data relizului

DirectX 1.0

4.02.0095

Windows 95a

 

30

septemb 1995

DirectX 2.0 / 2.0a

4.03.00.1096

Windows 95 OSR 2 şi Windows NT mai mici de

5

iunie1996

4.0

     
   

Windows 95 OSR 2.5 şi Windows NT 4.0 SP3 ultima versiunea DirectX susţinută pentru Windows NT 4.0

 

DirectX 3.0 / 3.0a

4.04.0068 / 69

15 septemb 1996

     
 

4.05.00.0155

   

DirectX 4.0

(RC55)

Accesibil ca beta pentru Windows NT 4.0

16 iulie 1997

     
 

4.05.01.1721 /

   

DirectX 5.0

1998

5

mai 1998

 

Windows 98 SE ultima versiunea DirectX Media susţinută pentru Windows NT 4.0. A fost inclus şi în Dreamcast

 

DirectX 6.0

4.06.00.0318

7

august 1998

 

(RC3)

 
 

DirectX 6.1

4.06.02.0436

Windows 95/98/98SE

3

febr 1999

 

(RC0)

   

DirectX 7.0

4.07.00.0700

 

22

septemb 1999

4

Grafica 3D (Suport de curs în baza Direct3D), S.Pereteatcu, A.Pereteatcu

 

(RC1)

   

DirectX 7.0a

4.07.00.0716

Windows 95/98/98SE/2000

1999

 

(RC1)

   

DirectX 8.0

4.08.00.0400

Windows 95/98/98SE/ME/2000

30

septemb 2000

 

(RC10)

   

DirectX 8.0a

4.08.00.0400

Ultima versiunea DirectX susţinută pentru Windows 95

7 noiemb 2000

 

(RC14)

 
 

4.08.01.0810

   

DirectX 8.1

4.08.01.0881

8 noiemb 2001

 

(RC7)

   

DirectX 8.1b

4.08.01.0901

 

???,2002

DirectX 8.2

4.08.02.0134

 

???,2002

 

(4.09.0000.0134)

   

DirectX 9.0

4.09.0000.0900

24

dec 2002

DirectX 9.0a

4.09.0000.0901

 

26

martie 2003

 

4.09.0000.0902

   

DirectX 9.0b

(RC2)

     

DirectX 9.0c

4.09.0000.0904

Windows XP SP2 ultima versiunea DirectX susţinută pentru Windows 98SE şi Windows Me

9

august 2004

 

(RC0)

 
 

Oferă interfeţele suplimentare IDirect3D9Ex şi IDirect3DDevice9Ex cu funcţionalitatea accesibilă numai prin LDDM-driverii SO Windows Vista.

DirectX 9.0L

4.09.0000.0905

 
 

(?)

 
 

DirectX 10 (inclus în componenţa Windows Vista)

 

6.0.6000.16386

Prima versiunea Windows Vista. Informaţii despre Direct3D10

10

noiemb 2006

   
 

DirectX 10.1

6.00.6001.18000

Service Pack 1 pentru Windows Vista, Windows Server 2008

4

febr 2008

     

DirectX 11 (inclus în componenţa Windows

 

Windows Vista Service Pack 2, Windows 7.

 

6.01.7600.16385

Prezentarea oficială a avut loc la Gamefest 2008. Informaţii despre Direct3D11

22

iulie 2009

7)

   

DirectX 11.1 (inclus în componenţaWindows 8)

 

26

octomb 2012

     

DirectX 11.2 (inclus în componenţa Windows

     
 

17

octomb 2013

     

DirectX 11.3 (inclus în componenţa Windows

     
 

29

iulie 2015

10)

     

DirectX 12 (inclus în componenţa Windows

     
 

29

iulie 2015

10)

     

5

Grafica 3D (Suport de curs în baza Direct3D), S.Pereteatcu, A.Pereteatcu

În capitolul 1 se descriu bazele programării sub SO Windows, se creează aplicaţia de tip fereastră. Aplicaţia creată permanent va fi dezvoltată pe parcursul studierii a materialului.

Capitolul 2 reprezintă o introducere în biblioteca DirectX. Aici sunt enumerate componentele acestei bibliotecii, sunt descrise pe scurt tehnologiile utilizate la crearea DirectX. Sunt prezentate informaţii despre СОМ, Direct3D, conceptul de creare a scenelor în Direct3D. În sfârşit, este descrisă instalarea DirectX 9 SDK pe calculator.

În capitolul 3 sunt expuse informaţii cheie despre etapa iniţială de utilizare a Direct3D — iniţializarea Direct3D, crearea dispozitivului Direct3D şi reglarea dispozitivelor.

În capitolul 4 ce creează şi se afişează pe ecran una din cele mai simple figuri un triunghi simplu. Se foloseşte bufferul vertexurilor şi conveierul de randare. Astfel se obţin informaţii principale despre geometria scenei în Direct3D.

Capitolul 5 este consacrat matricelor. Matricele joacă un rol foarte important în Direct3D.

În capitolul 6 este examinată afişarea pe ecran unui obiect tridimensional adevărat. Este expus conceptul de indexare a vertexurilor.

În capitolul 7 este descris bufferul de adâncime. Sortarea pixelilor după distanţa până la observator — iată pentru ce este necesar bufferul de adâncime, se mai numeşte şi Z-buffer.

Capitolul 8 conţine informaţii despre materiale ţi lumini. Sunt descrise modele de iluminare, informaţii despre surse de lumină, principiile de interacţiune a materialului cu iluminarea obiectului. Anume în baza acestor principii se construieşte percepţia culorilor de către observator. Tot în capitolul acesta sunt cercetaţi şi vectori normali, care se folosesc la calcularea iluminării.

În capitolul 9 sunt descrise bazele ale texturării. Se examinează metoda standard de suprapunerea texturilor pe obiect.

Capitolul

multitexturare.

10

continuă

tema

capitolului

precedent

prin

expunerea

materialului

despre

În capitolul 11 se descrie afişare de texte. Afişarea textului pe ecran este foarte importantă pentru diferite aplicaţii (de exemplu, jocuri). la sfârşitul capitolului se discută modul de trecere de la aplicaţia tip fereastră la aplicaţia tip ecranul plin (fullscreen).

În capitolul 12 В следующем разделе рассматривается вопрос загрузки модели, сделанной сторонним ЗD-редактором şi конвертированной в Х-формат.

În capitolul 13 Далее рассматриваются устройства ввода, представленные интерфейсом DirectInput.

În capitolul 14 Рассматривается работа с клавиатурой

În capitolul 15и мышью.

În capitolul 16 Последующие разделы посвящены звуку. Для этих целей в DirectX существуют интерфейсы DirectMusic

6

În capitolul 17 şi DirectSound.

Grafica 3D (Suport de curs în baza Direct3D), S.Pereteatcu, A.Pereteatcu

În capitolul 18 Следующий раздел представляет введение в тематику вершинных шейдеров. Этот большой теоретический раздел раскрывает общую концепцию работы вершинных шейдеров, затрагивая вершинные шейдеры первой версии.

7

Grafica 3D (Suport de curs în baza Direct3D), S.Pereteatcu, A.Pereteatcu

1. Bazele programării sub Windows

Noţiune de aplicaţie tip fereastră

Înainte de a începe programarea graficii cu DirectX 9, trebuie să elaborăm carcasul programului, care va crea suprafaţa de lucru pentru aplicaţia grafică 3D. Windows este un SO multitasking şi ceea ce vedem pe ecran al monitorului este aplicaţia obişnuită - tip fereastră. După ce vom crea carcasul, putem să trecem la programarea graficii, desenând orice obiecte în cadrul aplicaţiei create. Deci scopul principal este scrierea codului ferestrei în baza căruia vor fi create toate modificările ulterioare. Contează şi dimensiunea ferestrei a aplicaţiei. Sunt două moduri:

fullscreen şi fereastră. În modul fereastră putem seta dimensiunile ferestrei, stilul şi poziţia pe ecran. În modul fullscreen se indică rezoluţia şi frecvenţa de redesenare a ecranului. De la început vom folosi numai modul fereastră. În capitolul 11 se examinează trecerea la modul fullscreen, care de fapt nu este complicată.

Crearea aplicaţieiei în Visual C++ .NET

Pentru crearea aplicaţiilor mediul de programare Visual C++ .NET conţine mijloace incorporate. Deschidem mediul de programere Visual С++ .NET şi creăm un proiect. Perntru aceasta efectuăm următoarele acţiuni:

1. File / New / Project. Apare caseta de dialog New Project;

2. În caseta Project Types selectăm Visual C++ Projects, iar în caseta Templates Win 32 Project;

3. În caseta Name scriem numele proiectului, de exemplu, Project1. În caseta Location indicăm mapa, în carea se va păstra proiectul creat;

4. OK.

Apre caseta de dialog Win 32 Application Wizard Project1 (fig. 1.1), în care trecem la pagina Application Settigs şi în reginea Additional options bifăm opţiunea Empty project. În regiunea Application type selectăm Windows application, după ce apăsăm butonul Finish.

Astfel am creat o aplicaţie vidă obişnuită, care nu are nici o linie de cod. Mai departe dezvoltăm aplicaţia. Din partea stânga a ferestrei Visual C++. NET se află panelul cu trei pagini: Solution Explorer, Resourse View şi Class View. După selectarea paginii Solution Explorer, apare arborele proiectului Project1. După apăsarea butonului "+" pe lângă numele proiectului se desfăşoară ramura cu mape: Source File (fişiere cu cod, de regulă au extensia c şi/sau cpp) şi Header File (cu fişiere antet, de regulă au extensia h).

8

Grafica 3D (Suport de curs în baza Direct3D), S.Pereteatcu, A.Pereteatcu

de curs î n baza Direct3D), S.Pereteatcu, A.Pereteatcu Fig. 1.1. Caseta de dialog Win32 Application Wizard

Fig. 1.1. Caseta de dialog Win32 Application Wizard Project1

Inserăm un fişier gol în mapa Source File. În el vom scrie codul programului. Pentru a insera un fişier gol efectuăm următorii paşi:

1. Executăm clic drept pe iconiţa Source File, din meniul context selectăm opţiunea Add. Apoi după săgeată din meniul derulant alegem opţiunea Add New Item. Pe ecran apare caseta de dialog Add New Item - Project1 (fig. 1.2);

apare caseta de dialog Add New Item - Project1 (fig. 1.2); Fig. 1.2. Caseta de dialog

Fig. 1.2. Caseta de dialog Add New Item Project1

2. În caseta Templates selectăm C++ File (.cpp);

9

Grafica 3D (Suport de curs în baza Direct3D), S.Pereteatcu, A.Pereteatcu

3. În caseta Name scriem denumirea fişierului de creare, de exemplu, WindowsBazis. Apăsăm butonul Add. După asta pa pagina Solution Explorer - Project1 în mapa Sourse File va apărea fişierul gol WindowsBazis.cpp.

Modelul general de mesaje în Windows

Comunicarea Windows-ului cu aplicaţiile se bazează pe modelul de evenimente. Orice aplicaţie tip windows în timpul vieţii interacţionează cu SO prin intermediul de mesaje.

Numărul de mesaje pot fi destul de mare. Pentru a sistematiza mesajele curente, există aşa

numită coadă de evenimente. Ea este realizată în formă de buclă obişnuită. Fiecare din mesajele

Pentru a

apărute aşteaptă rândul său de prelucrare, după ce se extrage de către SO Windows

prelucra toate mesajele Windows dispune de un prelucrător de mesaje pentru toate aplicaţiile.

Modelul de interacţiune aplicaţiilor cu mesaje este prezentat schematic în fig. 1.3.

Aplicaţia Aplicaţia fereastră 1 fereastră 2 Coadă Coadă Coadă evenimen. mesaje ap.1 mesaje ap.2 Windows
Aplicaţia
Aplicaţia
fereastră 1
fereastră 2
Coadă
Coadă
Coadă
evenimen.
mesaje ap.1
mesaje ap.2
Windows

Fig. 1.3. Modelul de evenimente Windows

Reieşind din acest model de evenimente, pentru a crea o aplicaţie este necesar să creăm o fereastră şi să pornim un prelucrător de mesaje. Punctul de pornire a oricărei aplicaţiei în Windows este funcţia WinMain(), în care se creează fereastra şi se tratează evenimentele. De aceea, de la bun început, vom crea funcţia WinMain(), în care vom descrie clasa windowsclass, în care vom indica dimensiunea, stilul, culoarea, fundalul ferestrei viitoare. Apoi vom crea fereastra cu funcţia CreateWindowEx(). Apoi vom înregistra fereastra şi vom crea un prelucrător de evenimente, în care vor fi transmise diferite mesaje.

Funcţia principală WinMain()

În primul rând conectăm fişierul antet windows.h. El conţine declaraţiile claselor care sunt necesare pentru a programa în mediul Windows:

#include <windows.h> #include <tchar.h>

Fişierul antet tchar.h se foloseşte pentru utilizarea codului Unicod.

Apoi urmează funcţia principală a tuturor aplicaţiilor Windows: WinMain(). Antetul acestei funcţii este următorul:

int WINAPI WinMain( HINSTANCE hinstance, HINSTANCE hprevinstance,

10

LPSTR lpCmdLine, int nCmdShow)

Funcţia WinMain() are următorii parametri:

Grafica 3D (Suport de curs în baza Direct3D), S.Pereteatcu, A.Pereteatcu

hinstance este descriptorul aplicaţiei de creare, aşa numitul handle. Descriptorul se generează de către SO Windows pentru urmărirea ulterioară a aplicaţiei. Altfel spus, hinstance este un fel de etichetă a aplicaţiei şi a ferestrei care se creează;

hprevinstance acest parametru deja nu se foloseşte. El provine de la SO Windows 3.1, şi a fost lăsat pentru compatibilitate. Valoarea permanentă a acestui parametru este 0;

lpCmdLine pointer la şirul de comandă, care urmează imediat după numele comenzii care se lansează;

nCmdShow indică aspectul ferestrei care se creează pe ecranul monitorului. Există un şir mare de flaguri, care descriu aspectul dorit al ferestrei, şi care pot fi combinate pentru a crea valoarea acestui parametru. Informaţii suplimentare despre flagurile date pot fi găsite în documentaţia pentru Win32 API.

Cercetăm clasa windowsclass.

Trebuie să descriem clasa ferestrei windowsclass. Clasă – este ceea ce ne permite să diferenţiem aspectul şi destinaţia ferestrei. Diferite ferestre se diferenţiază una de alta prin clasă. SO Windows are un set mare de astfel de clase predefinite. Ne rămâne să păstrăm în structura windclassex informaţii despre clasa windowsclass care se creează. Deci, creăm clasa windowsclass, care va răspunde de obţinerea scopul formulat:

WNDCLASSEX windowsclass; // clasa ferestrei de creare

Declararea tipului structurat WINDCLASSEX, care este necesar pentru descrierea clasei, arată astfel:

typedef struct _WNDCLASSEX

{

UINT cbSize; UINT style; WINDPOC lpfnWndProc; int cbClsExtra; int cbWndExtra; HANDLE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackgroung; LPCTSTR lpszMenuName; LPCTSTR lpszClassName; HICON hIconSm; } WNDCLASSEX;

Câmpurile structurii au următoarea destinaţie:

cbSize dimensiunea structurii care se creează. Paralel cu descrierea câmpurilor le vom completa. Indicăm dimensiunea structurei noastre:

11

Grafica 3D (Suport de curs în baza Direct3D), S.Pereteatcu, A.Pereteatcu

windowsclass.cbSize=sizeof(WNDCLASSEX);

style conţine combinaţia flagurilor ce descriu stilul dorit al ferestrei. Combinarea se face cu ajutorul operatorului sau pe biţi "|". Completăm câmpul style:

windowsclass.style=CS_DBLCLKS|CS_OWNDC|CS_HREDRAW|CS_VREDRAW;

Descriem flagurile utilizate (informaţiile suplimentare pot fi luate din documentaţia pentru Win

32):

CS_VREDRAW în cazul când se schimbă înălţimea ferestrei sau fereastra a fost deplasată, este necesară redesenarea ferestrei în întregime;

CS_HREDRAW în cazul când se schimbă lăţimea ferestrei sau fereastra a fost deplasată, este necesară redesenarea ferestrei în întregime;

CS_OWNDC pentru fiecare fereastră a clasei date se repartizează un context dispozitiv propriu;

CS_DBLCLKS în cazul unui click dublu în cadrul ferestrei, ferestrei se transmit informaţii despre click dublu;

lpfnWndProc pointer la funcţia principală de tratare a evenimentelor cu ordinea inversă a parametrilor (call back). Orice aplicaţie în Windows conţine bucla de prelucrare a evenimentelor. În bucla respectivă se apelează funcţia MainwinProc(), de aceea scriem:

windowsclass.lpfnWndProc=MainWinProc;

câmpurile cbClsExtra şi cbWndExtra, sunt destinate pentru păstrare informaţiilor suplimentare. Câmpurile acestea se folosesc rar, mai ales la programare cu DirectX. De aceea scriem:

windowsclass.cbClsExtra=0, windowsclass.cbWndExtra=0;

hInstance câmpul acesta răspunde de exemplarul aplicaţiei care se creează şi se transmite funcţiei WinMain():

windowsclass.hInstance=hinstance;

hIcon defineşte pictograma aplicaţiei. Cu ajutorul funcţiei LoadIcon() putem încărca o pictogramă proprie, sau o pictogramă de sistem. Antetul funcţiei LoadIcon() este următorul:

HICON LoadIcon(HINSTANCE hInstance, LPCTSTR LpIconName)

Descriem parametrii acestei funcţii:

hInstance exemplarul aplicaţiei. Pentru a încărca o pictogramă standard, se foloseşte valoarea NULL;

LpIconName identificatorul resursei de tip pictogramă care se încarcă. Vom folosi pictograma standard IDI_APPLICATION pictograma care se foloseşte implicit pentru aplicaţii. Există o sumedenie de identificatori pentru încărcarea diferitelor pictograme. Există posibilitatea creării unei pictograme proprii pentru a înlocui pictograma de sistem. Având antetul funcţiei LoadIcon(), vom scrie:

windowsclass.hIcon=LoadIcon(NULL, IDI_APPLICATION);

12

Grafica 3D (Suport de curs în baza Direct3D), S.Pereteatcu, A.Pereteatcu

hCursor câmpul acesta răspunde de utilizarea cursorului. După utilizare câmpul acesta este asemănător cu cel precedent hIcon. Se diferă numele funcţiei care încarcă cursorul. Vom scrie:

windowsclass.hCursor=LoadCursor(NULL, IDC_ARROW);

Cursorul standard are formă de săgeată mică şi identificatorul IDC_ARROW. Asemenea pictogramelor, există un set de identificatori de cursoare (programatorul poate să elaboreze cursoare proprii);

hbrBackgroung culoarea de fundal al ferestrei. Pentru a colora fundalul cu o culoare ptandard predefinită se foloseşte funcţia GetStockObject(). Funcţia are un singur parametru flagul care setează culoarea pensulei de umplere. Pentru umplerea fundalului cu culoare sură scriem:

windowsclass.hbrBackground=(HBRUSH)GetStockObject(GRAY_BRUSH);

Putem să încercăm să colorăm fundalul cu o altă culoare, totuşi pentru DirectX aceasta nu are nici o însemnătate, fiindcă pentru asta sunt definite mijloacele proprii. Totuşi mai descriem câteva pensule de diferite culori:

GRAY_BRUSH umplerea cu pensula de culoare sură;

BLACK_BRUSH pensula neagră;

WHITE_BRUSH pensula albă;

LTGRAY_BRUSH pensula de culoare sură deschisă;

DKGRAY_BRUSH pensula de culoare sură închisă;

HOLLOW_BRUSH pensula transparentă (fără umplere);

lpszMenuName câmpul destinat pentru conectarea unui meniu la fereastra aplicaţiei. Valoarea NULL indică că aplicaţia nu va avea meniul:

windowsclass.lpszMenuName=NULL;

lpszClassName indică numele clasei de descriere a ferestrei aplicaţiei de creare. Pot exista simultan (de obicei aşa şi este) câteva aplicaţii, la crearea cărora s-a folosit una şi aceeaşi clasa windowsclass, iar sistemul de operare trebuie cumva să le deosebească. Anume pentru asta se foloseşte câmpul acesta. Aici putem indica o denumire arbitrară, principalul să ţinem cont de ea (să nu ne încurcăm în ele dacă vom avea mai multe denumiri):

windowsclass.lpszClassName=_T("WINDOWSCLASS");

hIconSm descriptorul pictogramei mici, care se afişează pe bara de taskuri sau în antetul ferestrei aplicaţiei. Vom folosi pictograma standard. Pentru asta vom scrie:

windowsclass.hIconSm=LoadIcon(NULL, IDI_APPLICATION);

Astfel, completarea tuturor câmpurilor structurii va arăta aşa:

WNDCLASSEX windowsclass; // класс создаваемого окна windowsclass.cbSize=sizeof(WNDCLASSEX); windowsclass.style=CS_DBLCLKS|CS_OWNDC|CS_HREDRAW|CS_VREDRAW; windowsclass.lpfnWndProc=MainWinProc;

13

Grafica 3D (Suport de curs în baza Direct3D), S.Pereteatcu, A.Pereteatcu

windowsclass.cbClsExtra=0;

windowsclass.cbWndExtra=0;

windowsclass.hInstance=hinstance; windowsclass.hIcon=LoadIcon(NULL, IDI_APPLICATION); windowsclass.hCursor=LoadCursor(NULL, IDC_ARROW); windowsclass.hbrBackground=(HBRUSH)GetStockObject(GRAY_BRUSH); windowsclass.lpszMenuName=NULL; windowsclass.lpszClassName=_T("WINDOWSCLASS"); windowsclass.hIconSm=LoadIcon(NULL, IDI_APPLICATION);

După ce am completat şi am salvat în structura windowsclass toate valorile, clasa windowsclass trebuie să fie înregistrată. Aceasta se face cu funcţia RegisterclassEx(). Parametrul funcţiei reprezintă adresa structurii cu descrierea clasei. Pentru orice aplicaţie care se creează, clasa poate fi înregistrată doar o singură dată:

if(!RegisterClassEx(&windowsclass)) // înregistrăm clasa creată return 0;

Creăm fereastra. După ce am înregistrat clasa, putem să creăm fereastra. Aceasta se face cu funcţia CreateWindowEx(), care are următorul antet:

HWND CreateWindowEx( DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWindParent, HWND hMenu, HINSTANCE hInstance, LPVOID lpParam);

Parametrii funcşiei CreateWindowEx() sunt:

dwExStyle flagul stilurilor ferestrei. Se foloseşte rar. În majoritatea de cazuri se foloseşte valoarea WS_EX_TOPMOST, ceea ce indică că fereastra aplicaţiei va apărea deasupra celorlalte ferestre. Valoarea NULL ignorează acest parametru;

lpClassName denumirea clasei ferestrei care se creează. În cazul nostru este

WINDOWSCLASS;

lpWindowName antetul ferestrei. De obicei textul antetului corespunde sensului aplicaţiei, de exemplu, "Fereastra de bază pentru DirectX";

dwStyle combinaţia flagurilor ce descriu stilul şi comportarea ferestrei ce se creează. Există un set de astfel de flaguri. Iată careva din ele:

WS_OVERLAPPED fereastra cu o linie de antet şi o margine;

14

Grafica 3D (Suport de curs în baza Direct3D), S.Pereteatcu, A.Pereteatcu

WS_VISIBLE fereastra va fi vizibilă din start;

WS_CAPTION fereastra cu o linie de antet (include în sine stilul WS_BORDER);

WS_BORDER fereastra cu o margine subţire;

WS_ICONIC fereastra va fi minimizată din start;

WS_OVERLAPPEDWINDOW fereastra cu suprapunere (include în sine următoarele 6

stiluri:

WS_MINIMIZEBOX şi WS_MAXIMIZEBOX) este un flag destul de funcţional. Anume acest flag vom folosi pentru fereastra aplicaţiei noastre;

WS_OVERLAPPED,

WS_CAPTION,

WS_SYSMENU,

WS_THICKFRAME,

WS_MINIMIZE fereastra va fi minimizată din start;

WS_MAXIMIZE fereastra va fi maximizată din start;

WS_MAXIMIZEBOX fereastra cu butonul Maximize (se foloseşte numai cu stilul

WS_SYSMENU);

WS_MINIMIZEBOX fereastra cu butonul Minimize (se foloseşte numai cu stilul

WS_SYSMENU);

X, Y poziţia iniţială a colţului stânga sus în pixeli. Se poate de indicat coordonatele prin utilizarea flagului CW_USEDEFAULT, lăsând astfel valorile implicite. Vom folosi pentru X valoarea 300, iar pentru Y valoare 150, setând astfel coordonatele colţului stânga sus în pixeli;

nWidth şi nHeight lăţimea şi respectiv înălţimea ferestrei în pixeli. Se poate de folosit valorile implicite cu ajutorul flagului CW_USEDEFAULT, sau de indicat valorile concrete, de exemplu, 500×400 pixeli;

hWindParent descriptorul ferestrei părinte. Dacă fereastra părinte nu este, se foloseşte valoarea NULL;

hMenu descriptorul meniului, adică dacă aplicaţia are un meniu, poate fi indicat descriptorul acestui meniu şi meniul va fi conectat la fereastra aplicaţiei. dacă meniul lipseşte, atunci valoarea parametrului se pune pe NULL;

hInstance exemplarul aplicaţiei. Foloseşte valoarea hinstance pasată funcţiei

WinMain();

lpParam pointerul la datele ferestrei, de obicei are valoarea NULL.

Acum toate valorile ale parametrilor funcţiei sunt cunoscute. Pentru a crea fereastra, declarăm descriptorul ferestrei şi apelăm funcţia CreateWindowEx():

HWND hwnd; // descriptorul ferestrei if(!(hwnd=CreateWindowEx( NULL, // stilul ferestrei _T("WINDOWSCLASS"), // numele clasei _T("Fereastră de bază pentru DirectX"), // antetul ferestrei

15

Grafica 3D (Suport de curs în baza Direct3D), S.Pereteatcu, A.Pereteatcu

//

//

WS_OVERLAPPEDWINDOW|WS_VISIBLE, // 0, 0, // colţul stânga sus CW_USEDEFAULT, 0, // colţul stânga sus 500, 400, // lîţimea şi înălţimea ferestrei CW_USEDEFAULT, 0, // lîţimea şi înălţimea ferestrei NULL, // descriptoruil ferestrei pîrinte NULL, // descriptorul meniului hinstance, // descriptorul aplicaşiei NULL))) // pointerul la datele ferestrei return 0;

NULL, // descriptorul meniului hinstance, // descriptorul aplicaşiei NULL))) // pointerul la datele ferestrei return 0;

Cu ajutorul instrucţiunii if se prelucrează erorile.

După ce fereastra a fost creată, ea trebuie să fie afişată explicit pe ecran şi reînnoită. Lucrul acesta se face prin două funcţii:

ShowWindow(hwnd, SW_SHOWDEFAULT); // afişăm fereastra UpdateWindow(hwnd); // reînnoim fereastra

Tratarea evenimentelor în Windows

În SO Windows evenimentele legate de aplicaţia trebuie prelucrate cu prelucrătorul de evenimente al acestei aplicaţiei. Pentru fiecare clasă poate fi definit unul sau mai mulţi prelucrători proprii de evenimente. Astfel se îmbunătăţeşte funcţionalitatea programului. În timp ce lucrează orice aplicaţie se generează o sumedenie de diferite mesaje. Ele se pun la coadă. Evenimentele legate de fereastra aplicaţiei noastre, nimeresc în secţiunea coţii care se referă anume la fereastra noastră. După aceasta prelucrătorul de evenimente principal extrage mesajul de rând si îl transmite funcţiei MainWinProc() pentru prelucrarea ulterioară. Cu evenimentele pentru care nu este asignat prelucrătorul, se ocupă însuşi SO Windows.

Cercetăm antetul funcţiei MainWinProc():

LRESULT CALLBACK MainWinProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)

Funcţia MainWinProc() are următorii parametri:

hwnd descriptorul ferestrei. Se foloseşte pentru a afla de la care fereastră a venit mesajul în cazul când sunt deschise simultan mai multe ferestre ale uneia şi aceeaşi clasă;

msg identificatorul evenimentului, care este transmis funcţiei MainWinProc() pentru prelucrare;

wparam şi lparam parametrii suplimentari la evenimentul dat. La elaborarea prelucrătorului de evenimente, de obicei, se foloseşte construcţia switch(msg). După analiza identificatorului msg, pot fi utilizate informaţiile suplimentare transmise prin parametrii wparam şi lparam.

WM_PAINT mesagul acesta se trimite atunci când se cere redesenare ferestrei în întregime (de exepmplu, fereastra a fost deplasată, fereastra a fost mărită, etc.);

16

Grafica 3D (Suport de curs în baza Direct3D), S.Pereteatcu, A.Pereteatcu

WM_DESTROY mesajul acesta se trimite de către SO Windows atunci când fereastra trebuie să fie închisă. Mesajul acesta comunică că trebuie de eliberat toate resursele ocupate de către aplicaţia;

WM_QUIT după eliberarea resurselor se generează mesajul acesta care va aduce la închiderea aplicaţiei.

Ca rezultat obţinem funcţia MainWinProc():

LRESULT CALLBACK MainWinProc(HWND hwnd, // descriptorul ferestrei UINT msg, // identificat. evenimentului WPARAM wparam, // informaţii suplimentare LPARAM lparam) // informaţii suplimentare

{

 

switch(msg)

{

//

 

case WM_PAINT:

ValidateRect(hwnd, NULL); break;

//

 

case WM_DESTROY:

PostQuitMessage(0);

return 0;

}

return DefWindowProc(hwnd, msg, wparam, lparam);

}

Apelul PostQuitMessage(0) pune la coadă mesajul WM_QUIT, care va închide aplicaţia noastră. WM_QUIT se aplică nemijlocit în prelucrătorul de evenimente principal. Funcţia DefWindowProc() prelucrează implicit acele mesaje pe care nu le prelucrează aplicaţia noastră.

Prelucrătorul principal de evenimente

Cercetăm prelucrătorul principa de evenimente, care deocamdată va arăta astfel:

MSG msg; // indicatorul de mesaj

while(GetMessage(&msg, NULL, 0, 0))

{

TranslateMessage(&msg); // transferul introducerii de la tastat. DispatchMessage(&msg); // prelucrarea şi pasarea mesajelor // funcţiei MainWinProc()

}

return msg.wParam;

Antetul funcţiei GetMessage() arată astfel:

BOOL GetMessage( LPMSG lpMsg, HWND hWnd, UINT wMsgFiltrenMin,

17

UINT wMsgFiltrenMax)

Parametrii funcţiei GetMessage() sunt:

Grafica 3D (Suport de curs în baza Direct3D), S.Pereteatcu, A.Pereteatcu

lpMsg poiner la structura care este responsabilă de mesaje;

hWnd descriptorul ferestrei care se crează;

wMsgFiltrenMin primul mesaj ajuns la prelucrarea;

wMsgFiltrenMax ultimul mesaj de prelucrare.

Bucla while se execută atâta timp cât funcţia GetMessage() întoarce valoarea diferită de zero. Corpul buclei este simplu: la apariţia mesajului din coada mesajelor, mesajul se prelucrează cu funcţia TranslateMessage() şi se transmite funcţiei DispatchMessage(), care pentru prelucrarea apelează funcţia MainWinProc(), trnsmiţind ultimei toate informaţiile necesare.

Pentru compilarea codului iniţial, aflându-ne în caseta de dialog cu proiectul deschis Project1, selectăm sau simplu deschidem WindowsBazis.cpp. Apoi apăsăm tasta <Ctrl> şi reţinând-o, apăsăm tasta <F7>. se va compila codul iniţial din fişierul WindowsBazis.cpp. Apoi apăsăm tasta <F7> se va executa editare legăturilor. Pentru a vedea rezultatul folosim combinaţia de taste <Ctrl>+<F5>. Fereastra creată de programul este prezentată în fig. 1.4.

creată de programul este prezentată în fig. 1.4. Fig. 1.4. Fereastra de bază pentru DirectX Astfel

Fig. 1.4. Fereastra de bază pentru DirectX

Astfel am creat o aplicaţie simplă tip fereastră, în care mai departe vom integra codul propriu, utilizând funcţiile bibliotecii DirectX 9. Cum a fost arătat, aplicaţia poate fi creată cu setarea

18

Grafica 3D (Suport de curs în baza Direct3D), S.Pereteatcu, A.Pereteatcu

proprietăţilor necesare. Mai departe va fi descris conceptul de creare a scenei în DirectSD, va fi abordată tehnologia СОМ, pe platforma căreia se bazează toată biblioteca DirectX.

19