i cut it back from one plant every 2 feet to one every 3 feet. coverage is decent, but there are some gaps compared to one every two feet. one plant every two feet with a clip range of 1000 feet occasionally dropped below 60 fps.

the plants are about twice as tall as i'd like them to be. making them wide and short improves coverage, but then the plants look "squashed". so i can't make them any shorter without making them smaller, which doesn't cover the ground mesh as well.

right now i've been doing this with one plant per draw call, so i can rotate them around x and z to make them sway in the wind.

since draw calls is the big bottleneck, one option is to make a model with 4 or 9 plants in it. more plants with fewer draw calls. but then you can't tilt it in the wind without it looking funny as the plants in the "array of pants" move in and out of the ground.

so i was thinking about doing a combo of the two. make half of them single plants that sway, and the rest multiple plants that don't. or is what i have now good enough? the grass is technically too tall for photo-realism - even if i do manage to get a good model and texture and material and lighting going.

another question is: how far out do games typically draw highest LOD? playing mad max recently, it seems its pretty short in that game, maybe 10-20 meters? and other shooters too as i recall... i've been testing mostly with high LOD out to 1000 feet (304.8 m).

i did some tests with a single wide short qaud (10 foot wide, 2 foot tall) with 6 plant textures on it. looks great at long range. a distinct possibility for impostor use.

so should i stick with what i have?

or thicken it up with some static plants and make all the plants a more realistic scale, but not all animate-able?

or go for impostors at long range? one consideration there is i let the player zoom the 3rd person view camera waaaaay out (50 -75 feet?). so impostors couldn't kick in until 100-200 feet. should i cut the zoom out if needed?

i'd like to get as realistic as possible, in which case the grass in the screenshot may just be too big. i'm thinking it should only come up to between mid-calf and knee height.

and plants that aren't as wide look better. but don't cover as well, which means you need more plants.

is it crazy to try to draw high LOD grass out to 300 m ? should i set a more realistic goal like 10 m + impostors or fadeout?

Share this post

Link to post

Share on other sites

1) Really crazy: Grass should not be "cards". Instead, render each blade of grass as a polygon and use vertex colors instead of textures.

Why? Won't that create millions of triangles? Sort of, but graphics cards are really good at rendering lots of triangles. The scene gets more expensive when you use cards with masked transparency and you get layers of overdraw on the cards. If each blade of grass is rendered as a polygon, then you can make the grass sway nicely with vertex shaders using position offsets. Modern graphics cards are quite capable of rendering all the triangles you can throw at it. You can get away with this by swapping out shaders at greater distances to reduce GPU instructions, and you can also start to reduce the grass density as a function of distance.

2) Grass is a *perfect* candidate for instancing. You can render all of your grass in about 3-5 draw calls (one draw call per batch of LOD's). Your GPU will love you if you can instance anything.

3) In principle, LOD's should be swapped out when the visual difference is unnoticeable. Distance based LOD's is somewhat the standard goto technique, but you can also do LOD swapping based on the object size in screen space. The screen space technique lets you have higher resolution objects for large objects in the distance (such as mountains) but quickly lets you switch LOD's for small objects in the near by zone (think of a thimble at 1 foot vs 1 yard). Generally, if you see noticeable popping between one LOD and the next, either you're switching too soon or you need more LOD's with less variation.

i may be forced to go to a later version of DX or start coding shaders, but i'd REALLY rather not do that.

so i'm still stuck with all the constraints that entails: draw calls are expensive. no instancing. static meshes only.

using the test of "change LOD when un-noticeable" i'd never change lod based on my early experiments with impostors. but they were't blended in/out. so the change from 3d model to 2d billboard was always noticeable. and impostors need to be rendered from multiple views to match the object if its not symmetric. i wasn't doing that either.

instead i chose a different course of seeing how far out i could push high LOD. with the answer being about 1000 feet at 60 fps and 22.5K grass plants, or 300 feet at 30-40 fps and as many as 100,000+ grass plants (over 100,000 draw calls per frame - yes i know that's crazy). seems i can almost but not quite get where i want to be with the number of plants drawn - all at high LOD.

and to top it all off, i'm not just going for "good looking" like skyrim SE or mad max, i'm going for photo realistic. although how i'll manage that in dx9 remains to be seen, and may not be possible. shadows are the big concern, even if i find solutions for grass and water.

Link to post

Share on other sites

In the vertex shader, you can use the texture coordinates to tell if a vert is at the top of bottom of the plant.
Translate the top verts by sin(time), etc, and don't translate the bottom verts.

Alternatively, you can manually process the verts in software. Make a big dynamic vertex buffer and MAP_DISCARD it every frame. Write some optimized CPU code to do this "vertex shading" of every plant model into this one big buffer. Then use a handfull (or 1) draw-call to submit all those triangles at once.

Share this post

Link to post

Share on other sites

Alternatively, you can manually process the verts in software. Make a big dynamic vertex buffer and MAP_DISCARD it every frame.

i've actually gotten great results with generating static (not dynamic) ground meshes in realtime (with caching). mesh animation using one static mesh per frame is another possibility. but i was thinking that simply tilting the plants might be enough. if the base of the texture image is narrow, the bottom corners won't pop up out of the ground when it tilts. or i could draw them down lower into the ground so they never appear above ground when tilted. but that still wouldn't solve the problem of needing more instances if the grass is of proper scale (ie smaller). i may have to go to dx 10, just for instancing. the problem is i don't know how big of a plunge that is: days, weeks or months to port a dx9 api wrapper to dx10. but it looks like i've already gotten a few responses on my question of porting dx9 to dx10, so maybe i'll find out.

Share this post

Link to post

Share on other sites

Yeah, what I was describing with polygon grass is in that NVidia video with turf effects, not the preceding one. The first video you posted is still using cards to render a masked grass texture onto but they're using a shader to mask the grass from an opacity layer. This is what causes the expensive overdraw I was talking about: If the camera is looking through the grass at an angle where a line of sight could pass through 20 cards, the GPU has to visit each card and run the shader to see if the card blocks line of sight. In terms of performance, it's decent for traditional games, but it can slow down your framerate if you have too much. This is particularly a problem for VR games.

The NVidia turf video is insane. Did you see how each blade of grass is casting shadows onto other blades of grass in real time?!? And then they zoom out and show you a whole field of grass. Unbelievable. I want to see that run at 90FPS.

Anyways, D3D9 supports instancing. I've done it. It also supports HLSL shaders. So, whether you're doing XNA or DX9 with C++, there's no reason why you can't use instanced draw calls for grass and combine it with shaders to create good looking grass which doesn't rely on cards.