Welcome to this tutorial on 3D programming with VB. I hope you are already
familiar with Visual Basic and its Synthaxes. Anyways, this tutorial will only
cover a part of the DirectX libary, the 3D part also known as Direct3D.
Instead of Direct3D you could also use OpenGL, but i sugest you use DirectX.
:) Well, DirectX wasn't always accessable by Visual Basic, only since version 7.0
was released, Visual Basic programmers could use the power of DirectX. It has
many useful things, like DirectPlay, for Multiplayer or DirectSound, for Sounds.
Before you can use DirectX in VB, you have to reference it, by selecting "Project"
from the menu, then click on "Reference" and in the list, scroll down to "DirectX
8 for Visual Basic Type Libary", and select it.
Now Let's start, by creating the main Object for DirectX, the DirectX8 object:
Dim DX as DirectX8
From this object we can control alot of things in the DirectX world. But since we
are using Direct3D, we have to declare this too, and while we are at it, we will
declare another essential part of Direct3D, the Direct3D-Device, which stands for
the hardware, that renders all the 3D stuff.:
Dim D3D as Direct3D8
Dim D3DDevice as Direct3DDevice8
we have now declared our Main Objects, now we will have to "create" them. :)
Public Function Init(hWnd As Long) As Boolean 'This function will return false if it failed
On Error GoTo ErrHandle 'Just to be on the safe side.
Set DX = New DirectX8 'We could have done this earlier by declaring
'Dim DX as New DirectX8, but this would be
'a bit slower.
Set D3D = DX.Direct3DCreate() 'Here we create our Direct3D Object
If D3D is Nothing Then GoTo ErrHandle 'if D3D = Nothing that means it wasn't created
Dim Mode As D3DDISPLAYMODE 'This variable is only temporarly to find our
'display mode
D3D.GetAdapterDisplayMode D3DADAPTER_DEFAULT, Mode
'This fills our Mode Variable with the Display
'mode
Dim D3Dpp as D3DPRESENT_PARAMETERS 'Another temporary Variable to store our
'Present Parameters (like how everything will
'be displayed)
With D3Dpp
.Windowed = 1 '1 = True, for now we will display everything
'in a window ;)
.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC 'This is how the BackBuffer will be 'Swapped'
'With the Screen.
.BackBufferForemat = Mode.Format 'This is the Format of the Backbuffer (the color
'format) we could have typed it in manually, but
'this way we will be safer ;)
End With
Set D3DDevice = D3D.CreateDevice(D3DADAPTER_DEFAULT, _ 'Finally we create our D3DDevice.
D3DDEVTYPE_HAL, hWnd, _ 'HAL = Hardware, REF = Software rendering
D3DCREATE_SOFTWARE_VERTEXPROCESSING, D3Dpp)
'We give it the Present Parameters, and how it
'will Process the Vertices, this can be done
'with Hardware or Software.
If D3DDevice = Nothing then GoTo ErrHandle
Init = True
Exit Function
ErrHandle:
Init = False
End Function
Now we have Created all Necessary Objects, it is time, i show you how to use them.
Or at least how one would render a scene:
Public Function Render()
D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET, &H0&, 1#, 0 '&H0& is the color the Screen will
'have while it is empty.
D3DDevice.BeginScene
'Between these 2 Functions come the Rendering
'calls and stuff.
D3DDevice.EndScene
D3DDevice.Present ByVal 0, ByVal 0, 0, ByVal 0 'This will 'Swap' the Backbuffer with the
'Screen
End Function
If you would now Initialise all Objects and Render the Scene, you would end up with a
Black Screen. let's try it out ;)
Private Sub Form_Load()
Me.Show 'If we don't do this, nothing will be shown
'on the form, untill all commands in the Form_Load()
'sub have been executed.
DoEvents 'This gives the Computer to do whatever he needs to
'do
If Init(Me.hWnd) = False then 'We could also pass it the handle to a PictureBox
MsgBox "Error initialising the Objects" 'This is only called when the Init() function didn't
'work.
End
End if
Render 'And of course, the Render call.
End Sub
Now we have got us a blank Screen. Wow. well we don't want this, we want shapes.
And that is what we will do next. Direct3Ds most simplest "shapes" or what we will call
them now, Polygons, are Triangles. Each Triangle needs 3 Points to represent where it is
in space. Direct3D allows us a simple way to create triangles and to store them. If
we have a Array of Vertices, we can pass them to something called a Vertex-Buffer,
which can then easily Render them. The Vertex Buffer needs some Information tough, about
how the Triangles are arranged, with this i mean, if we just pass it triangles, or we want
to create a triangle "fan" which uses less Vertices, which means it uses less Memory, but
at least 2 Triangles have to share 1 Vertex. There are also Triangle Strips, which work
similarly. Anyways, we have to declare our Vertexbuffer as well, like we did with our
other Objects:
Dim VB as Direct3DVertexBuffer8
And like the other Objects, we have to Set this one as well. But before we can set it, we
need Vertices. (At least 3 :)). DirectX doesn't have a predefined Vertex, so the user
has alot of flexebility in choosing what it's Vertices can do. For new we will just
use a Vertex with a Coordinate and a color. Before we can use them, we have to Create them
;) :
Public Type CVERTEX
position as D3DVERTEX
color as Long
End Type
Public Const D3DFVF_CVERTEX = (D3DFVF_XYZ Or D3DFVF_DIFFUSE)
You can call the Vertex what you want. The constant is important to show what the Vertex
can do. Let's say we have an Array of Vertices already, stored as Vertices(1 to 3) and
now we want to fill them into the Vertexbuffer, here is how we do it:
Public Function ReloadVB()
Dim VSize as Long 'This is the size of one Vertex in Bytes.
VSize = Len(Vertices(1)) 'Here we pass the size of one Vertice to our Variable.
Set VB = D3DDevice.CreateVertexBuffer(VSize * 3, 0, D3DFVF_CVERTEX, _
D3DPOOL_DEFAULT) 'This will Create a VertexBuffer with enough memory
'for our 3 Vertices. The First Param tells it how
'much memory we need. :)
D3DVertexBuffer8SetData VB, 0, VSize * 3, 0, Vertices(1) 'And now we Set our Data. The First Param
'Is were we want our Vertices to go, the 3 tells
'it the size again, and the Last Param tells it where
'to start.
End Function
Now all we need to know is how to Render the Triangles, and we would be able to write a
fully functioning game. :)
Now back to our Rendering function. Between BeginScene and EndScene, we will have to add
Following code, to normally render our Triangles stored in the VertexBuffer:
Dim V as CVERTEX
Dim VSize as Long
VSize = Len(V)
D3DDevice.SetStreamSource 0, VB, VSize 'This sets the VB from where the next Vertices
'will be coming.
D3DDevice.SetVertexShader D3DFVF_CVERTEX 'We need to let Direct3D know what Vertexshader
'to use.
D3DDevice.DrawPrimitive D3DPT_TRIANGLELIST, 0, 1 'This draws a Triangle list, starting with Vertex 0
'and drawing 1 Primitiv.
Well, that is all one needs to know about making a game with non-textured polygons :)
For textured Polygons, we have to change our Vertex declaration a bit, and our FVF.
Public Type CVERTEX
position as D3DVERTEX
color as Long
tu as Single
tv as Single
End Type
Public Const D3DFVF_CVERTEX = (D3DFVF_XYZ Or D3DFVF_DIFFUSE Or D3DFVF_TEXTURE1)
The Tu and Tv describe the Textures position on the Triangle. Tu and Tv must be a number between
0 and 1.

First thing we do now is we Declare a Object to hold our texture.
Public Texture As Direct3DTexture8
Now, like before, we will have to create it from a File, a image file to be exact ;).
Set Texture = D3DX.CreateTextureFromFile(D3DDevice, App.Path + "\texture.bmp")
That wasn't all to hard, was it? D3DX is only an Object that has many useful functions
but we haven't declared it yet.
Public D3DX As D3DX8
Set D3DX = New D3DX8
and now we did. This Object has alot of useful functions, like texture loading and so on.
Now, to use our Texture, we only have to add a command to our Rendering Function:
D3DDevice.SetStreamSource 0, VB, VSize
D3DDevice.SetVertexShader D3DFVF_CVERTEX
D3DDevice.SetTexture 0, Texture 'This will set the texture the D3DDevice will
'use to render all Triangles, until you select a new
'texture.
D3DDevice.DrawPrimitive D3DPT_TRIANGLELIST, 0, 1
I suggest that at the end in your Init Function you add following line:
D3DDevice.SetRenderState D3DRS_ZENABLE, 1
Without this, your game will not be fully 3D. There are many great things you can do
in DirectX. We haven't coverd one important thing. Matrices. As you most likely have noticed
that if you start the program at it's current state, nothing will be displayed. There are 2
very important Matrices. One is the View Matrices, which describes the Position of the Viewer
and what he is looking at. The second one is the Projection Matrix, which describes, how all
objects are rendered. Here is a simple function which creates these 2 Matrices:
Public Function SetupMatrices()
Dim EyePosition as D3DVECTOR, EyeLookAt as D3DVECTOR, UP as D3DVECTOR
Dim matView As D3DMATRIX
EyePosition.Z = -10 'Our Viewer is Standing 10 "steps behind" the 0-Offset
'We don't change EyeLookAt, because we want to look at
'point 0,0,0.
UP.Y = 1 'This describes what way is up.
D3DXMatrixLookAtLH matView, EyePosition, EyeLookAt, UP 'This creates the View Matrix for us.
D3DDevice.SetTransform D3DTS_VIEW, matView 'And here we set it.
Dim matProj As D3DMATRIX 'now our Projection Matrix
D3DXMatrixPerspectiveFovLH matProj, 3.14159275180032 / 3, 1, 1, 1000 'If you change the pi/3 part,
'you can create special effects, like zooming.
'the last parameter describes how far we can look.
D3DDevice.SetTransform D3DTS_PROJECTION, matProj 'And, of course, we set the Matrix.
End Function
This are all the important things you need to know about programming with DirectX. To rotate
the camera, you just have to change the EyeLookAt Vertex, and reload the Matrices. You do not
have to reload the Matrices every round, only when you want to change them ;).