How to use OpenGL in .NET

October 24th, 2007

I decided to port a program of mine that uses OpenGL from C++ to C#. I haven’t done any work using OpenGL with C# yet, and this is what I went through to get started.

The first place to look for OpenGL help is usually NeHe. He has a bunch of tutorials for various OpenGL features, plus some good frameworks to get started. And sure enough, in the Basecode section, there’s NeHeGL C#, plus many of the articles have source code ported to C#.

Download. Compile. Run. The familiar colorful rotating NeHe object shows up. Perfect. Now to look at what it does.

Familiar colorful rotating NeHe object

I already knew how I wanted the program to be structured. I wanted a custom UserControl for the “base” OpenGL stuff that can be shared across different applications - setting up the window context, etc. Then I wanted a control that inherits the base control to do app-specific stuff - actually drawing what needs to be drawn. And that control would be embedded on the form.

And lo and behold, that’s exactly what NeHe has. There’s BaseGL.cs, which is the UserControl that sets of the OpenGL window. The significant portion of the code comes straight from the C++ NeHe basecode: get the HWnd1 and DC2, set up the pixel format descriptor, and set the rendering context. And there’s TestGL.cs, the control specific to the app, which is basically just an OnPaint method and a keypress event handler.

But what I was really looking for was how to communicate to opengl32.dll. The solution comes in the form of three interop classes: OpenGL.cs, GLU.cs, and WGL.cs, courtesy of Colin Fahey and Chris Hegarty. I don’t know much about interops, but as I understand it, they’re like wrappers around unmanaged code. They’re just there to say, “over here, in this dll, is a function that looks like this”.
OpenGL.cs is for opengl32.dll; GLU.cs is for glu32.dll; and WGL.cs has a selection of functions from user32.dll (GetDC, ReleaseDC), gdi32.dll (ChoosePixelFormat, SetPixelFormat) , and opengl32.dll (wglCreateContext, wglMakeCurrent, wglDeleteContext, wglSwapBuffers).

In the end, this just means all OpenGL calls need to use one of these classes, so you have GL.glBegin(GL.GL_TRIANGLES) and WGL.SetPixelFormat.

By including these classes in my project, and making my custom UserControl, I was up and running with a window with a colorful triangle. The only problem is is doesn’t move. Windows doesn’t repaint unless is needs to, or you tell it to. This is as simple as calling Control.Invalidate(). The NeHe code puts this in a timer, so it happens repeatedly:

I don’t need this for what I’m working on, so I just set up event handlers for things like OnMouseDown.

There’s just one more thing I need for now: image loading. In C++ I’ve always been able to find functions for loading different image formats into raw data, but I was sure the .NET framework can do this itself. So I go to lesson 6 at NeHe’s texture mapping tutorial, ported to C#.

Load a bitmap, get the data, and create an OpenGL texture using the data.

Unfortunately, this didn’t quite work. BitmapData.Scan0 returns an IntPtr, but GL.glTexImage2D expects an object[]. The lesson 6 code works because it’s using the CsGL library, something I wanted to avoid for now. But since I have the source code for the interop, I can just change it to something that works, which matches up with what’s in CsGL. Compile and run, and that’s all I need for now.

I said I wanted to avoid using CsGL at first. That’s because I wanted to learn what needs to be done, rather than just use a library to do it for me. But I don’t want to have to include those three interop classes in every future project, so let’s see what CsGL has to offer.

I was hoping I could just change my control to inherit the CsGL OpenGLControl, instead of the NeHe base control, but it doesn’t work. ‘CsGL.OpenGL.OpenGLControl does not contain a definition for AutoScaleMode’ on a line Visual Studio inserted into InitializeComponent. If I remove the line it’ll compile, but it doesn’t run and I can’t load the form in the designer. CsGL is doing something differently than the NeHe basecode. After a quick look at CsGL, I think it has to do with OpenGLControl inheriting Control, not UserControl. A couple quick searches make it clear that I shouldn’t be using CsGL; it’s been discontinued and the Tao Framework is its successor.

Tao is pretty easy to implement. Just add Tao.OpenGl and Tao.Platform.Windows in the using list and make the control inherit SimpleOpenGlControl. A few changes to the code are needed again: in the control constructor you need to call InitializeContexts(), and the Tao class with all the OpenGL definitions is named Gl, not GL.

After all this, what have I learned? Mostly, getting started is a lot harder than it should be. A search for OpenGL C# should take me straight to the Tao Framework. OpenGL.org should have a giant “How to use OpenGL in .NET” link on it’s front page. And a place like NeHe should have a tutorial or article for using OpenGL with .NET, although the ported source code was very helpful. It’s not that getting everything working took too long, it’s just that I was expecting a simple list telling me what to do. So…

How to use OpenGL in a .NET program (Visual Studio 2005 edition):

  1. Download and install the Tao Framework.
  2. Create a new Windows application project.
  3. Create a new User Control in the project.
  4. In the User Control, make the following changes:
    • Add using Tao.OpenGl and using Tao.Platform.Windows.
    • Make the User Control inherit SimpleOpenGlControl.
    • Add a call to InitializeContexts() to the constructor.
    • Add a method to override OnPaint and add your rendering code.
    • (Optional) Add a method to override OnResize.
  5. Add an instance of the User Control to your form.
  6. To force the control to redraw, call Invalidate on the User Control.
  1. window handle []
  2. device context []

BDD and TDD are the Same Damn Thing

October 18th, 2007

One of the terms I’ve noticed in more and more development articles and blogs lately is Behavior Driven Development or BDD. It’s a development strategy that involves testing the behavior of an application during development. This is in contrast to Test Driven Development, or TDD, which is testing the behavior of an application during development.

What’s this obsession with labeling methodologies? It reminds me of the Gang of Four’s 24 design patterns, which consist of 12 new names for “is-a”, 11 new names for “has-a”, and 1 new name for “global variable”.

Haven’t we been over this already? There’s no magic development strategy to solve all your problems. There’s No Silver Bullet. Calling it BDD or TDD or DDD doesn’t matter if it’s just lipstick on a pig. Don’t live with broken windows. Don’t repeat yourself. Don’t program by coincidence.

Sorry, I dropped into Pragmatic Programmer Regurgitation mode.

Anyway, I prefer PDD: Product Driven Development. Here’s how it works.

  1. Create your product.

If you want to call your strategy BDD or TDD or just D, then more power to you. As long as you’re Getting Things Done. Just remember that is doesn’t matter what your practices are. It doesn’t matter if you miss your daily scrum meeting, or if you have any meetings at all. It doesn’t matter if your unit tests have 99% code coverage or 90% coverage, or 0% coverage. All that matters is the quality of whatever you produce.

Zelda and the DS are made for each other

October 16th, 2007

I knew when I first got the DS that it would be perfect for Zelda. The Zelda series has always been about doing things in innovative and tricky ways, and the DS has plenty of opportunities for that. Most consoles have a single mechanism for providing input: the controller. The DS has 4, and they’re all put to use in Phantom Hourglass.

  • Buttons of course can be used to perform different actions.
  • The touch screen, in addition to controlling Link’s movement, is used for taking notes and navigating your ship.
  • The microphone is used in battle in a few places.
  • Even closing and opening the lid can affect what happens in-game.

That said, and having just completed the game, I have to say I’m disappointed. And the fault is mainly the controls. Controlling your movement with the touch screen just doesn’t work. Link keeps switching between running and walking as he moves closer and farther from the edge of the screen. And you can never see the entire screen because your hand and the stylus always cover part of it. And worst of all, the action recognition doesn’t work. Supposedly, you can draw little circles to make Link roll. I’ve never gotten it to work though, unless I’m just trying to run or slash with the sword. Strangely, the shape recognition is great when you have to draw symbols. This is all especially disappointing because Zelda has always had great, tight controls.

Other than that, it’s everything you’d expect from a Zelda: puzzles, variety, and fun. Two things really stand out.

First is the note-taking. I’ve been waiting since long before the DS for a game that had note-taking capabilities like this, and I was hoping an earlier DS game would fill the void. Even though the wait was long, Phantom Hourglass gets it right. Early on, the reminders are plenty, put later in the game you’re on your own.

And Zelda is the perfect game for note-taking. How many times have you come across a blocked path or curious object in A Link to the Past or Minish Cap, only to forget about it later? In Phantom Hourglass, when you see a crack in the wall or an unreachable chest, you make a mark that will remind you.

The second outstanding thing really surprised me: the ability to stop at any time. Closing the DS lid is like a power-saving pause. You can stop at any time and instantly resume where you left off. This is great in Phantom Hourglass because of its fluidity.

Zelda has never been about long quests or marathon battles. And it’s never been about repetition or grinding. It’s about going from place to place, solving puzzles. There’s never a real sense of urgency, and there’s always plenty to do. It’s a lot like One More Turn syndrome in Civilization. Except unlike the Civ series, with Zelda you can jump right back in without missing a beat.

Just one more quick gripe before I’m done. Why are Zelda games so easy now? The first one was nearly impossible. The Adventures of Link and A Link to the Past hit the sweet spot. But The Minish Cap, Twilight Princess, and Phantom Hourglass have been ridiculously easy.

The biggest feature your editor is missing

October 14th, 2007

There’s a simple, powerful, and important feature that every text editor and IDE I’ve come across is lacking: alignment.

Alignment means “indent until the next character is in the same column as aligned columns in adjacent rows”. Visually, it means this (where . signifies “align”):

Is displayed like this:

The character following the “align” character is in the same column in each line. If another line were added, the alignment should be adjusted automatically:

Alignment can be used for multiple columms:

This would help get rid of coding style issues; we could eliminate internal tabs. So why doesn’t your IDE have this feature? It’s probably because there’s no ASCII value to represent “align”, so how should the editor save it? One option is to save as spaces.

That what elastic tabstops does. It interprets internal tabs and spaces as alignment when loading and goes back to spaces when saving. This way, editors without elastic tabstops will still show the alignment properly (watch the screencast). Unfortunately, there’s no Visual Studio or Notepad++ plugin.

But after watching their screencast, I’m surprised no IDE has implemented it natively. With all the editor enhancements we’ve been getting, you’d think something like this would be included.