Building things will be very important in Amberfell. There are basically two reasons for this. Firstly you’ll need to build workshops to be able to craft the equipment you’ll need to extract and process amberfell itself (I’ll explain a bit more about how I see crafting working in a later post). The other, and probably more important, reason is that it’s fun! I want to be able to build buildings and structures of all kinds, just for kicks. For that reason I wanted building to be a little more aesthetic than simply piling blocks on top of one another. I also wanted them to be slick and easy to create. So I set about creating wall and roof components. The walls were easy, just a thinner block with a log texture on it (more types to come: planks, brick, stone, even corregated iron). I didn’t want the player to have to go to the hassle of creating corners, t-junctions and crossovers – I wanted the game to work that all out and make it look good. In this video you can see how I approached it. As you place blocks their shape changes depending on their surroundings. It means with a single block type you can build walls and corners with minimal effort. The results look pretty good IMHO.
I wanted to do the same for roofs too. I played around with some ideas but I didn’t want to introduce partial height blocks or slopes at this stage (or maybe ever). That meant that slabs and stairs were out, but I still wanted a nice roofing component. The solution I came up with was a slab that was supported by a 2⁄3 height wall. It has a slight overhang too which looks nice on buildings, quite rustic. These blocks adapt automatically too, using similar logic to the walls. You can see them in action in the following video.
After all the groundwork I’ve put in place, adding these new unusually shaped blocks was actually pretty easy. The hard part was working out the vertices to render and making sure I got the textures mapped properly – just visualising what I wanted and translating the 3D coordinates to code.
I really hoped that I could start making progress on the game mechanics but I had this niggling problem in the background: framerate. Gradually over the past few weeks my framerate has been eroded down to about 10fps, from the 19 that I mentioned a few blog posts back. Now, 19fps on my low end GPU isn’t too bad – it’s tolerable. However at 10fps, the game starts to feel sluggish and jerky. I haven’t done much profiling yet but I do know that I have been using the slowest method for drawing opengl scenes. The immediate mode is where everyone starts and where all the tutorials focus their efforts. It has the advantage of being easy to pick up, just a matter of making the right calls in order: move to here, rotate this amount, draw a triangle here. However, that approach is known to be slow for large scenes, such as a game. In fact this whole immediate mode is now deprecated in the latest OpenGL specs. The best performance comes from using Vertex Buffer Objects. These work by storing the scene data in fast memory on the GPU itself and you just send commands to render it at appropriate times. The disadvantage is that you have to calculate all the scene data yourself and load it into the buffer. That meant a rewrite of a lot of my rendering code. I’m about half way through. I have all the drawing converted to data in in-memory structs rather than inline API calls. Currently I am looping through this data and calling the right API calls on the data. The next stage will be to load the data into a buffer and render from there. However, even getting halfway there has reaped huge performance rewards as this process basically results in a lot more caching of pre-calculated data. My framerate is a consistent 30fps which is excellent. The real framerate is likely to be even higher but video drivers with vsync enabled will force framerates to 30 if it’s anywhere between 60 and 30 to prevent tearing of the image. Anyway, here’s the video which shows off the new framerate and the new chunk-based rendering, and the new zoom feature :)
Update: I just ran amberfell with vsync disabled and I’m getting a true framerate of about 40fps. (I just ran using vblank_mode=0 ./amberfell)