ePlaice / For the Best Software on the Net

Mainly Free and Open Source Software

Graphics Navigation

Axiom Game Engine | Irrlicht Engine | OpenGL Tao Framework | Bezier Curves | Bifurcation Diagram | Lorenz Attractor |

Valid XHTML 1.1

Latest news

01 Apr 2008: Inkscape 0.46 has been released with major functional improvements.

07 Jun 2007: GLEE version 1.2 has been released with new Aspect ratio feature and some bug fixes.

17 Jan 2008: Stellarium version 0.91 has been released with improved startup and stability. Now runs very smoothly under Windows XP

26 Jan 2008: Horde3D SDK [0.14.0] released

Links:

OpenGL and TaoFramework

Nehe Example 22

OpenGL provides an API (Application Programming Interface) so that the programmer can select a number of functions designed for drawing graphics. OpenGL was developed by Silicon Graphics and apart from being used for CAD, and other commercial graphic applications it is now widedly used in games development. It is intended to be used across platforms (hence the Open in OpenGL) and on this page I will look at some of the wrappers using C# and my experiences. I am still looking for the combination of Silverlight, OpenGL and C# - just think what an advantage it would be to have true 3D graphics on a web page running under Silverlight.

It tends to be rather daunting for the coder to be confronted with over 250 functions contained in the OpenGL API, so it is really welcome to find any tool which reduces the learning curve and complexity and which also uses a managed language such as C#. I was originally attracted to a C# implementation by SharpGL and then I started having a look round and found Colin Fahey's C# wrapper for OpenGL, CsGL, and then on to Tao Framework. I also had a very brief look at OpenTK; it seems that as I looked there became more and more options. Clearly, there is much interest in OpenGL running under C# managed code.

Tao Framework Using SharpDevelop

I played around a bit with some of the OpenGL development platforms mentioned above and eventually hit upon Tao Platform version 2.1. I'm not saying it's the best just that it seemed to be fairly robust, and is being developed by an enthusiastic set of developers. As I have used SharpDevelop before and have gained some experience using this it was a natural choice for the IDE and indeed I have found this to be a very satisfactory C# graphics development environment. The common alternative is to use Microsoft Visual Studio.

Create a new Windows Project

Go to File/New/Solution and choose C# / Windows Application. The installed templates will then be used to generate a new skeleton project.

Add Tao Libraries

The Tao OpenGl library is the one that I am using for windows development on .NET. The library provides all the OpenGL binding for .NET, implementing OpenGL 2.1, plus extensions.

Use Project / Add Reference and choose Tao.OpenGl and Tao.Windows.Platform - you should find these under the GAC tab provided you have installed Tao Platform correctly. At first I thought Tao.FreeGlut was necessary, but so far working on the Nehe examples I have not found a requirement. Note the Tao.Windows.Platform is required for GDI Windows binding for .NET - this is required if you use the SimpleOpenGlControl on your forms. Then on the MainForm add the following using statements :-
using Tao.OpenGl;

Add the simpleOpenGlControl

Go to Design mode and from Tools choose the Custom Control "SimpleOpenGlControl' and place it on the form. It will appear as a small black square which can then be made to fill the whole of the Windows form by selecting Properties / Fill. The whole screen will now appear with a black background. You are almost ready to start coding. Note - the Nehe Lessons that come with Tao Framework all use CreateGLWindow to set up the OpenGL Context on Windows Forms, which involves a lot of tedious coding. The SimpleOpenGlControl allows you to use set up the GL context by just dropping the component on a Form - much, much easier and allows you to concentrate on the application.

InitializeContexts

This is added immediately after InitializeComponent() statement generated when the application was created. This is very important because otherwise you will not have an OpenGL context for your form and the first thing you will notice if you try to run without this statement is that you will get a windows message box saying 'No device or rendering context available'.

SimpleOpenControlPaint

I have found it is essential to click on the SimpleOpenGLControl property 'Paint' action so that you get a an empty function
private void SimpleOpenGlControl1Paint(object sender, PaintEventArgs e) {
}
This is the place to call all the OpenGL paint commands. I sometimes find it best to have a function called PlotGL() containing all the OpenGL paint commands and then call PlotGL() from within the SimpleOpenGlControlPaint function. This is useful if you need to call the Paint commands in more than one place.

SimpleOpenGlControl1SizeChanged

Although not all examples need this I have found when using Tao Framework that it is most often required. In here I set the Viewport, Reset the Projection Matrix, Calculate the Aspect ratio and finally reset the Modelview Matrix. From experience I have found that if this is not done then often I will just have a blank screen. Call this function on FormLoad.

void SimpleOpenGlControl1SizeChanged(object sender, EventArgs e) {
            Size s 
Size;
            
height s.Height;
            
width s.Width;

            
Gl.glViewport(00, width, height);                                 // Reset The Current Viewport
            
Gl.glMatrixMode(Gl.GL_PROJECTION);                                  // Select The Projection Matrix
            
Gl.glLoadIdentity();                                                // Reset The Projection Matrix
            
Glu.gluPerspective(45, width / (double) height, 0.1100);          // Calculate The Aspect Ratio Of The Window
            
Gl.glMatrixMode(Gl.GL_MODELVIEW);                                   // Select The Modelview Matrix
            
Gl.glLoadIdentity();                                                // Reset The Modelview Matrix
        
}

Initialization Code

Note in the following the importance of the simpleOpenControl1.InitializeContexts() command. Without it you will not get any window context. In some cases you may wish to add more initialization code, such as setting the Blending Function, clearing the background color, enable depth testing, enable smooth color shading and nice perspective calculations.

public MainForm() {
            
//
            // The InitializeComponent() call is required for Windows Forms designer support.
            //
            
InitializeComponent();
            
simpleOpenGlControl1.InitializeContexts();

            
            
LoadTextures();                // Jump To The Texture Loading Routine
            
InitBezier();                // Initialize the Bezier's Control Grid
            
mybezier.dlBPatch GenBezier(mybezier, divs);        // Generate The Patch
        
}

Refreshing the Screen

I have found that it is a requirement to refresh the SimpleOpenGLControl whenever there is any movement in the graphics. So for example in the Nehe example 11 where we are trying to achieve a flag waving affect we must do a refresh at the end of the paint routine.

Procesing Input Keys

Initially, I had some problems with making the application respond to key presses. Eventually, I settled on using ProcessCmdKeyand as used in the following example. Note that the Refesh command appears to be mandatory, otherwise the screen does not move. I don't particularly like this and there may be a way of removing the need for the Refresh command so maybe I will be able to update this section later.

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
            
const int WM_KEYDOWN 0x100;
            const int 
WM_SYSKEYDOWN 0x104;

            if 
(((msg.Msg == WM_KEYDOWN) || (msg.Msg == WM_SYSKEYDOWN)) && simpleOpenGlControl1.Focused) {
                
switch (keyData) {
                
case Keys.Down:
                    
if (divs > 1) {              // If We Have At Least 2 Divisions
                        
divs--;                // Decrease Divisions
                    
}
                    mybezier.dlBPatch 
GenBezier(mybezier, divs);       // Update The Patch
                    
simpleOpenGlControl1.Refresh();
                    break;

                case 
Keys.Up:
                    divs++
;                 // Increase Divisions
                    
mybezier.dlBPatch GenBezier(mybezier, divs);       // Update The Patch
                    
simpleOpenGlControl1.Refresh();
                    break;

                case 
Keys.Left:
                    rotz -
0.8f;               // Rotate Left
                    
simpleOpenGlControl1.Refresh();
                    break;

                case 
Keys.Right:
                    rotz +
0.8f;               // Rotate Right
                    
simpleOpenGlControl1.Refresh();
                    break;

                case 
Keys.Space:          // Is Space Bar Being Pressed?
                    
showCPoints !showCPoints;            // Toggle Display Of Control Points
                    
simpleOpenGlControl1.Refresh();
                    break;
                
}
            }
            
return base.ProcessCmdKey(ref msg, keyData);
        
}

Getting Started

I found a good place to start was with the Nehe Tutorials. There are a good selection of examples mainly written in variations of C++ and C, with a few translations into C#. Although at first sight translating from C++ would seem to be fairly trivial, I have found a number of pitfalls and sometimes find that what I considered a good translation just did not work in managed C# code.

Performance

Having tried a few examples using SharpGL, CsGL and Tao Framework I have been very impressed with the performance achievable using Tao Framework. I have run these tests using Windows XP and employing the SimpleOpenGLControl from within SharpDevelop.

A Few Points of Interest

There are a few little quirks I have found with Tao using the control - in particular I have to set the perspective manually, most times I do need a SimpleOpenGlControlSizeChanged function. There are requirements to do a refresh of the control whenever the scene is changing as a result of keyboard, mouse or speed changes.