Jump to content
Xtreme .Net Talk

Recommended Posts

Posted (edited)

I will be making a set of 5 or 6 tutorials, each of which include source for Visual Basic.NET 2002 and Visual Basic.NET 2003. C# tutorials may or may not follow. These tutorials are to give you guys a jumpstart to some Direct3D. I hope you enjoy these.

 

edit: ARGH! Font got screwed up on this one. Stupid thing doublespaces it automatically. The source code got 'squished' together. I patched up as much of it as possible. Please bear with me, but the source code is fully commented and follows along with this tutorial - so it might be better to paste from there rather than here.

 

This tutorial will teach you how to display a textured quad(square).

 

In this tutorial we're going to get into some hardcore definitions as we move along.

 

Well the first thing you need to know:

 

What's the simplest polygon? A triangle of course! This is why Direct3D constructs all of its shapes from triangles. A square is 2 triangles of course (draw a diagonal line from corner to corner and voila). This is how we're going to construct our square in this tutorial.

 

We'll get into more terminology as we move along.

 

Create a new project. Copy the same GameClass as the previous project ("Initializing The Device"), and use the same Form1 code as before.

 

For this tutorial, we're going to make an adjustment here which we'll discuss in the next tutorial(dealing with Matrices/Transformations). Go to your GameClass (in your new project), and at the very end of the Initialize sub, type this in:

 

D3Ddev.Transform.View = Matrix.OrthoOffCenterLH(0, DP.Width, DP.Height, 0, 0, 10)

 

 

Again, don't worry about this line in this tutorial, I'll explain more in the next tutorial.

 

Create a new class called clsSprite and at the top, Import the 3 DLLs which you usually import:

 

Imports Microsoft.DirectX

Imports Microsoft.DirectX.Direct3D

Imports Microsoft.DirectX.Direct3D.D3DX

 

 

Dim the following global variables in your class.

 

 

'Holds a copy of the device to be used in the class

Private dxDevice As Device

'Holds the image that will be drawn onto the square

Public SpriteImage As Texture

'This is the buffer in which the vertices of the square will be stored

Public vBuffer As VertexBuffer

 

Create a contstructor:

 

Public Sub New(ByVal lDevice As Device, ByVal ImageName AsString, ByVal TopLeft As Point, ByVal Width As Integer, ByVal Height As Integer)

 

'Store a copy of our device in the class

dxDevice = lDevice

'Load the image, we specify the arguments that we need to create a square

Load(ImageName, TopLeft, Width, Height)

 

EndSub

 

Don't worry about the error, we're going to create a Load sub in a minute http://www.xtremedotnettalk.com/x_images/images/smilies/smile.gif.

 

First, a quick note: We can create a square given the TopLeft coordinate. the Width, and the Height. It works like this:

 

TopLeft = (TopLeft.X, TopLeft.Y)

TopRight = (TopLeft.X + Width, TopLeft.Y)

BottomLeft = (TopLeft.X, TopLeft.Y + Height)

BottomRight = (TopLeft.X + width, TopLeft.Y + Height)

 

With some simple sketches, you'll realize that this holds true.

 

Now its time to do some hardcore coding.

Create a sub called Load:

 

 

Public Sub Load(ByVal ImageName As String, ByVal topleft As Point, ByVal width As Integer, ByVal height As Integer)

 

The next thing we're going to do is talk about Direct3D Vertices.

 

The thing about these vertices is that they are different from Math vertices.

A D3D Vertex can hold various proprties. Some of it includes

Position - Just like a math vertex

Color - .. yes, color, vertices can hold colors

Texture - you can place an image on top of the vertices

Normal - Stuff to do with lighting

 

In our case, we want our vertices to hold the Position and the Texture.

 

So in the Load sub,

 

'Declares an array of vertices that will make up the square.

Dim Vertices() As CustomVertex.PositionTextured

 

Now we have to set the texture:

 

'SpriteImage will hold our .. Image :D.

SpriteImage = TextureLoader.FromFile(dxDevice, ImageName)

 

-----

Now for a quick note. We know that a square is composed of 2 Triangles. That means that we'd need 6 vertices (3 per triangle) to make up a square! Nope ;0, thank goodness Direct3D has a way around it. Later in our code, we're going to set the PrimativeType (Primitiave means Triangle). The primitave type specifies how our shape will be creative. The 2 most common PrimativeTypes are:

 

PrimativeType.TriangleList - Using this method, we'd have to create 6 vertices for a square

 

PrimativeType.TriangleStrip - Using this method, we only need 4 triangles per square.

 

Take a look at these links from MSDN, they have pictures with explanations to help you understand what this is all about.

 

TriangleList - A triangle list is a list of isolated triangles. They might or might not be near each other. A triangle list must have at least three vertices. The total number of vertices must be divisible by three.

TriangleStrip - A triangle strip is a series of connected triangles. Because the triangles are connected, the application does not need to repeatedly specify all three vertices for each triangle.

 

So when we create our square, it is better to use a TriangleStrip. This way, There are 3 vertices (TopLeft, TopRight, BottomLeft) for the triangle - and D3D senses that 4th vertex (BottomRight) is "alone" and connects that vertex with the TopRight and BottomLeft. Thus, I opted to use a TriangleStrip to save memory.

 

 

 

-Splitting post into 2 to overcome character limit

Edited by ThePentiumGuy

My VB.NET Game Programming Tutorial Site (GDI+, Direct3D, Tetris [coming soon], a full RPG.... you name it!)

vbprogramming.8k.com

My Project (Need VB.NET Programmers)

http://workspaces.gotdotnet.com/ResolutionRPG

Posted (edited)

The next thing to do is instantiate our VertexBuffer:

 

vBuffer = New VertexBuffer(GetType(CustomVertex.PositionTextured), 4, dxDevice, Usage.WriteOnly, CustomVertex.PositionTextured.Format, Pool.Default)

'GetType(CustomVertex.PositionTextured) - This VertesBuffer will hold CustomVertex.PositionTextured vertices

'4 - It'll hold 4 vertices (4 vertices make up a square right)

'dxdevice - It'll use this device

'Usage.WriteOnly - We're only going to write to the buffer, not read from it

'CustomVertex.PositionTextured.Format - DirectX is retarded and wants the argument again? Can't think of an explanation for this :).

'Pool.Default - Specifies how we want to handle the memory pool. Woah we're not going to mess with this so we'll let Direct3D choose how it wants to handle the memory.

 

 

 

Before setting the vertex positions and such, we need to lock the vertex buffer. If we don't lock the buffer - it can lead to memory problems.

 

'Lock the buffer before use.

'The reason for the equal sign is basically, you're telling the Vertices

'to store/accept its data into the buffer

Vertices = vBuffer.Lock(0, LockFlags.None)

'0 - Lock the entire buffer. Any number greater than 0, you're only going to lock that offset in bytes

'LockFlags.None - Just lock it.. whatever, don't specify any more options

 

Imagine the vBuffer as a row of data going from left to right

 

<0123456789>

 

The offset specifies how much you want to lock it. For example, since we specified 0, we're going to lock the entire buffer. If we specified 6, we'd lock:

 

<6789>.

 

The next thing we're going to discuss is Tu and Tv. They essentially specify what corner of the texture goes where. Tu and Tv are written like coordinates.. for example (tu,tv).

Here's a quick example of how tu and tv work:

 

A tu,tv of (0,0) would be the topleft of the square.

 

A tu,tv of (1,1) would be the bottomright of the square.

 

You'll understand more as we go along.

 

Now that we've locked it, we're going to tell the vertices where they are!

 

'Set the vertices. The arguments are written like (X,Y,Z,tU,tV)

'We set its Z to 1 so that it appears "Forwards" a bit. Setting a Z to 0 would make it too close to the screen. Setting a Z of like.. 8 would make it too far

'View the tutorial for more information on how all this works

 

'TopLeft

Vertices(0) = New CustomVertex.PositionTextured(topleft.X, topleft.Y, 1, 0, 0)

 

'TopRight

Vertices(1) = New CustomVertex.PositionTextured(topleft.X + width, topleft.Y, 1, 1, 0)

'BottomLeft

Vertices(2) = New CustomVertex.PositionTextured(topleft.X, topleft.Y + height, 1, 0, 1)

'BottomRight

Vertices(3) = New CustomVertex.PositionTextured(topleft.X + width, topleft.Y + height, 1, 1, 1)

 

So now you see how tu,tv work? Let's recap. The first line (where you set Vertices(0)) has a tu,tv of (0,0). That means that the top left of the texture goes on that vertex. Vertices(2) has a tu,tv of (0,1), that means that the bottomLeft of the texture goes on that vertex. Btw, the 0's and 1's work like X and Y coordinates.

 

 

 

(0,0) = TopLeft

(0,1) = TopRight

(1,0) = BottomLeft

 

(1,1) = BottomRight

 

I'm sure you understand the other arguments (for X and Y, the Z argument is explained in the comments).

 

 

 

The last line in the load sub:

 

'Unlock the buffer - we're ready to render this thing ;D

vBuffer.Unlock()

 

Now its time to create a Render sub:

 

PublicSub Render()

 

'Sigh, set the vertex format AGAIN :).

dxDevice.VertexFormat = CustomVertex.PositionTextured.Format

 

'We're going to draw whatever is in the buffer.

dxDevice.SetStreamSource(0, vBuffer, 0)

 

'0 - StreamNumber. Saying 0 draws all the [memory] streams (meaning vertices) in the buffer

'vBuffer - Draws the content of our VertexBuffer

'0 - Offset. Draws the entire content of the buffer

 

'Draw the texture over the square we've just drawn.

dxDevice.SetTexture(0, SpriteImage)

'0 - Refers to the TextureStage(?)

'SpriteImage - The image we draw on our quad

 

'Draw our shape

dxDevice.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2)

'PrimitiveType.TriangleStrip - We draw using a TriangleStrip as opposed to a TriangleList

'0 - Our startvertex is 0 (remember the Vertices() array, the first vertex is Vertices(0))

'2 - The PrimitiveCount.. meaning 2 Triangles("Primitives") :).

EndSub

 

Heh, I hope you've understood that - it's all in the comments ;D. Basically you:

 

Set the vertices

Set the texture over the vertices

 

Draw the textured box.

 

Now go back to GameClass, in the globals,

 

Dim Alex As clsSprite

 

At the end of the Initialize sub:

 

Alex = New clsSprite(D3Ddev, "down1.bmp", New Point(0, 0), 32, 32)

 

In between BeginScene and EndScene:

Alex.Render()

 

Run it! :). You should see the sprite of your choice rendering. Err.. not really. You have to turn off lighting (do this at the end of the Initialize sub):

 

'Our object is so close to the screen that the lighting conflicts with its visibility,'making it appear black, so we disable lighting.

 

D3Ddev.RenderState.Lighting = False

 

That's it for this tutorial, the next one will be about Matrices/Transformations

 

The source code below is compatible with both 9.0a and 9.0c. VB.NET 2002 users shouldn't have a problem with this source. VB.NET 2003 users can easily convert by opening the file and clicking OK when it asks. Mods, the exe was removed from the bin and obj folders.

TexturingAQuad.zip

Edited by ThePentiumGuy

My VB.NET Game Programming Tutorial Site (GDI+, Direct3D, Tetris [coming soon], a full RPG.... you name it!)

vbprogramming.8k.com

My Project (Need VB.NET Programmers)

http://workspaces.gotdotnet.com/ResolutionRPG

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...