Creating a Window and Rendering a Blank Screen
Since we are going to be rendering inside a window, I thought the best place to start would be with that class. To create this initial class, right click on your 3D engine project and choose Add-New Item-Windows Form and name it. I am using HMSystem, since this is part of the Hazy Mind engine, and it will be our main system class for initializing Direct3D.
Go into the code of the main form by right clicking it in the solution explorer and choosing View Code. Before we add any code that relies on DirectX, we need to add references to it in the References section of the project. Right click on References and choose Add Reference. Scroll down and add Microsoft.DirectX and Microsoft.DirectX.Direct3D. Now we can start coding!
Step 1: Creating and Initializing the Device
The first thing we need to do is create the device we will use to render with and initialize it. In the using section at the top of the code add these statements:
using Microsoft.DirectX; using Microsoft.DirectX.Direct3D;
At the top of your system class add these variables:
private Device myDevice; private PresentParameters presentParams;
Now, we need to think about the different settings we will want to be able to control when we first create our system. One of the most important things I can think of for this stage of creation is the size and windowed mode of our engine. We want to be able to specify whether our window is fullscreen or not, and if not, what size to make it. We probably also want to give our window/demo a name, so let’s add that too. To make these settings easy to get at later, lets add some variables to the class, and put them into the constructor so we can specify them at creation time:
private bool isWindowed; public HMSystem(int width, int height, bool windowed, string name) { InitializeComponent(); // This is already here for window creation isWindowed = windowed; this.Name = name; this.Text = name; this.Size = new Size(width, height); this.ClientSize = this.Size; if(!windowed) this.FormBorderStyle = FormBorderStyle.None; // If fullscreen, remove window borders // This will save us grief later // this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true); }
Now that we have all of the information we need to create our device, lets write the function we will use to do exactly that:
private bool InitializeGraphics(){ // We specify bool so we can catch failures try { // This first group of settings applies to both windowed and fullscreen modes presentParams = new PresentParameters(); presentParams.Windowed = isWindowed; presentParams.SwapEffect = SwapEffect.Discard; if(!isWindowed) { presentParams.BackBufferFormat = Manager.Adapters[0].CurrentDisplayMode.Format; presentParams.BackBufferCount = 1; presentParams.BackBufferWidth = Manager.Adapters[0].CurrentDisplayMode.Width; presentParams.BackBufferHeight = Manager.Adapters[0].CurrentDisplayMode.Height; presentParams.FullScreenRefreshRateInHz = Manager.Adapters[0].CurrentDisplayMode.RefreshRate; presentParams.PresentationInterval = PresentInterval.Immediate; } myDevice = new Device( 0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams ); } catch(DirectXException) { MessageBox.Show(”Unable to initialize Direct3D”); return false; } return true; }
Ok, we have the function to create our device. Now let’s write the function that will make our device do things (namely rendering):
// These parameters are required to use this as an addition to the Paint delegate of the Form private void Render(object sender, PaintEventArgs e) { myDevice.Clear(ClearFlags.Target, Color.CornflowerBlue, 1.0f, 0); myDevice.Present(); this.Invalidate(); // This will tell the window to redraw immediately when it finishes each frame }
With these functions completed let’s add calls to them where appropriate so their functionality actually gets used. In the constructor, at the very bottom, add a call for InitializeGraphics(); To get the Render() function to be called continuously, we will add it to the Paint delegate of the Form. In the constructor, below the SetStyle call, add this:
this.Paint += new PaintEventHandler(Render);
That’s it! Our form is ready to create a Direct3D device and render to the screen with it. Since we are creating this engine as a class library, let’s move on to the main application part of the demo and write a Main() class to start and run this.
Step 2: Creating the Main() class of the Demo Program
Start out by adding a new class to the demo project by right click its name and choosing Add-Class… Name it whatever you want and click Add. Before we can create the objects we need from our engine library, we have to add a reference to it in the same way that we added references to the DirectX libraries. Right click on the project title and choose Add Reference. From the tabs at the top select Projects and add the project listed there (our engine project.) Now you can delete the namespace line and corresponding brackets and the existing constructor code and add this code:
using System.Windows.Forms; using HMEngine; static HMSystem demo1 = new HMSystem(800, 600, true, “Hazy Mind 3D Engine Demo Application”); [STAThread] public static void Main() { demo1.Show(); Application.Run(demo1); }
All done! Now you should be able to run this Direct3D application in windowed or fullscreen mode just by changing the windowed parameter in the constructor. If you want to close the demo in fullscreen mode, just do a simple Alt+F4. Stay tuned as we continue our delve into the world of Managed DirectX.