Home Articles Tutorials Resources About

Tutorial 1 - Initializing Direct3D


By Pieter Germishuys, January 4 2006

What I would like to do with this tutorial is get Direct3D up and running as fast as possible so that we can utilize the goodness of what is Direct3D. With that said I assume that you have some general C# knowledge and a limited knowledge of 3D Graphics. This tutorial is intended to be a starting point for anyone that wants to learn how to program games and 3d applications using .NET and C#.

The huge debate on Render loops and their performance implications has been widely discussed and this tutorial will cover the most recent once from Tom Miller. A Render loop is a method or a series of methods that will be called in an infinite loop so that the application refreshes. In this case we are referring to our window.

What we need to do first is extract the PeekMessage() method from the user32.dll and to do this we need to do some pretty funky stuff which you don't really need to know in detail about now as you are more interested in Direct3D and not how the message pump works in windows applications.
The class will look something similar to this
namespace Xilath.Core
{
? ?internal class NativeMethods
? ?{
? ? ? ?[StructLayout(LayoutKind.Sequential)]
? ? ? ?public struct Message
? ? ? ?{
? ? ? ? ? ?public IntPtr hWnd;
? ? ? ? ? ?public IntPtr msg;
? ? ? ? ? ?public IntPtr wParam;
? ? ? ? ? ?public IntPtr lParam;
? ? ? ? ? ?public uint time;
? ? ? ? ? ?public System.Drawing.Point p;
? ? ? ?}
? ? ? ?[System.Security.SuppressUnmanagedCodeSecurity]
? ? ? ?[DllImport("User32.dll", CharSet=CharSet.Auto)] //import the User32.dll to get the PeekMessage method
? ? ? ? public static extern bool PeekMessage(out Message msg, IntPtr hWnd, uint messageFilterMin, uint messageFilterMax, uint flags);
? ?}
}?
This class will provide us with the needed method called PeekMessage().

Next we will look at creating a simple renderer class that will handle our device and the creation thereof. The class will be simple and straight to the point as this is an introductory tutorial we will only look at setting up the device and graphics theory will be left for a later article/tutorial.

namespace Xilath.Graphics
{
? ?public class Renderer : IDisposable
? ?{
? ? ? ?private Device device;
? ? ? ?private PresentParameters presentParams;
? ? ? ?private bool deviceLost = false;

? ? ? ?///
? ? ? ?/// Direct3D Rendering Device
? ? ? ?///
? ? ? ?public Device Device
? ? ? ?{
? ? ? ? ? ?get { if(device != null) { return device; }
? ? ? ? ? ? ? ? ?else { return null; }
? ? ? ? ? ?}
? ? ? ?}

? ? ? ?///
? ? ? ?/// Renderer Constructor that initializes the direct3d rendering device
? ? ? ?///
? ? ? ?/// Fullscreen: True/False
? ? ? ?/// The Control to Render to
? ? ? ?public Renderer(bool fullscreen, Control control)
? ? ? ?{
? ? ? ? ? ?SetupPresentParams(fullscreen, control);
? ? ? ? ? ?SetupDevice(control);
? ? ? ?}
? ? ? ?///
? ? ? ?/// Setup the Present Parameters
? ? ? ?///
? ? ? ?/// Fullscreen: True/False
? ? ? ?/// The Control to Render to
? ? ? ?public void SetupPresentParams(bool fullscreen, Control control)
? ? ? ?{
? ? ? ? ? ?presentParams = new PresentParameters();
? ? ? ? ? ?presentParams.BackBufferWidth = control.Width;
? ? ? ? ? ?presentParams.BackBufferHeight = control.Height;
? ? ? ? ? ?presentParams.SwapEffect = SwapEffect.Discard; //How the backbuffer and the current display will be swapped
? ? ? ? ? ?presentParams.Windowed = true;
? ? ? ? ? ?if(fullscreen)
? ? ? ? ? ?{
? ? ? ? ? ? ? ?presentParams.Windowed = false; //is the application windowed or fullscreen
? ? ? ? ? ? ? ?presentParams.BackBufferWidth = control.Width;
? ? ? ? ? ? ? ?presentParams.BackBufferHeight = control.Height;
? ? ? ? ? ? ? ?presentParams.PresentationInterval = PresentInterval.Immediate;
? ? ? ? ? ?}
? ? ? ?}

? ? ? ?///
? ? ? ?/// Setup the Direct3D Rendering device
? ? ? ?///
? ? ? ?///
? ? ? ?private void SetupDevice(Control control)
? ? ? ?{
? ? ? ? ? ?device = new Device(0, DeviceType.Hardware, control.Handle, CreateFlags.HardwareVertexProcessing, presentParams);
? ? ? ? ? ?device.DeviceResizing += new System.ComponentModel.CancelEventHandler(OnResize);
? ? ? ?}

? ? ? ?public void BeginRender(System.Drawing.Color backgroundColor)
? ? ? ?{
? ? ? ? ? ?device.Clear(ClearFlags.Target, backgroundColor, 1.0f, 0);
? ? ? ? ? ?device.BeginScene();
? ? ? ?}

? ? ? ?public void EndRender()
? ? ? ?{
? ? ? ? ? ?device.EndScene();
? ? ? ? ? ?device.Present();
? ? ? ?}
? ?}
}

Ok, let's run through this quickly. Basically we have this class that will handle the device. The device is what we will use to render objects to the screen. Think of the device as your tool to use Direct3D. It gives you access to most of the render functions that you will need to render objects using Direct3D.

The constructor takes in 2 parameters. A boolean variable to tell your renderer class whether the device needs to be fullscreen or not. Next is a valid control that will be hooked to your device. This is so that your device can render to a specific control (in this case a window). Next up is the PresentParameters class. This class helps the device with some information as to how you want it to be created such as the width and height of your back buffer.. ahh. this is a new word isn't it. A backbuffer, you can simply think of as a surface that you will render your graphics/scene too before it actually gets displayed.

Next is the 2 methods called BeginRender and EndRender. These methods are very basic and don't handle alot of the needed scenarios that need to be handled but will suffice for this exercise. It simply states that we wish the clear this surface we are rendering too. ClearFlags.Target specifies this. The Present method just tells Direct3D that we are ready to display whatever has been rendered to the surface to the screen.

With these simple classes that we have created we can now simply create a new Form which can be done by going to your solution explorer and add a new Form.
Add the following method to the form

private bool AppStillIdle
{
? ?get
? ?{
? ? ? ?NativeMethods.Message msg;
? ? ? ?return !NativeMethods.PeekMessage(out msg, IntPtr.Zero, 0, 0, 0);
? ?}
}
This is simply a method that will tell us whether the application is idle or not and thus allow us to be able to render the objects we want to while the application is idle. With that said we will need to utilize this variable.

public void OnApplicationIdle(object sender, EventArgs e)
{
? ?while(AppStillIdle)
? ?{
???????//We are going to just instantiate a simple Renderer object or Engine class and implement the
???????//object here and call the needed methods here such as

???????engine.Render();
? ?}
}
In your main method (your application entry point), this can be in your Form or another class you just call and hook your idle event of your window/form to the application.

public static void Main(string[] args)
{
? ? ?XilathWindow window = new XilathWindow(800, 600, "Tutorial 1 - Creating the device");
? ? ?Application.Idle += new EventHandler(window.OnApplicationIdle);
? ? ?Application.Run(window);
}
?

If you have any questions or comments please drop me a mail. I really hope that this is a not too confusing base for anyone to quickly setup a device and get something rendered on the screen.


Files for this tutorial

Filename Size
? tut1.rar 96.6 KB
?
MDX info is an initiative by vector4. All content is copyright ? 2005-2006 by its respective authors | About MDX info | Terms of Use |
Coming soon!