DirectX8 is a frightening thing for the amateur game designer, mostly because, unlike its older brother DX7, it doesn’t have a 2D API. Even people who are trying to move straight from DirectX7 are having troubles. I’m no exception, so I’m documenting my attempt to learn the 3D API and how to use it to it’s full potential, and I’m going to show you all in the form of a series of tutorials.
So where do you start your new DirectGraphics project? Well, as stupid as it sounds, from the beginning.
DirectGraphics draws its images through a device, which is comparable to a car driver... the driver can drive pretty much any car, even though almost every car may have a small difference. The DirectGraphics device can use pretty much every 3D video card, but they all have their minor differences.
You haven’t closed the window yet? Shock! Okay, well first of all, let’s make 5 declarations which will control the objects and running of the program. Put these wherever you want, but for the demo app, they’re in a form.
Dim objDX As DirectX8 |
objDX is the object that is the root of all DirectX8 commands, DirectGraphics will be created from this object later and NO DirectX8 projects can be made without it, it’d be like trying to use VB without windows installed on your computer (I’m under the impression the VB6 CD isn’t bootable...)
objDG is the object that controls the operation of DirectGraphics. It’s extensively called Direct3D, but I’ve adopted calling it DirectGraphics because that’s what Microsoft call it in their SDK. This object will be responsible for creating the device.
devDG is a DirectGraphics device, which is responsible for the rendering of any image.
DGInited helps us keep a track of whether or not the initialisation of DirectGraphics was successful.
ProgramExiting will let our rendering loop stop when the user closes the program.
Okay then! That’s all cute and furry?
Open up the form’s code, and select Form_Load from the methods
Now then, we’ll start by making it display the form because it won’t have a chance to until the rendering loop starts.
Private Sub Form_Load() |
*Yawn* hehe, you didn’t need to know that did you?
Okay, well, declaring objects is one thing, but they’re useless until you actually set them to something, So we’ll start at the top and work down, lets first set an new instance of DirectX8 (We don’t want it using another program’s DirectX do we now? that could get messy...)
Set objDX = New DirectX |
Okay, now let’s leave the Form_Load for a little bit and do something a little more interesting, ie, our initialisation function :)
As with every good function, let’s start with our declarations and some code to trap errors
Function D3Dinit() as Boolean |
udtCurrentMode will display all the info regarding the screen’s current display mode, the bit depth, the width and height, etc, etc, etc… We’ll need this because it’s got the information we need to make the backbuffer (somewhere to draw that won’t get seen until it’s finished, this stops flickering) udtPParam is where we’ll provide DirectX the data it needs to display the graphics to the user
The last line will cause the program to fail if any part bombs out.
Set objDG = objDX.Direct3DCreate |
okay, now the first thing we need to do is create the DirectGraphics object, because it won’t really know how to behave if it’s not initialised. That’s what the first line does.
The second line calls the method .GetAdapterDisplayMode that gets all the information available for a particular device. The only reason we’re getting this is so we can get the pixel format, (how many bits of red, green and blue) so that the backbuffer will match. You wouldn’t need to call this on a full-screen application because you’ll be specifying the pixel format yourself.
The method is thus:
object.GetAdapterDisplayMode(Adapter As Long, Mode As D3DDISPLAYMODE) |
The next five lines fill the user defined type udtPParams with the information that will be required to fulfil a .present request (the command that displays the rendered graphic)
.Windowed will tell the graphics device that the program is windowed where 1 = true, and 0 = false. I don’t recommend setting this to True, because I have had troubles (True is actually -1) |
object.CreateDevice(Adapter As Long, DeviceType As CONST_D3DDEVTYPE, hFocusWindow As Long, BehaviorFlags As Long, PresentationParameters As D3DPRESENT_PARAMETERS) As Direct3DDevice |
Sigh coor, that one was a mouthful. Did I confuse anybody? I don’t know how to make it any simpler than that... sorry guys.
The next line just simply says, if you couldn’t create the device, drop out and give a Macintosh error (you know, one of those ones that isn’t very descriptive that nobody can figure out)
And if the device was created, everything was successful, so set the function to true (Success) and exit.
Lastly, we’ll do the very short and undescriptive error checking
ErrorCheck: |
This one is pretty simple, if it reaches this, then set the function to return False (Failure) and exit the function.
Okay! That’s the initialisation all over and done with! Now we’ll head back to the Form_Load function and pick up where we left off okay?
Set objDX = New DirectX8 ‘this is where we left |
Okay, first of all, we’ll call the function we just created and store the result in DGInited.
If DGInited is false, then something went wrong in the initialisation. The correct way of doing this is to actually declare D3Dinit() as a long, not a Boolean, then you can spit back some useful information to the user. Unfortunately, I’m writing this tutorial very late at night, and I couldn’t be bothered putting in the correct error checking (But hey... this is the basic code and should work on all computers... if this doesn’t work, you must have mistyped something.
Once you’ve given them their Macintosh error, end the program because it just won’t work.
Now let’s finish off the Form_Load subroutine
Me.Caption = "Create Device" |
the first line is pretty explanatory, we’ve finished initialising, so lets not delude the user.
Next, lets set up a loop, and the first thing we’ll do is clear the viewport (the section of screen the user can see)
We’ll use the devDG.Clear method. This will clear a number of rectangles which you can put in an array. However, if no rectangles are specified, it will clear the entire viewport. The .Clear method looks a little something like this:
object.Clear(Count As Long, ClearD3DRect As Any, Flags As CONST_D3DCLEARFLAGS, Color As Long, Z As Single, Stencil As Long) |
Okay, next we see two commands, devDG.BeginScene and devDG.EndScene these two commands are issued when you’re about to start rendering polygons to the device. You can’t do it outside of these methods. Unfortunately, this tutorial is all about creating the device, not using it. So there is nothing between there for now.
The last thing we need to do is to .Present the information to the user. Easy? I doubt it... this is DirectGraphics we’re talking about. So here we have the description of the devDG.Present command:
object.Present(SourceRect As Any, DestRect As Any, DestWindowOverride As Long, DirtyRegion As Any) |
Next we’ll let the user click on the close button if they want to close (as we’re sure they will, I don’t think anybody really wants to stare at a blue screen... there are plenty of other ways that can be much more interesting to them...
Now we’ll end the loop, and if the user has clicked on the close button, we’ll exit the loop and end the program.
Phew that’s it for the rendering loop. Nothing to it huh? At least, nothing to it when you understand it all...
Now I do think there is something I’ve forgotten. Oh yeah... what’s going to happen when the user tries to close the program? the variable still won’t be set to close! let’s fix that and some potential memory leaks...
Private Sub Form_Unload(Cancel As Integer) |
All we’re simply doing is destroying the two DirectGraphics components we created and setting our ProgramExiting Boolean to true.
It’s that simple.
Go on. Run it. I dare you.
Voila! a beautiful DirectGraphics blue screen. (Or a GDI Blue screen of death, depending on whether or not you were paying attention hehe)
Okay, so please don’t hit me. You’ve just wasted how long trying to create a blue screen? Yeah I know... But there is a lot that is hard to understand, so I’m trying to make it idiot proof (My apologies to all the idiots that might be out there reading this)
Well, that’s it, I’m going start researching now how to actually DRAW a triangle next. This ought to be interesting...
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