Thursday, December 16, 2010

20 – Hollow Earth, part one

As said last time, the only way to speed up rendering still left is to draw fewer tiles. But in a multi-layered 2D isometric game, where a wall tile is a single sprite, determining when something covers something is both difficult and costly in CPU power.
So let us suppose that we have a 3D world. While this world is not made up entirely by cubes, floors and walls are made up by rectangular 3D shapes that we can abstract as cubes. So how would we proceed in a 3D game? We would use one of the well-used and documented methods, like octrees. Octrees are basically cubes that are divided recursively into 8 cubes. These have interesting properties that are useful in 3D rendering engines. Or so I’m told. I never used them and I can’t write an octree implementation of the top of my head. I could with a little bit of study. But let us try something different.
Coming back to our 2D game, the idea is to split up the single tile of the walls into multiple “polygons” like you would do in 3D, and only draw the ones that are adjacent to a free space. We only draw the “borders” of the world. Hollow out the world. This should greatly speed up full multi-layer rendering, where all Z levels are drawn and which currently is unplayable, having with all optimizations a FPS of less than 20 while on the same computer single layer rendering is well over 100.
I’ll proceed and visually walk you through the process since this is not a technical blog. So let us start with a normal world, where walls are drawn by a single sprite:

Now, since the “camera angle” is fixed, we don’t have to worry about all sides of our cubes. At most, only three sides are visible, that is the ones in the front. We have one on the left, on the right and one on the top. So let us draw only all the ones on the left: 

Where is the gain in this? Well, first we need to only draw the sides that would actually be visible, not all of them. If we do that, everything will disappear. While all other sides are not drawn yet, they still would cover the ones on the left. So I cut out a small corner where two of these sides are seen:

Actually, let us cut out a few tunnels, so we can get a better look. All black parts are not rendered and should be invisible since they are covered by top layers. When enabling single layer rendering, the top sides of walls will be forced to render, but we’ll talk about that another time. This is the result:

Something you may notice is that floors seem to be drawn in a strange manner. This is due to a previous optimization in the rendering engine, which would enable some floor tiles that are covered to not be rendered. So don’t mind these. Now let us enable all right sides of the walls:

Then we will do the same thing, that is draw only the ones that should be visible. To better illustrate this, I managed to cut out a few extra tunnels:

If it is not clear what I am doing, maybe it will become clear when I apply the same process to top sides of walls and floors. Basically, the black part is and should be invisible. Theoretically no processing power is wasted on them. This only applies to multi-level rendering, but single level is fast enough.
But this post is way too long. I even broke the five pictures per post rule J. So I’ll split up this post…

No comments:

Post a Comment