DirectX Graphics
Part 2- Creating vertices

         Still with me huh? Mebbe my last tutorial wasn’t so boring after all, or is it that you just want to make DirectXGraphics actually do something huh? Heh, whatever the cause, unfortunately, there’s a LOT more theory in this one, and less code...

         First of all, for the sake of those who don’t know, I’m sure you’ll want to know what a vertex (plural vertices) even is!

         Well, to put it in it’s simplest terms, a vertex is a point in 3D space. For instance, the planet earth could be a vertex, the sun another, and pluto the third. This is all we really need to make the simplest kind of polygon possible. A triangle. Yes, now we’re going to write an addition to our original code to make it render a single triangle.

         When you’re dealing with DirectX however, a vertex can have more properties than just an X, Y, and Z location. It also can have a Normal, which tells us which way it’s facing, and a colour value. There are other possibilities, but for the purpose of these tutorials, these are all we’ll be using.

         Now... when you’re creating vertices, you can either let DirectX transform (slide the vertex up and down, back and front) and light (colour the vertex) itself, or choose to do them yourself.

         Unfortunately, transformation (The basis of 3D animation) and lighting is a little more advanced than you’re probably ready for, those are actually for parts 3 and 4, so keep with us. In the meantime, we’re going to take the simple way and do it all ourselves. Doing it ourselves means we don’t need to define a light in 3D space and we won’t need to find out where the camera is in order to actually show it.

         Right! That’ll do for the theory for now :) what we’re going to do next is create a FVF, a Flexible Vertex Format. Because there are soooo many possibilities to how vertices are created, DirectX lets us make out own Vertex Formats, which I think is pretty cool.

         So open up a copy of your tutorial from before (or the same copy if you’d like...) and right up the top, let’s add in our user defined type-FVF

Private Type typUDVertex
        x as Single
        y as Single
        z as Single
        rhw as Single
        color as Long
End Type

Dim objDX as DirectX8 ‘existing line

         Okay, so first of all, our vertex will have an X component on the screen, a Y component on the screen, a Z theoretical position, this will always be a value between 1 and 0 (Depending on how the window is defined and it’s actual position in 3D space) the vertex will either be facing towards the user, or away from them, and lastly, a 32-bit colour.

         No problems? I should hope not! :) This is only the start.

         Next we’re going to edit our objects declarations and add in our vertex buffer to the list.

Dim devDG as Direct3DDevice8

Dim bufVertex as Direct3DVertexBuffer8

DGInited as Boolean

         And lastly in the declarations, a constant which will tell our DirectXGraphics device how our FVF is set out!

Dim ProgramExiting as Boolean

Const fvfUDVertex = (D3DFVF_XYZRHW or D3DFVF_DIFFUSE)

Private Sub Form_Load()

         Okay, that was pretty quick and painless huh? Well, just to confuse you, I’m going to explain how the hell you define your vertices and what the hell those two constants we "or"ed together do.

         [D3DFVF_XYZRHW]
         Tells DirectX the position of the vertex, i.e., it’s pre-transformed and DirectX won’t do the sliding to compensate, please note that you can’t use this constant with [D3DFVF_XYZ] or [D3DFVF_NORMAL] constants (These will hopefully be explained in another tutorial)
         [D3DFVF_DIFFUSE]
         Tells DirectX that the FVF contains a 32-bit colour in it as well, so it’s pre-lit as well.

         Easy? Well, now that we’ve set up our program for our new vertices, let’s initialise our Vertex Buffer and set up a triad of vertices huh? In the demo tutorial, I’ve placed it just after the D3DInit function, just for clarity, but it doesn’t matter where you put it...

End Function

Function VBInit()
         On Error GoTo ErrorCheck
         Dim Vertices(2) As typUDVertex
         Dim VertexSize As Long

         VertexSize = Len(Vertices(0))

         Vertices(0) = CreateVertex(150, 50, 0.5, 1, &HFF0000FF)
         Vertices(1) = CreateVertex(250, 250, 0.5, 1, &H80FF8080)
         Vertices(2) = CreateVertex(50, 250, 0.5, 1, &HFF00FF00)
         Set bufVertex = devDG.CreateVertexBuffer(VertexSize * 3, 0, fvfUDVertex, D3DPOOL_DEFAULT)

         Call D3DVertexBuffer8SetData(bufVertex, 0, VertexSize * 3, 0, Vertices(0))

         VBInit = True
         Exit Function

ErrorCheck:
         VBInit = False
End Function

Private Sub Form_Unload(Cancel as Integer)

         Okay, that’s a pretty simple initialisation function compared to the DirectXGraphics initialisation... and three times easier to explain too Phew.
         The very first line is a familiar error checking line, if an error occurs in any DX calls, it’ll bomb out with an error message.

         Next we’ve got two declarations,
         Vertices(2) Which is a FVF, and is where we will temporarily store our vertices until they are passed into our Vertex Buffer.
         VertexSize, which in a second will have the size of one array element placed in it. Since when we place the information in the vertex Buffer, it’s going to want to know how much information it’s going to be able to grab. Like giving a blind man his food. He’ll get angry at you if he’s expecting a three course meal and you just give him a bowl of Jelly (Jello for you americans/canadians :P)

         The next line is where just that happens, we grab the (Len)gth of one element and place it in VertexSize. That lines a no-brainer.

         The next three lines take some vertex data and put it into our little vertex array. For those of you who tried to run the program would probably have noticed that "CreateVertex" isn’t defined. That’s because that’s a small function I wrote to simplify things. We’ll make that in two seconds.
         Basically, we’re just passing into each "vertices" element an x, y, z, rhw, and colour, as we specified in our FVF.

         Okay, now we’ve got another of those weird DirectXGraphics methods... This line actually creates the Vertex Buffer into something usable, and it’s going to want to know a couple of things.

         object.CreateVertexBuffer(LengthInBytes As Long, Usage As Long, FVF As Long, Pool As CONST_D3DPOOL) As Direct3DVertexBuffer8
         object is an object which relates to a Direct3DDevice8 object (devDG in this case).
         LengthInBytes tells DirectXGraphics how much info you’re passing to it. It will be the length of one element multiplied by the number of vertices you’ve defined.
         Usage gives DirectXGraphics a bit of information about the buffer itself, how it will be allocated memory, how it can be accessed, and how the vertices will be processed. This is a little out of the scope of this particular part of the tutorial.
         FVF is the constant you defined earlier which tells the Vertex Buffer how it is to store every vertex within the buffer.
         Pool is an advanced topic, it’s used to tell DirectX where about in memory it’s going to store the information, for this tutorial, we use [D3DPOOL_DEFAULT] but Microsoft says that most applications will end up using [D3DPOOL_MANAGED] because all devices can use it, and it can be locked for direct access, [D3DPOOL_SYSTEMMEM] places the data in system memory which is hidden from the 3D devices, information can be locked from this too. The reason why [D3DPOOL_DEFAULT] is impractical for most programs is that it cannot be locked, and when it is textures being pooled, you can’t edit the textures directly, which is a handy ability at times.

         Okay, I hope the basic parts of that, (not the pooling stuff and usage) are understandable. Pretty much you’d use 0 for the usage, and either D3DPOOL_DEFAULT or D3DPOOL_MANAGED as the pooling.

         Anyway, back to the topic, our last major line, is the line which submits our buffer data to our brand new vertex buffer.

         D3DVertexBuffer8SetData(VBuffer As Direct3DVertexBuffer8, Offset As Long, Size As Long, Flags As Long, Data As Any) As Long
         Vbuffer is a Vertex Buffer, relating to a Direct3DVertexBuffer8 object which is to receive the vertex array.
         Offset tells the vertex buffer, where in the buffer the information is being placed. This number is in bytes.
         Size tells the vertex buffer how much data is being passed into it.
         Flags tells DirectXGraphics how the vertex buffer is to be locked while it’s being written, this is a little out of this tutorial’s range, perhaps in the more advanced parts I might cover advanced memory management and cover this...
         Data is the start of the array which contains the data, always pass to it the array’s first element, i.e., Vertices(0)

         The next line just says, if no errors occurred, then it was successful, so set the function to true (Successful) and exit the sub.
         Following that is the error checking code, where, if an error was raised, set the function to false (Failed) and exit the sub.

         Right, now that we’ve gotten the initialisation off the ground let’s get rid of that nasty function not defined...

End Function

Private Function CreateVertex(x, y, z, rhw, colour) As typUDVertex
         With CreateVertex
                  .x = x
                  .y = y
                  .z = z
                  .rhw = rhw
                  .color = colour
         End With
End Function

Private Sub Form_Unload(Cancel as Integer)

         This function is pretty easy to comprehend, basically what we’re doing, is passing parameters to a with statement. Which is storing the information as the functions return. Basically this means you’re saving yourself about 15 lines of code. And makes it easier to read, which is always important.
         It’s very important to note that if you ever decide to use a function like this in your own programs, you’ll need to change it to reflect the FVF that you use... if you don’t use un-lit vertices, you don’t need the .color line, because it won’t exist in the FVF...

         Having said that, let’s head back into our Sub Form_Load and put in our initialisation commands and declarations we’ll need for the next bit:

Private Sub Form_Load

         Dim tempVertex As typUDVertex
         Dim VertexSize As Long

         VertexSize = Len (tempVertex)

         Me.Show
         Me.Caption = "Create Device: Initialising"
         Set objDX = New DirectX8

         DGInited = D3Dinit()
         If DGInited = False then
                  MsgBox ("Critical Failure initialising DirectXGraphics")
                  End
         End If


         DGInited = VBInit()
         If DGInited = False Then
                  MsgBox ("Critical Failure initialising Vertex Buffer")
                  End
         End If

         Me.Caption = "Creating Device"

         This is almost exactly the same as the one just above it calling the D3DInit function, except that it’s got a different Error message.
         On a small unimportant note, feel free to change the name of your new project, because you’re creating vertices in this one, not devices.

         Only two things left now, drawing the graphics on the screen, and cleaning up after ourselves...
         I didn’t explain the top three lines which we added, they were to help us render our picture, since when we’re rendering the vertices, it will need to know once more how big the elements are. So we’ve declared a single element and a variable to store the size, followed by the third line actually working out the size of the element.
         Now, time to paint! Remember in the last tutorial, I pointed out that all rendering must be done between a .StartScene and a .EndScene? Well, let’s start coding between them.

                  devDG.BeginScene
                           Call devDG.SetStreamSource(0, bufVertex, VertexSize)
                           Call devDG.SetVertexShader(fvfUDVertex)
                           Call devDG.DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1)
                  devDG.EndScent

         Goodie, three new DirectXGraphics commands to explain! The first two are Incredibly simple to explain.
         .SetStreamSource simply tells the DirectXGraphics device where its going to get the vertex information from. I suppose they call it a stream because it’s like a streamer (a party ribbon), where you could write a long line of text on It and everything you wrote would be one after the other.

         object.SetStreamSource(StreamNumber As Long, StreamData As Direct3DVertexBuffer8, Stride As Long)
         object is an object relating to a Direct3DDevice8 object (devDG in this case).
         StreamNumber creates an identity for the stream, this makes it very easy to do numerous renders in very few lines of code and lets you effortlessly switch between different vertex buffers.
         StreamData is an object relating to a Direct3DVertexBuffer8 and is your old vertex buffer which holds your vertices.
         Stride tells the steam how much information just ONE vertex has.

         Next we have the .SetVertexShader which just tells the DirectXGraphics device, what the FVF is.

         object.SetVertexShader(VertexShaderHandle As Long)
         object is an object relating to a Direct3DDevice8 object (devDG in this case).
         VertexShaderHandle is where you would pass a Vertex Shader, vertex shaders control the loading and processing of vertices. But you can also pass to it a FVF instead, which is what we’ll be doing.

         And lastly, the .DrawPrimitive method. This actually renders a vertex buffer from a screen onto the backbuffer. It has a few options that will take a little to explain, specifically the part about the primitive type.

         When Drawing Primitives, you can render them in a number of different ways, you can render by points, called a point list, and looks something like this:

Point List
         When you define your point list, it must be defined from left to right, or clockwise (it would be clockwise if you moved all the points upwards till it made an arc…. Otherwise the normals would be backwards and the vertices will be facing the wrong way. Point-lists are great for doing star-fields or pixel plotting. You can define a point list by declaring your primitives type to be [D3DPT_POINTLIST]

         Next we have line lists. These are singular lines joined by only two vertices, for example:

Line List
         Again, these must be declared clockwise, and are best used for effects like rain or, string or something along those lines (Bad pun)
         Line lists are defined by [D3DPT_LINELIST]

         Thirdly, we have line stips. Similar to Line lists, this is one continuous line which turns at each vertex:

Line Strip
         While these have no practical use that I can think of, they’re almost like a wireframe (But that is really done by a triangle list). None the less, again, defined clockwise you can select a line strip via [D3DPT_LINESTRIP]

         Next we have Triangle lists, which turns 6 points into two separate triangles:

Triangle List
         Having a large number of these as a wall, with vertices emitting lights would look somewhat like a force field, as you could see between the triangles. You can select a Triangle List using [D3DPT_TRIANGLELIST]

         Two more to go. Triangle Strips, also known as a wireframe, these give users a detailed look at what exactly they are looking at:

Triangle Strip
         This will also help you debug your graphics if there is a glitch somewhere (I don’t think the developers of Descent 3 did this correctly… Either that or they stuffed up with their Z-Buffer, which we’ll get into later). Anyway, select one of these via [D3DPT_TRIANGLESTRIP]

         Finally, we have the triangle fan, which looks like one of those Japanese fans which we all probably have made as children:

Triangle Fan
         You could use something like this to render a set of twirling stairs. Select this one using [D3DPT_TRIANGLEFAN]

         Okay, hopefully now you’ll have an idea of what DirectX Primitives are and what they can do. Having explained that, let’s have a look at the .DrawPrimitive Command Syntax.

         object.DrawPrimitive(PrimitiveType As CONST_D3DPRIMITIVETYPE, StartVertex As Long, PrimitiveCount As Long)
         object is an object relating to a Direct3DDevice8 object (devDG in this case).
         PrimitiveType tells DirectXGraphics what kind of primitives you’re creating, selecting from the list above.
         StartVertex tells DirectXGraphics which Vertex is the first one to be rendered. Rending an entire buffer requires this to be 0.
         PrimitiveCount tells DirectXGraphics how many primitives it is to draw. A primitive is ONE unattached, set of vertices. In the examples above, the point list has 7 primitives, the line list has 3 primitives. The line list, like the triangle strip and triangle fan, only have one primitive, and the triangle list has 2.

         No Problems! We could run the program now... But we’ve left an open opportunity for a memory leak, so lets finish off out shut down subroutine...

Private Sub Form_Unload(Cancel as Integer)
         Set bufVertex= Nothing
         Set devDG = Nothing

         Woo hoo! We’re done for the second part. Now I know this part won’t be as boring as you’d first thought, because when you run this program, you’re not just going to get a boring triangle. It would be a boring triangle if we were using lighting from DirectX, but we’re not. We’ve coloured every vertex and instead we've got a tripping interpolated triangle.
         Next we’re going to take out our program’s ability to transform for itself, and work on animation, using DirectXGraphics’s transformation abilities. Starting to get a little more interesting huh?

[Download Source]

Written By
Steven Blom AKA
LynxofCP (Lynx of Central Programming)

         If there is any information here guys that you know that I don’t, or if you find a better way to explaining something please don’t hesitate to E-Mail me at CodeWarrior@octa4.net.au