Greg Dolley’s Weblog

A Blog about Graphics Programming, Game Programming, Tips and Tricks

Archive for the ‘.NET Graphics’ Category

Managed DirectX C# Graphics Tutorial 2: Drawing a Triangle

Posted by gregd1024 on February 29, 2008

Now we’re going to look at drawing a triangle with Managed DirectX (MDX 1.1) using C#. The material presented here will strive to be the equivalent of the last tutorial which was in C++.

Requirements

The tutorial sample code was built and tested on Visual Studio 2008 Express. However, the code should work with 2005. You’ll also need the DirectX SDK August 2007 or earlier. I use June 2007 – you can download it with this link.

Tutorial Source and Project Files

To get the finished result of what this tutorial teaches – project files, binaries, and source – use this link:

Getting Started

Everything involved with setting up the project, form, and DirectX will not be covered in this tutorial since it was already explained last time. See the “Managed DirectX C# Graphics Tutorial 1” if you want details on that.

In this post we’re going to take the code from the last tutorial and build off of it. We actually only need to change one function – OnPaint(). If you have the last tutorial’s project open, you can delete the contents of OnPaint. We’re going to replace those lines with stuff from the next section.

Define Vertices and Render

Unlike using DirectX in C++, there’s no need to define your own FVF vertex structure. Managed DirectX has pre-defined vertex types. The one we need to use in order to draw our triangle is represented by the “TransformedColored” struct. This struct is a nested entity inside the CustomVertex class. The CustomVertex class contains many struct’s representing common fixed-format vertex types. Basically, different vertex types that you’d commonly need to create using FVF codes in C++ are already defined by Managed DirectX.

There’s also no need to create a vertex buffer object like you would in native DirectX. You can use the original array of vertices and pass them directly into drawing routines. However, MDX still has the ability to work with vertex buffer objects if you need them.

These two major differences result in very simple drawing code. Drop the following code snippet into OnPaint() and you’re good to go:

CustomVertex.TransformedColored[] vertexes = new CustomVertex.TransformedColored[3];

 

vertexes[0].Position = new Vector4(50, 50, 0, 1.0f);
vertexes[0].Color = System.Drawing.Color.FromArgb(0, 255, 0).ToArgb();

vertexes[1].Position = new Vector4(250, 50, 0, 1.0f);
vertexes[1].Color = System.Drawing.Color.FromArgb(0, 0, 255).ToArgb();

vertexes[2].Position = new Vector4(50, 250, 0, 1.0f);
vertexes[2].Color = System.Drawing.Color.FromArgb(255, 0, 0).ToArgb();

 

m_device.Clear(ClearFlags.Target, System.Drawing.Color.FromArgb(0, 0, 0).ToArgb(), 1.0f, 0);
m_device.BeginScene();        
m_device.VertexFormat = CustomVertex.TransformedColored.Format;
m_device.DrawUserPrimitives(PrimitiveType.TriangleList, 1, vertexes);
m_device.EndScene();
m_device.Present();

The first line creates the vertex array while the next six lines fill in the information at each vertex (position and color). Then Clear() is called to erase the background. BeginScene() starts the 3D drawing code just like in C++. We tell DirectX about the vertex type being used by setting VertexFormat. This must match the vertex array element type. DrawUserPrimitives() takes the vertex array and renders the triangle. Finally we end the scene with EndScene() and show everything on the screen with Present(). What could be easier?

Full Listing

Since using .NET makes the text of this application so small, I’m going to list all the code here for your convenience. 🙂

using System;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

 

namespace MDX_Tutorial2
{
   class MainClass:Form
   {
      private Device m_device = null;

 

      MainClass()
      {
         this.Text = “Managed DirectX Tutorial 2”;
      }

 

      void InitGraphics()
      {
         PresentParameters present_params = new PresentParameters();

         present_params.Windowed = true;
         present_params.SwapEffect = SwapEffect.Discard;

 

         m_device = new Device(0, DeviceType.Hardware, this,
                               CreateFlags.SoftwareVertexProcessing, present_params);
      }

 

      protected override void OnPaint(PaintEventArgs e)
      {
         CustomVertex.TransformedColored[] vertexes = new CustomVertex.TransformedColored[3];

 

         vertexes[0].Position = new Vector4(50, 50, 0, 1.0f);
         vertexes[0].Color = System.Drawing.Color.FromArgb(0, 255, 0).ToArgb();
         vertexes[1].Position = new Vector4(250, 50, 0, 1.0f);
         vertexes[1].Color = System.Drawing.Color.FromArgb(0, 0, 255).ToArgb();
         vertexes[2].Position = new Vector4(50, 250, 0, 1.0f);
         vertexes[2].Color = System.Drawing.Color.FromArgb(255, 0, 0).ToArgb();

 

         m_device.Clear(ClearFlags.Target, System.Drawing.Color.FromArgb(0, 0, 0).ToArgb(), 1.0f, 0);
         m_device.BeginScene();        
         m_device.VertexFormat = CustomVertex.TransformedColored.Format;
         m_device.DrawUserPrimitives(PrimitiveType.TriangleList, 1, vertexes);
         m_device.EndScene();
         m_device.Present();
      }

 

      static void Main()
      {
         MainClass MainForm = new MainClass();
         MainForm.InitGraphics();
         Application.Run(MainForm);
      }
   }
}

Program Output

Now for the fun part. What does running the program look like? Here’s a screenshot:

managed_directx_tutorial_2_ouput

Look familiar? If it does, good. We set out to create the C# .NET equivalent of the C++ tutorial and did exactly that. If it looked different from last time, then we’d have a problem.

Conclusion

I hope you’ve gained insight into the differences and similarities of native DirectX versus Managed DirectX. If you have any questions or comments, please don’t hesitate to email me or leave a comment on this post.

Thanks for reading! 😉

-Greg Dolley

*Get new posts automatically! Grab the RSS feed here. Want email updates instead? Click here.

Posted in .NET Graphics, 3D Graphics, DirectX | 8 Comments »

Managed DirectX C# Graphics Tutorial 1: Getting Started

Posted by gregd1024 on February 26, 2008

I’m going to demonstrate the same principles as my last post (DirectX 9 C++ Graphics Tutorial 1), how to fill a form with a solid color – except this time it’ll be in .NET using C# and Managed DirectX (MDX 1.1). MDX 1.1 is meant to expose most of the functionality as native DirectX 9.

Requirements

Everything in this tutorial is based on Visual Studio 2008 Express.

You’ll also need the DirectX SDK. You can download it from Microsoft’s site with this link. Note that this is the June 2007 release. I purposely didn’t link to the latest (November 2007 at the time of this writing) because Microsoft has removed the Managed DirectX samples and documentation from that release. If you read my last post, then you know that Microsoft has moved MDX’s functionality into the XNA framework, but threw out all features which were not simultaneously supported by both Xbox and Windows.

Tutorial Source and Project Files

To get the finished result of what this tutorial teaches – project files, binaries, and source – use this link:

Download C# Sources and Binaries [~10k]

Step 1: Create and Setup Your Project

We’re going to start from absolute scratch – that means no wizards and no auto-generated code. So start out by creating an empty C# project. You can name it whatever you like and place it in any directory.

Now add the following references:

  • Microsoft.DirectX
  • Microsoft.DirectX.Direct3D
  • System
  • System.Drawing
  • System.Windows.Forms

Go into your project settings and change the output type from “Console Application” to “Windows Application.”

managed_directx_tutorial_1_project_settings

Add one source file called “main.cs” (actually, you can use a different name but I’m going to refer to this file as “main.cs” throughout the tutorial).

Step 2: Create the Form

Inside “main.cs” you’re going to add the following “using” statements:

using System;

using System.Windows.Forms;

using Microsoft.DirectX;

using Microsoft.DirectX.Direct3D;

To make the form, copy the following code snippet and paste it directly underneath the “using” statements:

namespace MDX_Tutorial1
{
   class MainClass:Form
   {
      MainClass()
      {
         this.Text = “Managed DirectX Tutorial 1”;
      }

 

      static void Main()
      {
         MainClass MainForm = new MainClass();
         Application.Run(MainForm);
      }
   }
}

Step 3: Create the Device Object

Just like the previous post’s C++ example, you’ll have to create a device object. Since we’ll be accessing this object in multiple functions, it must be a class member variable. Add the following declaration inside “MainClass”:

private Device m_device = null;

Also add a method called “InitGraphics()” – this is where we’ll create and initialize the device object. The initialization code is only a few lines:

void InitGraphics()
{
   PresentParameters present_params = new PresentParameters();
  

   present_params.Windowed = true;
   present_params.SwapEffect = SwapEffect.Discard;
  

   m_device = new Device(0, DeviceType.Hardware, this,

                         CreateFlags.SoftwareVertexProcessing, present_params);
}

First, we create the “PresentParameters” object. This object describes how DirectX should behave in our application. We want the application to be a window and we’ll let the device handle the back buffer (“Windowed” and “SwapEffect”). Next, we actually create the device. There are several overloads for the constructor of “Device” but the one we’re interested in takes five arguments as described below:

  • Parameter 1: “int adapter”
  • Parameter 2: “DeviceType deviceType”
  • Parameter 3: “Control renderWindow”
  • Parameter 4: “CreateFlags behaviorFlags”
  • Parameter 5: “params PresentParameters[] presentationParameters”

For the adapter we used “0” since this designates the default. We chose hardware rendering as opposed to software emulation. Our main application class is also our render target form (hence the “this” keyword). We wanted software vertex processing instead of hardware calculated transforms. Lastly, we passed in our “present_params” object as the fifth parameter.

Now we must call “InitGraphics()” from somewhere. Add the following line in “Main()”:

static void Main()
{
   MainClass MainForm = new MainClass();
   MainForm.InitGraphics(); // <— ADD THIS LINE
   Application.Run(MainForm);
}

Step 4: Draw on the Form

In order to draw on the form we must override the “OnPaint()” function. In this function we use the “m_device” member to call “Clear()” and “Present()” like this:

protected override void OnPaint(PaintEventArgs e)
{
   m_device.Clear(ClearFlags.Target,
                  System.Drawing.Color.FromArgb(0, 0, 255).ToArgb(), 1.0f, 0);
   m_device.Present();
}

The “Clear()” function fills one or more buffers with a single value. The first parameter specifies which buffer, or series of buffers, to fill. It can be the rendering target buffer (Target), depth buffer (ZBuffer), or stencil buffer (Stencil). You can specify more than one by combining their values via a bitwise “OR” operation. The second parameter specifies what color to use in clearing the render target surface. In our case we chose blue. The third parameter specifies what value to use for clearing the depth buffer. Lastly, the fourth parameter specifies what value to use for clearing the stencil buffer.

The “Present()” function displays everything to the screen. It is equivalent to calling the C++ version with four NULL parameters.

Run the Program!

Our first managed DirectX program is done! Now compile and run the program. You should see output similar to this:

managed_directx_tutorial_1_output

Conclusion

While this program is rather boring, in the next tutorial we’ll cover how to draw a 2D triangle with different colored vertices.

-Greg Dolley

*Get new posts automatically! Grab the RSS feed here. Want email updates instead? Click here.

Posted in .NET Graphics, C# Programming, DirectX | 35 Comments »