Skip to main content
GameDev.net gamedev.net
🔒 Locked

Software Renderer Design

Started by RenderMe Mar 8, 2009 at 6:27 PM 9 replies 2.3k views
Original Post
RenderMe
RenderMe
Hi all, I guess im hoping for someone to smack me into gear because I have been mulling over this problem for ages now, trying new things and finding out they dont work as the project gets bigger. So, I have given myself the monstrous task of creating a software renderer (limiting myself to just the use of OpenGL's glDraw(GL_POINTS)). These are a few of the features I would like to include: ->Perspective transformations ->Wire Frame ->Flat surface rendering ->Gouroud rendering additional "nice" features: ->Animation ->Apply a 2D texture map to a 3D object ->Collision I understand (and have working versions)of the things of the above - but when I put them all together they go to pot! Does anyone have any links to some software renderer UML's? or could anyone give me some design tips? I have done searches but not pulled up a great deal of info on design, I hope you can help :-)
NineYearCycle
NineYearCycle
Good luck.

One point though; You say you're limiting yourself to just using "glDraw(GL_POINTS)" but the way that most people do this stuff is just to render everything to a buffer in memory that they allocate as their "framebuffer".

Then if you want to show it using OpenGL you just use glDrawPixels or you attach it to a texture and draw it on a quad. The advantage being that if you really like you can just save it to a file like tga or bmp for example or quickly port it to work with something else like DirectX.

It's just a block of data after all :)
"Ars longa, vita brevis, occasio praeceps, experimentum periculosum, iudicium difficile" "Life is short, [the] craft long, opportunity fleeting, experiment treacherous, judgement difficult."
RenderMe
RenderMe
Yes i like this aproach very much - I even have a program that is made to operate in this way. Unfortunately I can't get it to work - when I pass opengl my framebuffer all it displays is garbage (when it should be just an array of black pixels). I am storing color as a 32bit unsigned long int in the form ARGB (which i feel may be causing a problem). I am operating with floats then converting the value to the unsigned long int using bit shifting. My framebuffer is merely an 1 dimensional array of unsigned long int's of size screen width x screen height.
RenderMe
RenderMe
Can any one link some good websites that will help me with this framebuffer aproach?

Kind regards
JNT
JNT
Quote:
Original post by RenderMe
limiting myself to just the use of OpenGL's glDraw(GL_POINTS)

I havn't really done much work through OpenGL myself, so correct me if I'm wrong, but that approach would be extremely slow, since the hardware has to sync up before the CPU can do anything on the framebuffer. The fastest approach for a software renderer would be to store a framebuffer in the main memory instead.

I personally think working through SDL would be a simpler approach than working directly through OpenGL, basically since SDL's minimalistic interface is built around the user creating his/her own interface. Getting things displayed on the screen would then be a sintch.
RenderMe
RenderMe
To be completely honest I have not used SDL before and dont really want to spend time learning another tool. I do see how glDraw(GL_POINTS) would be costly but I'm struggling to find information relating to framebuffers.
JNT
JNT
Once you get SDL set up you really don't have to learn much, especially if you want to custom build most of the neccessary data structures for handling graphics. Basically, all you need is:
#include <ctime>#include <cstdlib>#include "SDL.h"int * screen_pixels;int screen_width = 640;int screen_height = 480;int screen_bpp = 32;int main(int argc, char ** argv){  if (SDL_Init(SDL_INIT_VIDEO) == -1) { return 1; } //initializes SDL (this should be the first SDL call you do), and if -1, then error occurred  SDL_Surface * screen = SDL_SetVideoMode(screen_width, screen_height, screen_bpp, SDL_SWSURFACE|SDL_DOUBLEBUF); //sets up a window for you, allocated in main memory so you don't have to lock the surface before manipulating the pixels  if (screen == NULL) { SDL_Quit(); return 1; }  screen_pixels = reinterpret_cast<int*>(screen->pixels); //point the screen_pixels pointer to the screen structure's pixels  srand(time(0));  do{    //example of pixel manipulation using the screen_pixels pointer    for (int y = 0; y < screen_height; ++y){      int * dst = screen_pixels +(screen_width*y); //gets y row      for (int x = 0; x < screen_width; ++x){        dst[x] = rand(); //sets pixel color randomly      }    }    SDL_Flip(screen); //updates the contents of the window  }while (!QuitEvent()); //QuitEvent() is just made up  SDL_FreeSurface(screen); //deallocates the screen (do this before calling SDL_Quit)  SDL_Quit(); //closes SDL (this should be the last SDL call you do)  return 0;}


You would still need something for input handling, though. SDL can do this for you as well, but in order to keep input separate from graphics, that is not included in my code above.
RenderMe
RenderMe
Thanks for that information but I am still going to stick with OpenGL :-P moreso I have used it for a few years now and feel pretty comfortable using it.

Again if anyone could point me in the direction of a frame buffer source I would be very greatful.
RenderMe
RenderMe
Hmmm, was hoping for a little more help on this one. At least I have decided to stick with the framebuffer approach.

I have implemented my color class as described here:

http://www.gamedev.net/reference/articles/article1563.asp

I have switched the Alpha value to be the low byte and moved the others along (for OpenGL).

RRRR RRRR GGGG GGGG BBBB BBBB AAAA AAAA

Anyone know how to take this further?
JNT
JNT
I don't know exactly if this goes for OpenGL as well, but if you don't use ARGB ordering the graphics will get screwed up when it finally hits the screen buffer (I think this depends on what OS you use).

A color class I find particularly useful is:
union color32{  unsigned int value;  struct { unsigned char blue, green, red, alpha; } channels;};


There are also higher level color structures you should use (involving floating points and saturation arithmetic), but for the pure pixel buffers this structure works well.

[EDIT:]
Forgot, the main 4-byte value should be unsigned...

[Edited by - JNT on March 14, 2009 9:46:45 AM]
NineYearCycle
NineYearCycle
One link I always find myself recommending is to Trenki's Software Renderer. Its a really interesting design though it might be pretty confusing for someone just starting out.

Andy
"Ars longa, vita brevis, occasio praeceps, experimentum periculosum, iudicium difficile" "Life is short, [the] craft long, opportunity fleeting, experiment treacherous, judgement difficult."

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.