a call for opinions - drawing grass

Started by
26 comments, last by Norman Barrows 7 years, 2 months ago

a call for opinions - drawing grass

i'm working on drawing better grass plants in caveman.

here's where i'm at right now:

gallery_197293_593_1278146.jpg

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?

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

Advertisement

Personally, here are my thoughts on grass:

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.

one big design constraint i forgot to mention:

dx9, fixed function, no shaders, no true instancing.

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.

so yeah, extra challenging problem this one. unless i port to dx10.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

Use instancing and shaders :)

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.

Out of curiosity how many draw calls are you using on grass per frame right now?

-potential energy is easily made kinetic-

use vertex colors instead of textures

not so sure about that for photo realism.

check out this grass... a nice example of poly based

vs this grass - procedural by nvidia - turf effects.


Use instancing and shaders

which leads to my next question....

https://www.gamedev.net/topic/685102-porting-dx9-to-dx10-or-later-how-hard/

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

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.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

i may have to go to dx 10, just for instancing
D3D9 supports "real" instancing:

https://msdn.microsoft.com/en-us/library/windows/desktop/bb173349(v=vs.85).aspx

(On SM3 capable GPUs -- which is any D3D10 capable GPU, and a handful of the last D3D9-era GPUs)

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.

Out of curiosity how many draw calls are you using on grass per frame right now?

i've tested it at one plant per foot, per 2 feet and per 3 feet in a 300x300 foot terrain chunk. drawing the player's chunk and all adjacent chunks (9 chunks total).

that works out to 90,000, 22,500, or 10,000 draw calls per chunk just for savanna grass plants.

clip ranges are set to 1000 feet, as is the frustum far plane distance, during the pass that draws grass and other things that are "neither very near nor very far".

after trivial rejection of chunks behind the camera and a frustum cull, in a scene with 2000-3000 other meshes, i've hit over 100,000 draw calls total.

needless to say, that was a bit of a performance hit. <g>

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

This topic is closed to new replies.

Advertisement