So, as I mentioned the other day, I'll be making a 3D engine specifically suited to technically simpler 3D games, such as indie developers might want to make. I've started working on this now, and there's two major lessons I've learned over the years: 1) keep it simple, and 2) don't add features you don't need yet (also known as the KISS and YAGNI rules).
Many are the times when I've tried to keep things simple, but failed somewhere along the way - it's so damn easy to overcomplicate things, and I've found that keeping it simple can at times be really hard.
There's also been plenty of occasions when I have thought I've been keeping features at a minumum, while in reality I've been thinking too far ahead, and kept adding things I've anticipated that I'll need further down the line. Only to end up with lots of bloat, and code I don't really enjoy working with.
When I made the Pixie game engine, I managed to avoid most of those mistakes from the past, and I've ended up with a really nice, well structured engine, which is a joy to work with, so I'm determined to apply the same principles to the 3D engine.
In fact, Pixie is such a great codebase to work with, that I will build the 3D engine on top of it, which will allow me to use the same nice, clean infrastructure and platform abstraction layers.
So, my first task in making this 3D engine, is to add an abstraction layer for 3D hardware. It would certainly be possible to work with DirectX or OpenGL directly, but that has some serious disadvantages. As I said in the previous post about this engine, I want it to be suitable for indie developers, and that means it should work on both Windows and OsX (as many self-publishing indies report a similar number of sales on OsX as they see on Windows, even though the Windows userbase is much larger).
I wouldn't want to use OpenGL for a Windows game - that's just asking for trouble, as many potential customers wouldn't have suitable drivers to get OpenGL to work, and in that case would probably not even bother trying to get the demo to work. And you'd obviously not use DirectX on the Mac. Note that I won't be supporting any fancy stuff such as Shaders - this will be strictly a Fixed Function engine, for ease-of-use, performance and, most importantly, compatibility.
Here's the full abstraction layer for accessing 3D hardware, such as it is at the moment. I've only added functionality I actually need, not stuff I anticipate that I will need later on. When that time comes, I can decide whether it's a must to have it, and then add it, or if it's something I can live without, and just leave it.

As you can see, there's not much in there. Functionality to create Vertex/Index buffers and Textures, set transformation matrices, specify dynamic lights, toggle a couple of renderstates and rendering indexed or non-indexed triangles.
The goal here have been to streamline the whole rendering API, to just a handfull of methods that I actually use, and to specify them in such a way that I would like to work with them, without attempting to conform to a specific API. At this point in time, anything outside of this would just be distracting and add bloat. I suspect though, that I will be adding a few more things to this down the line. Time will tell.
In the main abstraction interface above, there's methods to create vertex/index buffers and textures. I'd like to show you what the interface for the index buffer itself looks like:

Now, this one is actually very simple: you can "Bind" the indexbuffer, which essentially makes it the indexbuffer that will be used in the next calls to the Render method used for indexed primitives. The rest of the methods are used to fill the index buffer with index data values.
The vertex buffer is essentially the same, but with more accessors for the different components. Which components are available are specified by passing a combination of VertexFormat flags to the CreateVertexBuffer method (and are similar to the Flexible Vertex Format of DirectX, though not identical).

And last, for completeness, the interface for textures:

Which again is similar, but here we pass an additional parameter to the Bind method, to indicate at which texture stage we want to use it.
The idea is to use these concepts in my higher level 3D engine code, so that it is independent of the actual rendering API used. I'm making a D3D9 implementation of this to start with, but will extend it to a DirectX3 version as well, for compatibility (to be used as a fallback on systems which doesn't have a recent version of DirectX installed - means I have to get reacquainted with Execute Buffers... argh!), as well as an OpenGL version and a basic Software renderer (as the ultimate fallback for when there's no 3D hardware).
Keeping the function set limited should make the work on the different versions a bit easier, which is a good thing :-)
Digg this
Add to reddit