http://alpha-thema-online.uv.ro
Fa-ti si tu propriul forum, pe www.myforum.ro!
Pagina de start a forumului http://alpha-thema-online.uv.ro Autentificare Inregistrare FAQ Membri Cautare

Pagina de start a forumului http://alpha-thema-online.uv.ro » Visual Studio » Basic primitives and texturing DirectX& VB
Creaza un subiect nou  Raspunde la subiect Subiectul anterior :: Subiectul urmator 
Basic primitives and texturing DirectX& VB
MesajTrimis: 19/07/2007 17:21 Raspunde cu citat (quote)
Ad_Infinitum
Administrator
Administrator
Ad_Infinitum
Data inscrierii: 23/Iun/2007
Mesaje: 212




Tutorial 2

- Introducere in Direct3D, Triunghiuri -

Download source code

E pe la 11 noaptea, asa ca imi veniti cu o bere pentru tutorialul curent. (alta decat pe cea pe care o beau acum Smile )

In acest tutorial vom crea o fereastra D3D si vom desena un patrat texturat.
Sa incepem cu niste elemente de baza despre 3D si placa noastra grafica,
pentru care am dat atitia bani sa aiba "de toate".

Functionarea acceleratoarelor grafice sunt tare complicate,
dar ceea ce ne intereseaza pe noi, e la ce s-au gandit baietii de la firmele mari de profil,
cand au stat zi si noapte ca sa mai primeasca vreun punct in plus la testele de la reviste.
Ei au gandit astfel: obiectele 3D sa fie compuse din triunghiuri,
ele sa poata fii texturate, iar descrierea imaginii sa fie vectoriala.
De fapt placa grafica se ocupa mai mult de texturare,
si ar putea fi numit "accelerator 2D" iar restul il face DirectX-ul.
(placile moderne au si cateceva imbunatatiri cum ar fi "Hardware transform & Lighting",
dar nu exista inca un "pure" device, care sa poate functiona fara grija transformariolor efectuate de CPU)

Cum functioneaza: se specifica coordinate in spatiu (x, y, z) numite "vertice" ("vertex" e plural pt. "vertice",
dar cateodate mai citesti "vertices" sau "vertexes" gresite de altfel)
Pentru a crea un triughi, se vor specifica 3 coordinate.
La ifecare coordinata, se va mai aduga cate o coordinata de texturare numita "TU" respectiv "TV".
(alias "UV mapping" de la 3dsmax)
UV mapping functioneaza astfel: ai o imagine de rezolutia sa spunem 320x240.
TU este pe orizontala, iar TV pe verticala. TU si TV sunt din intervalul [0, 1]
0 insemnand primul pixel din partea stanga a imaginii, iar 1 va insemna pixelul din dreapta,
adica pixelul 320.-lea din textura noastra. (textura inseamna fotografie incarcata in memorie gata de folosit)
La fel si TV 0 e coltul de sus a imaginii, iar 1 va insemna 240.

0 <-- TU --> 1

^
|
TV
|
V

1

ex: TU = 0.5 TV = 0.5 va insemna pixelul din mijlocul imaginii

Daca vrem sa afisam o poză (textura), vom crea un dreptunghi texturat.
Pentru a crea un dreptunghi avem necesitate de 2 triunghiuri.

(0,0) |-----| (1,0)
| 1 |
| |
| |
| 2 |
(0,1) |-----| (1,1)

Obiectul va arata astfel:

XYZ TU/TV

triunghi1:
(0,0,0) (0,0)
(320,0,0) (1,0)
(320,240,0) (1,1)

triunghi2:
(0,0,0) (0,0)
(0,240,0) (1,0)
(320,240,0) (1,1)

Cam multa teorie asa deodata, dar e destul de rudimentar de fapt.
Daca alterati marimea dreptunghiului, D3D va destul de lungi textura,
este asa numitul "streching", careia se pot atribui niste filtre mai tarziu.

Dar ia sa vedem si putin cod sa fie mai clar:

frmMain

Citat:

Dim bRunning As Boolean

Private Sub Form_Load()
Me.Show
Direct3D.PreCheck 'Precheck the device, initialize DX objects

bRunning = Direct3D.InitD3D(False) 'Init the device,
bRunning = Direct3D.InitGeometry() 'Init Geometry

Do While bRunning
Direct3D.Render 'Render the scene
DoEvents
Loop

Direct3D.TerminateDirect3D 'Clean up device and DirectX objects
End
End Sub

Private Sub Form_Unload(Cancel As Integer)
bRunning = False
End Sub

Private Sub Form_KeyUp(KeyCode As Integer, Shift As Integer)
If KeyCode = vbKeyEscape Then bRunning = False 'if Escape key is pressed Quit program
End Sub



Direct3D.bas

Citat:


'''''''''''''''''''''''''''''''''''''''''
'(C) 2005 Osvath - Boros Robert '
' osvathrobi@hotmail.com '
'''''''''''''''''''''''''''''''''''''''''

'-----------------------------------------
'Here I will implement Direct3D functions
'such as Initializing, Rendering,
'Device autodetection, Device termination
'-----------------------------------------
Option Explicit

Public DX As New DirectX8 'Our main DirectX object
Public D3DX As New D3DX8 'D3DX is a helper library
Public D3D As Direct3D8 'The main Direct3D object
Public D3DDevice As Direct3DDevice8

'Theese values will be used for quick conversions between trigonometrical values
Public Const PI = 3.14159 'Peee :P
Public Const RAD = PI / 180 'Convert to RADIANS
Public Const DEG = 180 / PI 'Convert to DEGREES
'Converting Degrees to Radiants will look like: 45 * RAD will result the value: Pi / 4
'Converting Radians to Degrees will look like: Pi/4 * DEG will result the value: 45
'Don't worry conversions will not be used in this tutorial, but catch up on your Trigo. skills ;)

Public Declare Function GetTickCount Lib "kernel32" () As Long 'Substitute timer object

Dim Dispmode As D3DDISPLAYMODE 'Stores the DisplayResolution, and other information
Dim D3DWindow As D3DPRESENT_PARAMETERS 'Our Direct3D window
Dim DevCaps As D3DCAPS8 'Our Graphics Hardware capabilities
Dim DevIdent As D3DADAPTER_IDENTIFIER8 'The name of our Hardware (graphics card)

Private Type TL_VERTEX
X As Single
Y As Single
Z As Single
rhw As Single
color As Long
TX As Single
TY As Single
End Type
Public Const FVF_TL_VERTEX = (D3DFVF_XYZRHW Or D3DFVF_DIFFUSE Or D3DFVF_TEX1)
Public myObject(0 To 3) As TL_VERTEX
Dim Texture As Direct3DTexture8


Public Function InitD3D(FullSCR As Boolean) As Boolean
'--------------------------------------------------------------'
'Checks device caps. If available, then initializes them. '
'If every initialization was succesfull, true is being returned'
'--------------------------------------------------------------'
On Error GoTo BailOutInit
'On Error Resume Next ' Use this if you want to force the program to start

'> Presentation Parameters
If FullSCR Then
D3DWindow.Windowed = 0
D3DWindow.BackBufferFormat = Dispmode.Format
D3DWindow.BackBufferCount = 1
D3DWindow.BackBufferWidth = Dispmode.Width
D3DWindow.BackBufferHeight = Dispmode.Height
Else
D3DWindow.Windowed = 1
D3DWindow.BackBufferFormat = Dispmode.Format
End If
D3DWindow.hDeviceWindow = frmMain.hWnd
D3DWindow.SwapEffect = D3DSWAPEFFECT_COPY ' D3DSWAPEFFECT_COPY

'> Stencil depth
If D3D.CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, Dispmode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16) = D3D_OK Then
D3DWindow.AutoDepthStencilFormat = D3DFMT_D16
D3DWindow.EnableAutoDepthStencil = 1
Else
D3DWindow.EnableAutoDepthStencil = 0
End If

'> Hardware/Software VP & initialization
Set D3DDevice = D3D.CreateDevice(0, D3DDEVTYPE_HAL, frmMain.hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, D3DWindow)
If D3DDevice Is Nothing Then Set D3DDevice = D3D.CreateDevice(0, D3DDEVTYPE_HAL, frmMain.hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, D3DWindow)


InitD3D = True
Exit Function
BailOutInit:
InitD3D = False
MsgBox "There was an error initializing the graphics engine!", vbInformation
End Function

Public Sub TerminateDirect3D()
'-----------------'
'Unloading objects'
'-----------------'
Set D3DX = Nothing
Set D3DDevice = Nothing
Set D3D = Nothing
Set DX = Nothing
'MsgBox "Ready"
End Sub

Public Function PreCheck() As Boolean
'--------------------------------------------'
'Displays information about graphics adapter,'
'and creates our main Dx Objects. '
'--------------------------------------------'
Set DX = New DirectX8
Set D3D = DX.Direct3DCreate()
Set D3DX = New D3DX8

D3D.GetDeviceCaps D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, DevCaps
D3D.GetAdapterIdentifier D3DADAPTER_DEFAULT, D3DENUM_NO_WHQL_LEVEL, DevIdent
D3D.GetAdapterDisplayMode D3DADAPTER_DEFAULT, Dispmode

Dim a As Single
frmMain.Caption = "> Graphics adapter: "
For a = 0 To 511
frmMain.Caption = frmMain.Caption & Chr(DevIdent.Description(a))
Next a
frmMain.Caption = frmMain.Caption & " / " & "> Screen Resolution: " & " / " & " " & CStr(Dispmode.Width) & "x" & CStr(Dispmode.Height)
End Function


Public Sub Render()
'------------------------------------------------------------'
'The entire rendering of objects, and presentation on screen '
'------------------------------------------------------------'
D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET Or D3DCLEAR_ZBUFFER, &H0, 1#, 0
D3DDevice.BeginScene

D3DDevice.SetTexture 0, Texture
D3DDevice.SetRenderState D3DRS_LIGHTING, 0
D3DDevice.SetVertexShader FVF_TL_VERTEX
D3DDevice.DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 4, myObject(0), Len(myObject(0))

D3DDevice.EndScene
D3DDevice.Present ByVal 0, ByVal 0, 0, ByVal 0
End Sub

Public Function InitGeometry() As Boolean
'On Error GoTo bail
myObject(0) = CreateTLvertex(0, 0, 0, 1, &HFFFFFF, 0, 0)
myObject(1) = CreateTLvertex(320, 0, 0, 1, &HFFFFFF, 1, 0)
myObject(2) = CreateTLvertex(0, 240, 0, 1, &HFFFFFF, 0, 1)
myObject(3) = CreateTLvertex(320, 240, 0, 1, &HFFFFFF, 1, 1)
Set Texture = D3DX.CreateTextureFromFile(D3DDevice, App.Path & "tex.jpg")


InitGeometry = True
Exit Function
bail:
InitGeometry = False
End Function

Public Function CreateTLvertex(mX As Single, mY As Single, mZ As Single, mrhw, mcolor As Long, mtu As Single, mtv As Single) As TL_VERTEX
CreateTLvertex.X = mX
CreateTLvertex.Y = mY
CreateTLvertex.Z = mZ
CreateTLvertex.rhw = mrhw
CreateTLvertex.color = mcolor
CreateTLvertex.TX = mtu
CreateTLvertex.TY = mtv
End Function


Cum ati vazut in primul tutorial vom crea formul si modulul pentru functiile directx. (nu uitati sa dati pe la project>references pentru libraria dx for visual basic)

Prima diferenta o gasim la declararea de variabile in Direct3D.bas .

Citat:

Private Type TL_VERTEX
X As Single
Y As Single
Z As Single
rhw As Single
color As Long
TX As Single
TY As Single
End Type
Public Const FVF_TL_VERTEX = (D3DFVF_XYZRHW Or D3DFVF_DIFFUSE Or D3DFVF_TEX1)
Public myObject(0 To 3) As TL_VERTEX



In primul rand cream o structura numita (de mine) "TL_VERTEX" ("transformed and lit vertex").
Inseamna ca ii vom trimite D3DDevice-ului coordinate finale, si nu e trebuință sa le calculeze el.
Facem acest lucru ca sa fim siguri ca obiectul va fi desenat pe un loc vizibil pe monitor.
In loc de tu si tv i-am dat nume de tx si ty sa fie mai clar. RHW va preciza ca avem o coordinata finala. (va fi 1)
Color este optional, dar mai tarziu va fi important, in particular cand vom vorbi de iluminare.

Pentru fiecare structura de acest tip, se va preciza o constanta numita "Vertex shader".
Vertex shader nu are (aproape) nimic de a face cu umbre (shader is not shadow creator)
Vertex shader este de fapt informatia care ii spune Direct3D-ului cum dorim sa trimitem datele pentru device.
Structura TL_VERTEX poate sa contina si alte date in afara de cele precizate acum.
Fiind ceva flexibil, avem nevoie de o descriere pentru a preciza cum arata de fapt.

Citat:

Public Const FVF_TL_VERTEX = (D3DFVF_XYZRHW Or D3DFVF_DIFFUSE Or D3DFVF_TEX1)



De aici vine si numele: "FVF - Flexible Vertex Format"

D3DFVF_XYZRHW - inseamna coordinatele xyz urmat de rhw
D3DFVF_DIFFUSE - inseamna ca urmeaza o culoare
D3DFVF_TEX1 - inseamna ca urmeaza coordinate de textura (pe inițialul stagiu, despre stagii mai tarziu)

In final putem crea structura noastra. Vom utiliza o matrice de 4 elemente,
pentru ca D3D iti da probabilitatea sa descrii doua triunghiuri cu 4 puncte,
veti vedea la rendering imediat.

Citat:


Dim Texture As Direct3DTexture8



Aici vom stoca textura, pe care o incarcam cu susținerea unei functii din libraria D3DX, mai precis CreateTextureFromFile.

Observati ca avem o functie numita "InitGeometry". Aici vor intra toate procedurile de incarcare a obiectelor.
(De întocmai am facut o functie de utilitate numita CreateTLVertex, ca sa fie codul mai curat)

Citat:

myObject(0) = CreateTLvertex(0, 0, 0, 1, &HFFFFFF, 0, 0)
myObject(1) = CreateTLvertex(320, 0, 0, 1, &HFFFFFF, 1, 0)
myObject(2) = CreateTLvertex(0, 240, 0, 1, &HFFFFFF, 0, 1)
myObject(3) = CreateTLvertex(320, 240, 0, 1, &HFFFFFF, 1, 1)




1 |-----| 2
| / |
| / |
| / |
|/ |
3 |-----| 4

Citat:

Set Texture = D3DX.CreateTextureFromFile(D3DDevice, App.Path & "tex.jpg")



Textura se incarca usor. D3DX are f. numeroase functii de acest gen Smile

Si in sfirsit am ajuns la functia "Render". Sa-l vedem in detaliu.
Cum ati vazut in primul tutorial, functia render incepe cu stergerea cadrului vechi.
Dupa care urmeaza "Begin Scene".

Citat:


D3DDevice.SetTexture 0, Texture


Textura pe care tocmai am creat-o in InitGeometry, este setata pe întâiul stagiul de texturi (stagiul 0).
(despre "texture stages" vom avea un tutorial amanuntit mai tarziu)

Citat:

D3DDevice.SetRenderState D3DRS_LIGHTING, 0


D3DDevice are o procedura numita "SetRenderState" care ne va fi utila,
deoarece se pot specifica detalii despre cum sa deseneze deviceul un anumit obiect.
Incercati sa tipariti manual comanda "D3ddevice.setrenderstate" si apasind tasta space,
veti primi toate constantele posibile. Una din aceste constante este "Lighting"
(D3DRS -> Direct 3D Render State) Asta inseamna ca nu dorim iluminare calculata de device
pentru obiectul care urmeaza sa fie desenat. ("0" inseamna ca obiectul va fi iluminat 100%,
"1" ar insemna calcularea iluminarii obiectului de catre Dx)

Citat:

D3DDevice.SetVertexShader FVF_TL_VERTEX

Prin metoda SetVertexShader, ii spunem Deviceului ce fel de vertexe fvf ii vom trimite.
FVF_TL_VERTEX, cum v-am mentionat mai sus este o constanta prin care descriem verticele noastre.

Iar in sfirsit:

Citat:


D3DDevice.DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 4, myObject(0), Len(myObject(0))


Sa vedem DrawPrimitiveUp in detaliu!

DrawPrimitiveUp ( primitive type, primitive count, vertexstream zero data array, vertex stream zero stride )

Primitive type - D3DPT_LINELIST (cate 2 elemente)
- D3DPT_LINESTRIP (min. 2 element)
- D3DPT_POINTLIST (min. 1 element)
- D3DPT_TRIANGLEFAN (min. 3 elemente)
- D3DPT_TRIANGLELIST (cate 3 elemente)
- D3DPT_TRIANGLESTRIP (min. 3 elemente)

Primitive_Count - cate elemente sa citeasca din matrice.

Vertexstreamzerodataarray - numele cam complicat, de fapt e primul element din matricea noastra Smile

vertex stream zero stride - marimea unui element din matrice. (ex.: Len(myobject(0))

Cum vedeti si pe imaginea atasata LINELIST inseamna ca deviceul urmeaza sa primeasca o lista de cate 2 vertice.
Pentru 6 elemente in matrice, insemana un primitive count de 3, pentru ca daca specifici o lista de 6 elemente,
o linie e alcatuita din cate doua, insemna ca ai specificat 3 linii.

Linestrip inseamna ca oricare punct nou, va fi legat de ultimul din matrice.
Daca ai 2 puncte, deseneaza o linie. Daca mai adaugi un puct, atunci o va conecta de ultimul punct,
si asa mai departe. Primitivecount va fi numarul punctelor.

Pointlist e f. usor: o lista de puncte. Primitive count va fi numarul punctelor.

Triangle list e o lista de triunghiuri. Primitive count va fi numarul punctelor impartit la 3.
Deviceul va desena cate un triunghi din fiecare 3 puncte.

TriangleStrip e exact ca line strip, iar fiecare punct nou, va fi conectat de ultimele 2 puncte din matrice.
Astfel vor fi 3 si va desena un triunghi.
(Tri-strip si Tri-list sunt cel mai des folosite)

Si in sfirsit TriFan: fiecare punct nou va alcatui un triunghi,
cu debutantul punct din matrice, si ultima. "Fan" vine de la "ventilator"
deoarece obiectul desenat va arata ca un fel de ventilator Smile

Incercati sa trimiteti Deviceului on obiect făcut de voi (specificati inca cateva puncte pentru myobject),
si jucati-va cu distincte primitive type-uri. Dar aveti grija la primitive count:
daca nu mai sunt date, si deviceul le cauta, poate cauza diferite anomalii.
(de obicei reprezentate de un system restart Smile )

Cam atat pentru astazi, spor la treaba. Urmatorul tutorial va fi mult mai interesant.
(Vom crea primul nostru cub rotitor!)
Pe curand.


-------------------------------------------

Tutorial written by: Osvath - Boros Robert

Petru reclamatii, sugestii sau altele scrieti-mi: osvathrobi@hotmail.com

PS: (explicatia greseliilor de exprimare: gandesc in lb. maghiara, documentatia dx e in engleza, iar eu scriu romaneste Smile )
Vezi profilul utilizatorului Trimite mesaj privat

Basic primitives and texturing DirectX& VB
 Pagina de start a forumului http://alpha-thema-online.uv.ro » Visual Studio
Nu puteti crea un subiect nou in acest forum
Nu puteti raspunde in subiectele acestui forum
Nu puteti modifica mesajele proprii din acest forum
Nu puteti sterge mesajele proprii din acest forum
Nu puteti vota in chestionarele din acest forum
Ora este GMT + 3 ore  
Pagina 1 din 1  

  
  
 Creaza un subiect nou  Raspunde la subiect  


Fa-ti si tu propriul forum GRATUIT, pe www.myforum.ro
    Powered by phpBB © 2001-2004 phpBB Group. phpBB Skin by Vjacheslav Trushkin.