Monday 4 July 2011

Improved Grass Rendering using a Quad-tree

So nice to finally get back to the blog after being away on holidays for a bit. While Vanuatu is a beautiful place its internet and computer access leaves a lot to be desired. But never the less a break away from the computer to sip cocktails is probably good for me.
I have just had some great success improving the efficiency of my grass rendering. Previously adding 1,000,000 pieces of grass across my 1 square kilometre of terrain would bring the frame rate to its knees, crawling along at barely 30fps. And a clear linear relationship between the frame rate and the number of grass was apparent.
It turns out that my algorithm was very badly CPU bound and although most of the 1,000,000 pieces of grass were not visible at one time, the algorithm to determine grass visibility was just taking forever. Note to self don’t try to do 1,000,000 sphere to view frustum calculations every frame.
So alternatively I created grass patches that represented all of the grass in a 2 meter by 2 meter area. This resulted in approximately 200,000 patches spread across my terrain which each contained a small list of locations and these were added to the quad tree of the terrain.
Using the quad-tree structure to determine visibility removed a lot of the work performed previously in the simple brute force method. Once a grass patch was determined to be visible all of its grass locations were added to a global visible grass list and sent to the shader as previously rendered.
The downside of this method was that I found that it was more noticeable if an entire patch popped in and out of visibility compared to previously where only a couple of pieces here and there popped in and out at any one time.
My solution was to modify the fog colour algorithm and use it to fade out the alpha of the grass the further it got from the viewer. Then once the entire patch is almost completely transparent it is free to pop in and out of visibility without it being noticed by the player.
It proved to be a very effective solution and I think it gives a very nice depth of field effect as well. The extra efficiency allowed me to not only render the 1million pieces of grass at over 100fps but also found that increasing the number of grass no longer had a linear penalty. I now have in excess of 200,000,000 pieces of grass spread across my terrain and still can render on average at about 100fps.