Greg Dolley’s Weblog

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

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.

Advertisement

8 Responses to “Managed DirectX C# Graphics Tutorial 2: Drawing a Triangle”

  1. Robert said

    There is an error here to do with the vertices. Each should be changed to:-

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

    While I am here, can I suggest to others working through this tutorial (which I think is excellent) that you can experiment with values, inputting values into the running application by doing the following.

    1. Create a standard C# windows application.
    a. in the window add a ‘Panel’ (in the example below it’s name is ‘panelDraw’)
    b. Now you can add textboxes and values around this and a Button to redraw with new values (include an information box so that you can feed back infortion on values to yourself).
    2. As stated in the first tutorial add refferences for DirectX and DirectX3d
    3. Add ‘using’ statements at the top of your source.
    using Microsoft.DirectX;
    using Microsoft.DirectX.Direct3D;
    4. Add the device to the class
    private Device m_device = null;

    Example
    namespace graphclassws
    {
    public partial class Form1 : Form
    {
    private Device m_device = null;
    public Form1()
    {
    InitializeComponent();
    InitGraphics();
    }

    private void InitGraphics()
    {
    PresentParameters present_params = new PresentParameters();
    present_params.Windowed = true;
    present_params.SwapEffect = SwapEffect.Discard;
    //panelDraw is our Panel control
    m_device = new Device(0, DeviceType.Hardware, panelDraw, CreateFlags.SoftwareVertexProcessing, present_params);

    }

    …..rest of class ….

    So using code up to the second in greg’s tutorial our trigger button may look like this.

    private void btnFindPointOnLine_Click(object sender, EventArgs e)
    {
    //clear our device surface
    m_device.Clear(ClearFlags.Target, System.Drawing.Color.FromArgb(0, 0, 255).ToArgb(), 1.0f, 0);
    //create array of vertexes
    CustomVertex.TransformedColored[] vertexes = new CustomVertex.TransformedColored[3];

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

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

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

    //draw our surface
    m_device.BeginScene();
    m_device.VertexFormat = CustomVertex.TransformedColored.Format;
    m_device.DrawUserPrimitives(PrimitiveType.TriangleList, 1, vertexes);
    m_device.EndScene();
    m_device.Present();
    }

    This helps you to work along through these tutorials, and experiment with the running code.

    • gregd1024 said

      Robert – hmmmm, maybe DirectX changed this in your version, but mine works fine just by setting the Position property directly. Thanks for the additional code.

      -Greg

  2. Till said

    Robert uses an older DirectX version !

  3. shome24 said

    Dear All,

    I don’t have “vector4” object in my system,
    which dll can I download to get it?

    Shmuel

  4. Jay said

    Read your Tutorial, getting this result: http://a00.img-up.net/?up=strangeo9j6d.jpg

    MS Visual C# 2010
    MS DirectX SDK June 2010

    Wtf is this? No Warnings or Errors while compiling…

  5. Ram Raddhakrishnan said

    Thank you for a clearly written, handy tutorial.
    It has just the right ingredients to satisfy my impatience – a bit of linear algebra as it relates to 3D transforms, just enough C++ and sufficient C#. I could not have asked for a more balance recipe!.

  6. Jens said

    Thank you for your Tutorial πŸ™‚
    I’m a german student, but i understand your tutorial very well, i was searching a long time for a good tutorial, but now i found one πŸ™‚

    But on your 1st tutorial i have to say that your code only run @Net. Framework 3.5, maybe you can add this @beginning so other beginners hasn’t this problem

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

 
%d bloggers like this: