I have built a software renderer in C++. I use the GDI+ library to draw to the screen. The renderer can load a model that is stored in the .MD2 format (Quake 2) and draw it to the screen. I can create a range of different lights in different colours to light the model.
The software renderer loads .MD2 files into memory. I store this information in my my custom model, polygon and vertex classes.
- Draw models to the screen
The model is drawn to the screen using the GDI+ library. The program makes use of a number of optimisations, such as backface culling.
In order to draw to the screen, the model must go through a number of transformations first, known as the rendering pipeline:
Firstly I apply a camera transformation to the models vertices. This takes the position and direction of the camera and calculates where everything in the scene is relative to the camera.
Next I apply a perspective transformation to the model, this transforms the models 3D co-ordinates into 2D co-ordinates to be drawn on the screen.
Finally I apply a screen transformation to the model, this accounts for the fact that the size of the window is not a perfect square (the aspect ratio of 800×600 is 1.3 for example). This prevents distortion of the image.
After the three transformations have been applied, the model is ready to be drawn to the screen. I do this by drawing each polygon with my own custom SetPixel function, which draws each pixel individually and allows me to interpolate colour values.
(Each of these transformations is stored as one or more matrices in my custom matrix class.)
By applying rotation matrices to the loaded model I am able to rotate it in the X,Y or Z directions (or any combination of the three!)
My software renderer calculates which direction the polygons in my model face, if they are facing the opposite way to the camera, then they will not be drawn. This speeds up the process of drawing the model.
My renderer makes use of numerous kinds of light, including: ambient lights, directional lights and spot lights.
Ambient lights affect all polygons equally, they are sometimes referred to as ‘background light’. They appear to light the model from every direction with the same amount of light. Ambient lights can be set to any colour.
Directional lights have a direction in 3D space and come from infinitely far away. Directional lights can be set to any colour.
Spot lights have a position in 3D space and emit light equally in every direction.
I used Visual Studio 2010 Ultimate to write this program in C++ with the GDI+ API.