|
The Device
Everything in
Direct3D centers around the Device. The device is an objects which
communicates with the Graphics Card and tells it to render (draw)
your objects.
The first step to creating any Direct3D application is Initializing
the Device - you have to get it ready for some drawing!
Create a new project called Direct3D Initialization.
Reference:
Microsoft.DirectX
Microsoft.DirectX.Direct3D
Microsoft.DirectX.Direct3DX
(You reference the DLL's by going to the Solution Explorer (all the
way to the right), and right clicking References and Add Reference.
Control click the references to select multiple ones)
Now create a new class called GameClass. This class will be the
center of your application
At the very top of the code, type these 3 lines:
Imports
Microsoft.DirectX
Imports
Microsoft.DirectX.Direct3D
Imports Microsoft.DirectX.Direct3D.D3DX
Why are we importing? So that we can declare the variables easily!
Here's an example. Soon, we're going to say Dim D3DDev as Device. If
we didn't import DirectX and Direct3D, we'd have to say Dim D3DDev
as Microsoft.DirectX.Direct3D.Device. This just helps us save some
time while coding ;p.
We're going to declare 3 more variables: the Device, the
PresentationParameters, and the Displaymode.
The Device will be the object that 'talks' to our graphics card, it
is the main control of our direct3D application.
The PresentationParameters are basically how we're going to present
our program to the user (you'll see what I mean when we code)
The Displaymode is... well, our display mode!
__________________________
Declare the following variables.
Private D3Ddev
As Device = Nothing
'Short for
PresentationParameters
Private D3Dpp As PresentParameters = Nothing
Private DP As DisplayMode = Nothing
Now we're going to create a function to initialize our device, this
gets the device ready for some action!
Create a new sub:
Public Sub
Initialize(ByVal TargetForm As Form, ByVal FullScreen As Boolean)
End Sub
The first argument takes in the form that we're going to draw to.
The 2nd argument tells us whether we're going to do this in
fullscreen or windowed.
Now add the following code to the sub.
If FullScreen
Then
'800x600
Resolution
DP.Width = 800
DP.Height = 600
'R5G6B5 =
16-bit. Visit MSDN to find out what the other ones are.
DP.Format = Format.R5G6B5
Else
'If it's
not fullscreen, use the current display mode!
DP = Manager.Adapters.Default.CurrentDisplayMode
End If
I'm sure you guys understand most of that :).
The only tricky part is the Format.R5G6B5.
Format.X8R8G8B8 is 32-bit mode. Format.R5G6B6 is 16-bit mode.
Visit
this site for help on what each Format does.
The next thing to do is set up your PresentationParameters.
'As usual, we
must always instantiate our classes
D3Dpp = New PresentParameters()
'Initialize some
stuff for the Presentation parameters
D3Dpp.BackBufferFormat = DP.Format
D3Dpp.BackBufferWidth = DP.Width
D3Dpp.BackBufferHeight = DP.Height
What's the backbuffer you ask? The backbuffer is what Direct3D draws
to. D3D draws to the backbuffer, and then takes the content of the
backbuffer and draws it to the screen.
We need to set up more flags for the Presentation Parameters.
'There's flip,
copy, and discard. Flip and Discard are used most often. Visit MSDN
has more information.
D3Dpp.SwapEffect = SwapEffect.Discard
'Present the
scene immediately
D3Dpp.PresentationInterval = PresentInterval.Immediate
Ok - let me explain. Swapeffect is a flag which basically tells
Direct3D how to go from one frame to another.
SwapEffect.Discard - This flag deletes the old frame and draws a new
one on top of it. Great preformance.
SwapEffect.Flip - Not sure what this does, but it provides the
greatest compatibility compatibility for FullScreen and Windowed
Swapeffect.Copy - The new frame is simply copied on top of the old
one. This is the most simple of the backbuffer swap operations, but
it is the one with the worst performance.
"In particular, the Flip swap effect operates the same whether
windowed or full-screen, and the Direct3D runtime guarantees this by
creating extra buffers. As a result, it is recommended that
applications use Discard whenever possible to avoid any performance
penalties, because the current swap effect is always the most
efficient in terms of memory consumption and performance."
"An application can use the Discard swap effect to avoid overheads
and to enable the display driver to choose the most efficient
presentation technique for the swap chain."
- From the DirectX Help file.
Thus, I'd recommend you use Discard, typically for FullScreen apps,
although flip is common as well. Please consult MSDN for more help
as I am not 100% sure on what each does.
Now to explain PresentationLevel.Immediate. Basically it means
present the scene immediately when its drawn. It doesn't have to
wait for other stuff to happen before presenting - just present
immediately. Gets the most FPS out of your game ;).
The next few lines are simple.
'Set to
Fullscreen or Windowed
If FullScreen Then
D3Dpp.Windowed = False
Else
D3Dpp.Windowed = True
End If
Ah cmon, no need to explain here.
The next line will be a bit tricky though.
'Instantiate the
device
D3Ddev = New Device(Manager.Adapters.Default.Adapter,
DeviceType.Hardware, TargetForm.Handle,
CreateFlags.SoftwareVertexProcessing, D3Dpp)
Here's an explanation of the arguments
Manager.Adapters.Default.Adapter - Use the current display
driver: the one that's displaying your desktop right now
DeviceType.Hardware - If you've worked with GDI+, you'll know
how slow software devices are
TargetForm.Handle - Draw to the form
CreateFlags.SoftwareVertexProcessing - Processing vertices
with Software (Direct3D) is safer than processing it with your
hardware. This is because different graphics cards may process them
differently. You want it to be processed the same universally, so
you let Direct3D do the work.
D3Dpp - Well, use the presentation parameters!
We're done with this sub!
__________________
Now its time to do some rendering.
Here's what a basic rendering loop would look like:
Do While Not GameOver
Clear
BeginScene
RenderTheObjects
EndScene
Present
End While
We're going to do just that. In your GameClass globals,
Public GameOver
As Boolean
Create a new sub:
PublicSub
RenderScene()
End Sub
Add the following code to it:
Do While Not
GameOver
'Try
commenting this out . You'll see what it does. It might hang your
app depending on your graphics card. In DX 9.0a, the screen would
flash in multiple colors if you didn't clear, this, you want to
clear it with one color (see explanation below)
D3Ddev.Clear(ClearFlags.Target, Color.FromArgb(0, 0, 225), 0, 0)
D3Ddev.BeginScene()
' Rendering code goes here usually. But we're not rendering
anything in this program. So don't type anything here.
D3Ddev.EndScene()
D3Ddev.Present()
'In a
loop, keyboard events are ignored. This means: let them NOT be
ignored :).
Application.DoEvents()
Loop
___________
Wow. That was kind of simple right? I just have to explain the
D3DDev.Clear.
ClearFlags.Target - Clear the form, our "target"
Color.FromArgb(0, 0, 225) - Clear it with this color (Dark
blue)
0 - ZDepth. Our app isn't 3D yet, so don't waste memory on
ZDepth (Z = 3D)
0 - Stencil. Has to do with the advanced topic of Stenciling.
We're not going to do that, so just set it to 0.
Now we're going to create a Terminate sub.
Public Sub
Terminate()
'Free up
mem
DP = Nothing
D3Dpp = Nothing
D3Ddev.Dispose()
D3Ddev = Nothing
'Exit
Application.Exit()
'FORCE an exit if it
didn't exit already.
System.Environment.Exit(System.Environment.ExitCode)
End Sub
At the very end of RenderScene, type in
Terminate().
This insures that when GameOver = True, the application will
terminate.
Wow - we're done with GameClass! It has 3 basic parts: Initialize,
Render and Terminate, simple right? Now it's time to put this
program into some action.
_________
Go back to form1.
Type in
Dim Game As
GameClass
In the form1_load event, type in:
'We have to say
Me.Show becuase the form doesn't actually get shown until AFTER the
load event.
'Try emptying this sub, and type in MessageBox.Show("Hi"). Notice
how
'the MessageBox appears *before* the form shows up?
Me.Show()
'As usual, we
must always instantiate our classes
Game = New GameClass()
'Initialize the
game
'Me - Render to form1
'True - Use fullscreen
Game.Initialize(Me, True)
Game.RenderScene()
Now go to form1_keydown.
Type this in.
If e.KeyCode =
Keys.Escape Then
Game.GameOver = True
End If
Now, it's time to run your app! Before doing so, save all of your
work, just in case it crashes. You should get a blue screen :o.
That's it for this tutorial. The source code is compatible with VS.
NET 2002. 2003 users will find it easy to open it and hit 'ok' when
it asks to convert :)
(I hope that the files don't get corrupted from now on, because I'm
uploading attachments for this section)
The source
code for this tutorial can be found
here.
You can also locate this by
logging in to vbProgramming Forums and going to:
Tutorials
> Tutorial Source Code > Source Code |