Tuesday, March 20, 2007

I have been quite busy these days writing my own small 3d engine. I did some small stuff with OpenGL in the past and to understand at least a bit better what is going on behind the scenes, I decided to do my own small renderer. I know, why write another software renderer if there is so much available. But at least for me I can say, that what I implement I do understand a little better.

Of course, it takes some time to get the basics running. Until know it does only little (only perspective projection is covered), such as the transformation from an object's local space to actual screen space. But many things are left to do such as homogenous clipping, 2D clipping, painting ...

The things I want to implement as a next step are
  • rasterization (lines via bresenham, basic filling - flat shading)
  • homogenous clipping
  • 2d clipping
  • a primitive scene graph
Since basic rasterization often produces flicker, I looked for a basic method to do double-buffering with windows forms and .NET and these are some of my findings:

  1. Enable double buffering for a control (e.g., Form) via setting a control's property DoubleBuffered = true
  2. Set a control's style via calling Control.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
This gives you basic double-buffering in an instant. But sometimes one wants to have a bit more control over the actual double-buffering process and therefore, the .NET framework provides several new classes in the System.Drawing namespace, such as:
  • BufferedGraphics
  • BufferedGraphicsContext
  • BufferedGraphicsManager
You can obtain an AppDomain's main BufferedGraphicsContext by using the Current property of the BufferedGraphicsManager or you may create your own BufferedGraphicsContext. A BufferedGraphicsContext can be used to create a BufferedGraphics object (the Off-screen buffer you want to use for drawing) and associate this object to an output device (e.g. display).
Use a BufferedGraphicsContext.Allocate method to create a BufferedGraphics object and to render the contents of such a BufferedGraphics object to an output device use the BufferedGraphics.Render method, which allows you to set the desired output device or use the one supplied to the BufferedGraphics.Allocate method. Drawing to such an off-screen buffer is easily done via a BufferedGraphics.Graphics property.

Of course, if this is not what you want you may still use a Bitmap object to do all off-screen drawing and draw that bitmap to the display.

No comments: