If you read the last post, certainly it seems that was a lot of work just to get blocking to look right. You weren't satisfied? Neither was I! This is my second solution which also works. I wanted to do an alpha check and then a depth check and then decide to overwrite the pixel in a particular square, all the while using batched geometry (and the issues that causes when it draws super quads which overlaps properly between super squares but not between smaller squares).
Ultimately, I've changed the rendering order such that objects that cannot possibly block each other can be written in large batches. I merely have to keep the ordering between layers but not between squares. So I batch up the grass, the bushes, rendering it in order of: terrain, grass, bushes. Then comes the new trickery. I am drawing in 3d but showing a 2d game, so what do? Well, I draw the trees, the only objects that are taller than a square in the game so far, with a little bit of "height".
Try to picture the above across the 2d plane. The squares in the bottom right corner of the map is already closest to the orthographic camera plane because the entire world is tilted 30 degrees downward. Why not use this z-level information to do proper depth checking and z-buffering? The issue was that the default settings is to write every pixel information to the screen no matter the alpha value.
But then there's this in Ogre3d:
pTreeFirstPass->setAlphaRejectSettings(Ogre::CMPF_GREATER, 0, false);
Anything with an alpha channel value of zero is not drawn at all, thus the z buffer doesn't get polluted with magical pixels you can't see. In order to understand why it is a problem let's go back to how it decides the colour value of each pixel.
- Original value is some colour, an alpha value and a z-value of 0. (Remember that nothing writes to the z-buffer, so the z-value is 0)
- NewValue = OldValue * (1 - AlphaValue) + IncomingValue * (AlphaValue)
If the alpha value is always 1 or 0 (which is the case in such 2d graphics), then basically the colour of the pixel is completely overwritten by any new pixel. That is, NewValue = OldValue * 0 + IncomingValue * 1. Therefore, NewValue = IncomingValue. However, what if the incoming value had an alpha channel value of 0? Then the colour remains the same as before. But, if I want my tree quads to record z-value information, then the z-value is overwritten with some new non-zero value. So what do you see on the screen? When it draws the humans it'll see this greater than 0 z-value and thus decide that it "blocks" the human. Yet to you, you see what is "behind" the human. It looks confusing but it's only because when the tree quad is drawn it overwrites the z-value but nothing else and thus blocks anything else from drawing there, yet all you see is grass, not tree.
Now it decides not to draw anything if the alpha channel value is 0, then the z-value is not overwritten. When the human is drawn, then it happily gets drawn overtop the grass, which had a z-value of 0 (that was not overwritten by the tree quad in the square "downwards" from it) but gets blocked when trying to draw overtop a tree that is in front. That is absolutely correct. And thus I avoided having to write some kind of complicated shader to do anything.
In the future I intend to have massive gigantic 5000x5000 maps, which will likely require a simple shader (one that looks at the RGB value of the texture and then draws things specified in a texture atlas... anyway I'll get to that when I have big maps. For now I have small maps so it doesn't matter. EVERYTHING IN MEMORY LIKE I'M A JAVA DEV!)
I may update this post with what I'll do later, but at this point, I'm going to leave the iso-engine alone and optimise it again when I need to (for larger maps or more units). For now, here is a screenshot! Yummy red gazelles and a brown dragon turtle hiding in the forest.
No comments:
Post a Comment