Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Starting DirectX with Visual Basic .NET

0.00/5 (No votes)
21 Feb 2011 1  
Create a DirectX device and draw some Primitives using VB!

Introduction

I will try in this simple tutorial to introduce you to the world of DirectX through Visual Basic, although I am a beginner of both! I will focus on some errors that you could face, and I will try to explain each step as I know, but it may be better to view MSDN also for more information.

There is some talk about the poor performance and features of managed DirectX, and that when you want to learn DirectX, you should learn the native API using C++ or another low level programming language. OK, that may be true, but if you are a novice (or thick headed!), and don't want to bother learning a low level language first, and you want to have a quick beginning in games programming, Visual Basic is a nice choice.

Also, in Visual Basic, you will generally concentrate more on the program algorithm than on the language syntax.

About the performance issue, that is the last thing you should worry about, with modern video cards, it is usually no problem. Anyway, you can't easily develop games like Metal Gear and Devil May Cry at home; if you want to develop Super Mario classic or the likes, you can use any language.

There is another important point about managed DirectX, it is no longer supported by Microsoft, and Microsoft developed another games library (XNA) which does not support Visual Basic (and will not) so you will be stuck with DirectX 9 and won't be able to develop any further. Although this is very disappointing, with some alternative SDKs like Slim SDK, there is hope, or may be in future Microsoft will change their mind!

Let's Start!

Note: Before you start, you most have DirectX SDK installed on your computer. You can download it from Microsoft's site.

In a new Windows application project, add these references:

  • Microsoft.DirectX
  • Microsoft.DirectX.Direct3D
  • Microsoft.DirectX.Direct3DX

Then import the following:

Imports Microsoft.DirectX
Imports Microsoft.DirectX.Direct3D

Declare this variable in your form class:

Dim device As Direct3D.Device ' this the main DirectX device    
Dim buffer As VertexBuffer    ' don't worry about this now!

The first variable is the device object which will perform the drawing and transforming and all those stuff; to put it simply, it represents your video card.

But how I can create my device object? Just have a look in device Constructor:

Public Sub New(ByVal adapter As Integer, ByVal deviceType As  _
    DeviceType, ByVal renderWindowHandle As System.IntPtr, ByVal _
    behaviorFlags As CreateFlags, ByVal ParamArray presentationParameters() _
    As PresentParameters)  

So many parameters, huh! The first one is your adapter index (if you have more than one). The default adapter number is 0. The second parameter determines the type of your device (software or hardware). After that is your window handle (the third parameter), and some options as the fourth. The last one is the PresentParameters object .

So we most create this object first,

Sub initilizdx()
Dim present As New PresentParameters
'
'
'
End Sub  

and set some properties:

present.BackBufferCount = 1 'the number of backbuffer
 present.BackBufferFormat = Manager.Adapters(0).CurrentDisplayMode.Format
 present.BackBufferHeight = Me.Height
 present.BackBufferWidth = Me.Width
 present.Windowed = True 'If you want full screen set it to 
 'false but you should change other properties so don't try it    
 'till now
 present.SwapEffect = SwapEffect.Discard   

What is BackBuffer?

It is the surface where DirectX directly draws. After the drawing is completed, the drawing will be rendered to the front buffer (screen surface) through a swap chain. This method reduces screen flickering, because the picture will not be displayed in the front buffer until rendering is completed.

The swap chain has three methods: discard, copy and flip. See the explanation of each in MSDN.

Then create our device:

device = New Device(0, DeviceType.Hardware, Me.Handle, _
    CreateFlags.SoftwareVertexProcessing, present)  

and adjust its properties:

device.RenderState.CullMode = Cull.None 

Note: We just set it to None at this time to make it easy for you, but in practice, culling has very important performance implications.

How to Draw using this Device

Before drawing, we must clear the device.

Sub draw_me()
    
    device.Clear(ClearFlags.Target, Color.Black, 0, 0)
    '
    '
    '
End Sub 

This means we cleared device using black color. Then,

device.BeginScene()

'all drawing functions here   
        
device.EndScene()
device.Present()'present to screen 

To see what we have done, add this line in the LoadForm event:

Sub form1(ByVal sender As Object, ByVal e As System.EventArgs)_ 
Handles Me.Load

    initilizdx()
    draw_me()

End Sub 

Press F5 and see what happens. Nothing! That is a silly mistake, you can't draw before the form is shown! So,

Sub DirectX_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles Me.Load
    initilizdx()        
    Me.Show()
    draw_me()
End Sub 

Press F5 again.

blackscreen_screenshot.png

Congratulations!

Set Up Geometry Data

In the beginning, we have declared a variable named buffer as VertexBuffer. The vertex buffer is a place in memory where the system stores vertex data.

So we create our vertex buffer:

Sub creat_vertxbuffer()

    buffer = New VertexBuffer(GetType(CustomVertex.TransformedColored) , _ 
        3, device, Usage.None, CustomVertex.TransformedColored.Format,  _ 
        Pool.Managed)  
    '
    '
    '
End Sub

The type of this vertex buffer is TransformedColored, so our vertices are already transformed and don't need any transformation matrix to be presented. They are also colored, meaning they bear color information. For the moment, don't bother yourself with other parameters and write it as I did!

The second parameter determines the number of vertices in the vertex buffer. It is 3 because we want to draw a triangle.

To set the triangle vertex data, we use a useful group of structures which come with DirectX:

CustomVertex 

Write:

Dim ver(2) As CustomVertex.TransformedColored
'The first point
ver(0) = New CustomVertex.TransformedColored(50, 10, 0, 0, Color.Red.ToArgb)

'and the others

ver(1) = New CustomVertex.TransformedColored(200, 15, 0, 0, Color.Red.ToArgb)
ver(2) = New CustomVertex.TransformedColored(10, 200, 0, 0, Color.Red.ToArgb)

'now set the vertex buffer data:
buffer.SetData(ver, 0, LockFlags.None)    

Return to draw_me and write:

   Sub draw_me()
        device.Clear(ClearFlags.Target, Color.Black, 0, 0)
        device.BeginScene()
        device.VertexFormat = CustomVertex.TransformedColored.Format
        device.SetStreamSource(0, buffer, 0)
        device.DrawPrimitives(PrimitiveType.TriangleList, 0, 1)
        device.EndScene()
        device.Present()

    End Sub 

First, we set device.vertexformat = our_vertex_format. If we didn't, our vertex data would not be read properly by the device, and some data may be lost.

Then set the stream source where the device reads a data stream, and call the DrawPrimitives method.

DrawPrimitives(Primitives_type, start_vertex, number_of_primitives_to_draw)

There are six types of Primitives. Here we chose TriangleList.

In this type, the first three vertices form the first triangle. If you want 2 triangles, you must have 6 vertices. See MSDN for other Primitives types.

Now add this to Form load Event.

Sub DirectX_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles Me.Load
    initilizdx()
    creat_vertxbuffer()
    Me.Show()
    draw_me()
End Sub

The press F5.

firstrender_screenshot.png

Very nice!

Try This

Sub creat_vertxbuffer()
    buffer = New VertexBuffer(GetType(CustomVertex.TransformedColored), 3, _
        device, Usage.None, CustomVertex.TransformedColored.Format, Pool.Managed)
    
    Dim ver(2) As CustomVertex.TransformedColored _
        ver(0) = New CustomVertex.TransformedColored(50, 10, 0, 0, Color.Red.ToArgb)

    ' the difference is here:
    ver(1) = New CustomVertex.TransformedColored(200, 15, 0,0, Color.Green.ToArgb)
    ver(2) = New CustomVertex.TransformedColored(10, 200, 0, 0, Color.red.ToArgb)
    buffer.SetData(ver, 0, LockFlags.None)
End Sub

You expect to see this:

addgreen_screenshot.png

but you do not!

Set the rhw value to 1:

Sub creat_vertxbuffer()
    buffer = New VertexBuffer(GetType(CustomVertex.TransformedColored), 3, _
        device, Usage.None, CustomVertex.TransformedColored.Format, Pool.Managed)
    Dim ver(2) As CustomVertex.TransformedColored
    ver(0) = New CustomVertex.TransformedColored(50, 10, 0, 1, Color.Red.ToArgb)
    ver(1) = New CustomVertex.TransformedColored(200, 15, 0, 1, Color.Green.ToArgb)
    ver(2) = New CustomVertex.TransformedColored(10, 200, 0, 1, Color.Blue.ToArgb)
    buffer.SetData(ver, 0, LockFlags.None)
End Sub 

and run it again.

Also, you can draw a square if you start by drawing 2 triangles, like this:

practise.png

Conclusion

I hope I have taught you something useful. Sorry for my bad English!

If many people are interested, I will write more tutorials, and I will discuss more topics like transforming and other rendering issues.

Thank you.

Note: The project is made using Visual Studio 2008. If you have any problems, just open the Form1.vb file and copy the code to your project after adding references.

History

  • 21st February, 2011: Initial post

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here