as I mentioned in the article - http://devmaster.net...a-static-model/ - here is my little attemp to try to explain those "why's". I'd be glad if anyone made a reply containing - whether I shall continue and further do the explanation (e.g. explain stuff like how does triangle rendering & shading work and why, and also how to access buffers - etc. etc. - there is really a TON of stuff to explain) ... now few little notes for beginning...
I'm really NOT writing this or the accompanying application as something high-performance, not that this can't be turned into high-performance renderer in the end - this whole thing is to explain how rendering works and mainly WHY it works like that.
So what do we need (for compiling & using the application) - you need just Gtk, C99 standard compiler and ehm... thats probably all.
What is our goal in this part - our only goal in this part is to write two basic types into the renderer - the framebuffer and the (vertex)buffer. Plus additional procedures for clearing framebuffer and drawing points (really the easy and extremely useless way now - just to show something on screen).
The source + headers + makefile with explanation is here http://www.otte.cz/G..._Lesson1.tar.gz now the details (e.g. the article):
1. The Framebuffer object
The word framebuffer is quite self-explaining itself - it's the buffer that holds the frame (e.g. the result of rendering). Of course this explains why it has to have width, height and some data. Additional parameters are holding data like number of channels in it (this comes useful when you have different types of framebuffer, like RGBA (4 channels), or DEPTH (1 channel)) and size of one pixel in bytes (useful for simple stepping through buffers pixel by pixel).
So why do we need framebuffer - basically the framebuffer is what you think, it's a thing that allows us drawing to texture (because storing dimensions + pixel size + channels are actually texture infomation) - and textures are good. Our resulting image is a texture, or if we want for example shadow mapping for shadows - we need rendering to texture - this is where framebuffers are quite useful. Note that we can bind different textures to framebuffer sequentially (changing the parameters and data pointer of framebuffer now, but actually I'd like to point out that there should be pointer (or pointers) to some texture_t type). If I'll have some success with this thread - I'll extend this so we'll be able to attach F.e. multiple textures to framebuffer (and this explaining how MRT work).
2. The (Vertex)Buffer object
Further I'll call this just buffer. This one is quite similar to Framebuffer, but stores just 1D data. The buffers mostly stores vertices (4D floats) and also other parameters for them (texture coordinates, normals, etc. etc.). So...
Why vertex buffers? Why won't we call Vertex(x, y, z, w) all the time? Because calling that is a huge waste of resources and for static meshes, it's even more huge waste! There is a little (very very little computing power we need for each call - but doing that 1 million times a frame more is really quite a bit of computing power). For static objects this is even larger - because we can create buffer once at start and then we don't have to touch it, for dynamic objects we can just update vertices that need to be updated (so rest vertices wont be even touched) + updating buffer in a loop is faster than calling Vertex(x, y, z, w) zillion times (you'll save call overhead multiplied zillion times).
But this isn't all - vertex buffers are stored in a single memory block - so it means, that transforming vertex buffer in a loop is a lot faster than doing it per vertex (memory accessing is a lot faster - because next vertex to transform will most likely be in cache - be it on CPU or GPU). Also the matrix-vertex multiplication (and practically whole vertex processing) can be batch-processed - and thats a win (in performance of course)!
So how do we work with buffers? Because this renderer is a state machine, we work with single framebuffer/vertexbuffer at once - and that single is the binded one. I mostly followed the way OpenGL does it (but DirectX isn't far off from this - in the end they're both quite similar) - so you have to generate the object, bind the object and then you can work with binded object (e.g. fill it with data, read parameters from it and write into it's data). Although writing to them is quite simple now it will work until we meet the parallelization (then it becomes not-as-simple) - I hope I'll ever make it that far - to explain why we need to map/unmap buffers in OpenGL.
The last thigs are - basic operations - clearing the currently bind framebuffer (just see the file basic_ops.c) and draw operations with brain dead simple point write (warning, no clipping occurs to really keep it brain dead simple).
Well, this should be probably everything for now. I hope I'll get at least a bit of feedback whether it is helpful and whether I should continue or whether I should rather to stick to programming (instead of explaining - I know that I'm not a good teacher). If this is understandable and explaining, at least a bit - and if you allow me to continue - I'd like to get to lines, triangles, vertex processing and pixel processing next time(s). And then I might get enough courage to post as article (and feel like real ninja on devmaster
And by the way, thanks for reading this.














