FrameBuffer 101 section 2Posted: March 16, 2012
What I have found over the years is the hardest part of programming is not writing the initial code, but rather testing that the code is correct, and maintaining it over the course of a number of years.
My mind being as feeble as it is, I can’t remember my coding intentions for more than a year out. That is, when I look back on my old code, I can’t remember what I was thinking, so it’s hard to get back in and fix an obscure bug.
One of the hardest areas to test is UI related stuff. That is anything that uses graphics, keyboard, mouse, sound. One technique that I’m employing for graphics is the low-res and composable approach. That is, the graphics algorithms themselves are compleletly independent of the actual rendering surface. A line drawing routine, or a triangle drawing routine, should work whether I’m drawing ascii art, or 32-bit rgb values.
The benefit of doing it as ASCII art is that it’s much easier to spot mistakes and boundary cases in the routine. In the above, I’ve created a frame buffer:
local fb = FixedArray2D(20, 20, "unsigned char", string.byte("."))
The size is only 20×20 ‘pixels’. I then create a ArrayRenderer object:
local graphPort = ArrayRenderer(fb)
That’s a nice easy constructor. It can take anything that pretends to have a width, height, and some other specifics about the values, like the type of the elements.
and then I draw a couple of overlapping triangles:
graphPort:FillTriangle(1,1, 12,7, 1,15, string.byte("x"))
graphPort:FillTriangle(18,1, 8,7, 18,15, string.byte("O"))
That’s about all there is to it. Now, when I want to write some tests of the rendering routines, I can use these ASCII art images as the canonical images. I can even create them using a simple text editor if I want, thus solving the chicken and egg problem for getting baseline images.
Now, when I go to test, I cam only testing the raw rendering routines, and it’s fairly low key. I can easily see from visual inspection where things are going wrong. Then, when I want to go further and test something like 3D rendering with lighting, I can be assured that at least the low level primitives, such as drawing lines, rectangles, and the like, aren’t the problem, but rather some other part of the routines.
And now there are triangle renderings in the system. So, a framebuffer, set/get pixel, line drawing, and triangles. With those basics, just about any rendering system can be built.