Advertisement

Good way to manage grass rendering?

Started by July 04, 2013 08:10 AM
5 comments, last by echoshen 7 years, 2 months ago

In general, what would be a good approach to manage the rendering of these kind of things? Like grass and trees. For example i'd have a density map of some sort that specifies the location of the objects, but do i sample it in the GPU and use the result to translate, or read it in the CPU at initialization? Or is there a better approach?

"Spending your life waiting for the messiah to come save the world is like waiting around for the straight piece to come in Tetris...even if it comes, by that time you've accumulated a mountain of shit so high that you're fucked no matter what you do. "

As a "general, high-level answer", yes you will certainly want to do such things as reading a density map as much on the GPU as possible. You will also want to use techniques such as instancing as much as you can.

And, you will want to cheat as much as you can. If you can get away with a texture map in the distance, do that. If you can get away with some raymarching in the intermediate distance, do that. If you can get away with billboards, use them. Only draw real geometry where you need it, because drawing all foliage using geometry will be insane amounts of triangles and overdraw.

The best "grass" paper that I know is from Kevin Boulanger. Definitively look at it.

Advertisement

I can second Kevin Boulanger's method. I'll also include example results of my own implementation of his method, so you can see some results.

wvsayh.jpg

Ad my implementation notes:

1.) I have basically just 2 grass tiles types - one with separate blades and one from slices (as opposing to kevin, he had more complicated LoD).

2.) Positions of tiles are generated as a grid on heightmap, in vertex-shader the grass is placed correctly on terrain. Animation is done also in vertex shader by bending the grass geometry (note that it's weighted by texture map).

3.) Height of the grass is driven by "density" map (e.g. the road). Note that if there is no density for given tile, the tile is skipped.

4.) Tiles use instancing, I have 2 lists of tile positions with additional parameters (one for high detail tile and one for sliced tile), these lists contains position, whether tile is flipped in X or Z direction (this helps to eliminate repetition pattern). Now I take just visible tiles from these lists (frustum culling using quadtree), and update those to vram. In current-gen you could also do this in compute shader (but it's not rly that much of data).

For large worlds, the tile data could be streamed from disk.

5.) It's very important to balance colors and lighting (so the seam between high detail and low detail is invisible).

6.) No grass shadowing & self-shadowing like in kevin's work, it was too expensive for my purposes. I preferred antialiasing to that (done through sampling alpha to coverage), FXAA doesn't work well for this kind of aliasing (result was blurry).

7.) Casting shadows on grass isn't as expensive in deferred renderers, in forward renderers it is expensive like a hell (tons of vertices) -> I used deferred shading for my project.

And just a last note -> SSAO works quite well with this grass.

If you have any questions about code, etc. I could give some (at least pseudo-code, so it would be easier to understand) out.

My current blog on programming, linux and stuff - http://gameprogrammerdiary.blogspot.com

My concern is with the density map since my terrain is relatively large (30km x 30km). You're sampling the density map on the GPU right? If so, do you render the grass patch everywhere and use the GPU to modulate the height/skip grass or do you choose where to place patches on the CPU and use GPU to modulate height?

Also, what do you guys think of techniques that use geometry shaders instead of meshes?

http://illogictree.com/upload/site/LeeRealtimeGrassThesis.pdf

http://outerra.blogspot.com/2012/05/procedural-grass-rendering.html

"Spending your life waiting for the messiah to come save the world is like waiting around for the straight piece to come in Tetris...even if it comes, by that time you've accumulated a mountain of shit so high that you're fucked no matter what you do. "

One problem with geometry shader technique is directly mentioned in the first paper you link though without the author noticing:

Anu Kalra (2007) provides a method of using DirectX 10’s geometric instancing technique to efficiently render thousands of blades of grass

That's exactly the issue, a field of grass is not "thousands of blades", it is "billions of blades". For example, FIFA specifications request that one square meter of grass have at least 25,000 blades. Thus, rendering a relatively small part of a field within your frustum, say, only 100x100 meters, we're talking about 250,000,000 blades. Rendering stiff quads as mentioned in the paper (i.e. no bending in the wind), that's 1 billion vertices. Now, hopefully you don't want to draw anything else that frame!
Approaches like the ones by Boulanger or Bakay have the advantage that their complexity is proportional to the amount of pixels covered on the screen, not to the amount of grass blades. They still look resonably good although they don't draw billions vertices
On 2013/7/4 at 9:34 PM, Vilem Otte said:

I can second Kevin Boulanger's method. I'll also include example results of my own implementation of his method, so you can see some results.

 

wvsayh.jpg

 

Ad my implementation notes:

1.) I have basically just 2 grass tiles types - one with separate blades and one from slices (as opposing to kevin, he had more complicated LoD).

 

2.) Positions of tiles are generated as a grid on heightmap, in vertex-shader the grass is placed correctly on terrain. Animation is done also in vertex shader by bending the grass geometry (note that it's weighted by texture map).

 

3.) Height of the grass is driven by "density" map (e.g. the road). Note that if there is no density for given tile, the tile is skipped.

 

4.) Tiles use instancing, I have 2 lists of tile positions with additional parameters (one for high detail tile and one for sliced tile), these lists contains position, whether tile is flipped in X or Z direction (this helps to eliminate repetition pattern). Now I take just visible tiles from these lists (frustum culling using quadtree), and update those to vram. In current-gen you could also do this in compute shader (but it's not rly that much of data).

For large worlds, the tile data could be streamed from disk.

 

5.) It's very important to balance colors and lighting (so the seam between high detail and low detail is invisible).

 

6.) No grass shadowing & self-shadowing like in kevin's work, it was too expensive for my purposes. I preferred antialiasing to that (done through sampling alpha to coverage), FXAA doesn't work well for this kind of aliasing (result was blurry).

 

7.) Casting shadows on grass isn't as expensive in deferred renderers, in forward renderers it is expensive like a hell (tons of vertices) -> I used deferred shading for my project.

 

And just a last note -> SSAO works quite well with this grass.

 

If you have any questions about code, etc. I could give some (at least pseudo-code, so it would be easier to understand) out.

 

i'm implement grass effect in my game,could you show me the pseudo-code please

This topic is closed to new replies.

Advertisement