Archived

This topic is now archived and is closed to further replies.

bsekerci

Lots of trees

Recommended Posts

Hi, I have a problem rendering trees. You can get an idea what i am trying to do from http://alpertu.virtualave.net/directx/flight8_12.jpg . There is a terrain which has about 15000 polygons. I have to render trees which have also about 15000 polygons total. Framerate is about 1! It is too slow. My card is not a good one (3D Propthet Ultra II). This terrain area is a small part. The total tree count is about 4000! My scenegraph structure is tree-like. Every object in the scenegraph has "bounding boxes" for culling. The scenegraph is created using Level of detail technique. As you can see from the tree leaves, I don''t sort polygons. I don''t use BSP or Quadtree yet. I am going to use BSP and quadtree soon. Do you think these techniques will increase my framerate much? Can you tell me how to render these trees using an efficient way? Thank you. barconan.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Use billboarding for every tree you have. You should be able to give the appearance of 3D. Try mixing up the tree bitmaps a bunch.

Share this post


Link to post
Share on other sites

I don''t create terrain. Terrain data comes to me in OpenFlight format. It has trees also. I can select all trees are billboard or like this (12 polygons).

Maybe I can create a copy for every tree ( actually there are five different trees, the others has translation information before rendered) for billboarding.

I''ll try this.

Share this post


Link to post
Share on other sites
When you have lots of little things like these that occupy a comparatively small amount of screen space, you should really billboard them, especially the far away ones. In fact, in the distance, they should be billboarded in strips (one per terrain chunk), multiple trees to a quad. Since they are not transparent, draw front to back (per terrain chunk, don''t sort all the polys individually, because that would take forever), so Z test eliminate unecessary quads. You might want to google some grass rendering papers.

Share this post


Link to post
Share on other sites
1. How are you sending the trees to the graphics API? Could be that you could benifit from caching the billboards in vRam.

2. Don''t even bother using a bsp tree for terrain. Quadtree is a much better idea.

3. Profile your app and make sure you know where the bottleneck is before trying to optimise anything.

4. If your tree models are 15k polys each, imposters would be a great idea. Render it into (say) 4 different imposters at the start of the frame at different angles, then reuse these all over the terrain. Maybe use nailboards if you need depth accuracy (although you can probably get away without).

Share this post


Link to post
Share on other sites
1. I have a geometrynode in the scenegraph. This node has vertex and index buffers. Buffers are created using D3DPOOL_MANAGED. And the textures are created using same pool parameter. In this scenegraph there are 5 geometrynode for trees. Every geometry tree has 12 polygons and one texture (textures are hold in the texture table for all nodes). This geometry node renders itself using "DrawIndexedPrimitive". The all other trees are reference nodes, which refer to tree geometry nodes. As a result, There are 5x12=60 polygons on video memory, these polygons are rendered about 12000 times! using different world matrix.

2. I don''t know much about BSP and quadtree; I think I need to sort polygons. If I use Z buffer, I need to sort them front-to-back, I don''t use Z buffer back-to-front. I am thinking BSP for sorting. I am thinking quadtree for view frustum culling. Can I use quadtree for both?

3. Do you know a good tool for profiling? I downloaded sometime Vtune. But its trial license is expired before I couldn''t try.

4. What is imposter? Can you tell me a good reference?

Thank you for helping.
Barconan

Share this post


Link to post
Share on other sites
For imposters you basically render your model (like your tree) to a texture, then billboard this everywhere instead of rerendering the original object. Nice because you can use a high poly object lots of times without actually drawing it lots of times. You can also re-render the texture imposter every few frames instead of every frame to save time. Google knows much more..

However you say your trees are only 12 polys each, so maybe imposters won''t help that much.

But you do say you''re rendering with a different world matrix each time - that sounds like you''ll be doing lots of little calls to draw primative. Instead you could fill one big vertex buffer for the entire map (duplicate your trees geometry) for all the trees, and hold the indices in the quad tree leaves. Then you get nice large batches of trees at a time instead of lots of little rendering calls.

Also try sorting by texture to minimise texture thrashing (although with 5 this might not be a problem depending on the texture size). Don''t bother sorting back to front or front to back, there are more important things to sory by. If need be you can use a quad tree for a quick and efficiant front to back sort on the leaves which will be more than good enough.

Share this post


Link to post
Share on other sites
You are right OrangyTang, I render trees using different world matrix according to their scenegraph location.

It is a good idea to fill one big vertex buffer for the entire map. But I''ll have another problem. Now I can eliminate some trees using frustum culling (bounding boxes)and LOD. I will have to render all trees discarding distance and location.

I think I can use this technique some way. I''ll try.

Thank you.

Barconan.

Share this post


Link to post
Share on other sites
quote:
Original post by bsekerci[/i
But I''ll have another problem. Now I can eliminate some trees using frustum culling (bounding boxes)and LOD. I will have to render all trees discarding distance and location.


This is why I mentioned an indexed vertex buffer. You keep your raw data the same after filling it once, but change which indices you use to render with. You can put all the indices for a quad tree leaf in an array at level load, then every frame if the leaf is visible add the indices to a buffer for this frames trees. Or if your leaves are big enough you can just render each leaf chuck straight away.

Share this post


Link to post
Share on other sites
For imposters, i you have say 10 trees nearby the viewer... What about angles?

if you render all these trees into a texture and then using it as a billboard, you will end with something not very realistic.

Is it better to render it few times, from few different angles, and then choose the more appropriate?

Share this post


Link to post
Share on other sites
for impostors, I would suggest two things: don''t use them for neraby objetcts, that move a lot in screenspace when you move the camera, in order not to get a choppy or ugly animation/image, you would need to rebuild you impostors almost every frame when the camera moves, in a high resolution texture (depending on your screen resolution of course), to get an acceptable quality. you''d rather want to switch to impostors when the trees start becoming far away, and the further they are, the more trees you group into a single impostor.

I think pre-rendering impostors isn''t good if you''ve gots lots of different models (but that doesn''t seem to be your case, but anyway, imo, it doesn''t give the best results).
something better is to render your impostors once, from the current camera position, you don''t care about camera rotation. when your camera moves, you''ll have two kind of movements that will change the appearence of the objets on the screen, and that will tell when you sould rebuild (re-render) the impostor:
in screenspace, up/down/left/right, so in worldspace it would be up/down and strafing, and camera forward and backward movement, that will change the "perspective" of the object, as it gets closer on goes away.
for the first one, you could store, for each impostor, the vector starting at camera position from witch the impostor was rendered and going to the center of the impostor.
then each frame, you take the current camera position, compute the vector from the camera to the impostor''s center, and compare the angle between that vector and the one stored in your impostor. if it''s greater than a given treshold, you rebuild the impostor from the current view point.

for the second deformation type, just compare the distance between the camera and the center of the impostor.

so for example when your object is between 0 and 1000 units (arbitrary units, I don''t know what units you''re using) from your camera, you render the object directly at the maximum LOD, when it''s between 1000 and 3000 units you render a simple impostor, and beyong 3000 units, you can start grouping multiple objects in the impostor.

something better you could do would be to compute the projected object normalized area (1.0 is the screen width and height) on the screen, and use this value to control your LOD switches. (u could project the object''s bounding box or render the bounding box and use some occlusion culling techniques? I haven''t tryed that, but it could be interesting to hear from anyone who''s tryed it?)

Share this post


Link to post
Share on other sites
Hello there...

I don''t have something to add, because i haven''t worked with trees and terrain that much. I''m completely sure that impostors will help much, and a quad-tree also.

But there is something in bsekerci''s first post made me post this.

quote:

There is a terrain which has about 15000 polygons.
I have to render trees which have also about 15000 polygons total.
Framerate is about 1! It is too slow. My card is not a good one (3D Propthet Ultra II).
This terrain area is a small part. The total tree count is about 4000!



If i''m not wrong 3D Prophet Ultra II is actually a GeForce 2 Ultra (if not a GTS). If i''m correct on that, then 30k polygons (15k terrain + 15k trees) isn''t your cards limits! You can do better than that i think. 1 FPS for 30k polygons is 30k polys per sec.

My GeForce 256 DDR 30k polys (real scene) in 60 fps (averange). Maybe it''s not the same when rendering terrains and trees but you don''t loose anything checking things once more. 1 FPS is too slow.

I didn''t mean to insult you, so sorry if it seemed like that But maybe you should look at your code once more. Or maybe it''s just a typo in the first post. Who knows.

Again, no offence.

HellRaiZer

PS. I haven''t saw anyone mention this, so forgive me if it already said!

Share this post


Link to post
Share on other sites
The problem is you''re submitting the vertices to the 3D card in a horrible manner. I have a GeForce2 also (if HellRaizer is correct that that''s what yours is), and my engine gives me ~40-50fps with ~60000 triangles. And my data isn''t even static... so you must be doing something insane like 3 vertices per vertex buffer, to get what you''re getting.

The solution is definitely not BSPs or quadtrees or billboards... those help, but your problem is much more low-level.

~CGameProgrammer( );

-- Post screenshots of your projects. 100+ posts already in the archives.

Share this post


Link to post
Share on other sites
Hi,

There is no typo. Polygon count is exactly 33268, and frame rate is 1 FPS. Card was GeForce2.

I want to summurize my configuration.
Today I changed graphic card and PC, now I have ATI ALL-IN-WONDER SERIES RADEON 9800 128 MB. P4 2.6 GHz, Memory 512 MB.
I was using DirectX8.1 as API, recently I upgraded to DirectX 9.

Now I got 4.5 FPS with same polygons.
I just calculated polygon counts.
The total terrain is about 5K, trees are about 150K!
In runtime (in the picture I gave address) terrain is about 4-5K, trees 28K.

I got 60 FPS with 120K in runtime before using my old machine. But there were no trees in there!

I thought LOD and culling nodes using bounding boxes are enough.
After trying trees I understood I need new rendering techniques.
That''s way I asked these question. If I am doing something stupid (it looks like me I am doing :-) ) please tell me! I''d be happy to find out a mistake.

You right HellRaiZer, maybe I should check my code.

I got good ideas from all of you. I am trying implement quad tree, I will create a vertex pool on the video memory for releated geometries. I will try billboards and imposters.

Thank you for helping.

BSekerci




Share this post


Link to post
Share on other sites
When I had a GF2GTS on Athlon 800 MHz, I made a terrain consisting of 131.072 (128k) polygons and it drew about 130 fps there. So you definitely have something got VERY WRONG in your app.

I would recommned the following:

1. First just draw the terrain triangles and optimize from there using indexed tri-lists/strips
2. When you have optimized terrain rendering (optimized through Indexed triangle list/strip) only then start adding trees to see the real bottleneck in your app (most probably a fillrate problem - not a number of tris (20k per scene is very low for such a card)).
3. Only after all optimizations start trying some ROAM or other algos, although with 5k you could easily just stay with brute-force rendering.

Just a few general questions regarding terrain:
1. Are you using Frustum culling ? If not, quadtree your terrain and make ONE VB from each chunk of quadtree consisting of at least few hundreds tris per smallest VB.
2. Change the size of the each chunk so that you know what size (how many tris) per chunk`s VB is optimal.
3. Do you render your VB as Indexed Tri List/Strip ?
4. How many textures do you have in your terrain ?
5. You aren`t Lockin/Unlockin Vertex Buffers every frame, are you ?
6. What size is your FVF ? Ideal size is 24 bytes
7. Are you rendering your terrain front-to-back ?


VladR
Avenger 3D game

[edited by - VladR on October 9, 2003 3:14:38 AM]

Share this post


Link to post
Share on other sites
Your problem is not the poly count, its probably the huge amount of state switching involved in drawing hundreds of tiny objects. If the trees are static and all use the same material, then you should compile them into a single mesh, or maybe a few hundred trees to a mesh. Impostering isnt going to gain you anything at all, unless you draw whole batches of trees to a single impostor.

Share this post


Link to post
Share on other sites
For comparison: I also have a GeForce2. It''s in py P3 600 Mhz with 128 mb ram. I saw a demo pull over 4 million tri/sec on it (The one-million tree forrest demo from SpeedTreeRT to be exact). Even my old TNT2 card can do better than 30k tri''s. My TNT2 pulled 1,1 million tri/sec on some GeoMipMap demo.

Sander Maréchal
[Lone Wolves Game Development][RoboBlast][Articles][GD Emporium][Webdesign][E-mail]

Share this post


Link to post
Share on other sites
Maybe I''m just too drunk to really understand the problem but the trees in your shot seems to be very detailed so I will assume that one tree is 15k gons.

Even if your 4000 trees are using the same VB again and agin, there are still some TnL to do each time you draw a tree.

You are transforming 4000*15000*3 vertices on each frame (assuming you are using a tri-list). 180,000,000 TnL operations. Whouch.

That sounds enormous.

--
Emmanuel

Share this post


Link to post
Share on other sites
i still believe to have read something about 12 polys per tree, so billboarding might help but not make that much of a difference.

but if i get that right youre drawing thousands of small objects one by one. i dont know d3ds overhead for drawing calls but you should really try and group them together. at least for a test place all trees in one big buffer and draw them with just one call.

Share this post


Link to post
Share on other sites
Hi,

I want to answer VladR''s questions;

1. I am using two kind of culling. LOD and frustum culling. Database is a "Bounding Volume Hierarchy".
There are group, LOD(derived from group), geometry,... nodes. Every node in the tree has bounding boxes.
Every node renders itself. For example LOD node checks camera position, if the distance is inside of range it renders children.
Also every group node checks frustum culling, if bounding boxes are inside of frustum, it renders children.

2. chunk?
3. My geometry is indexed triangle list.
4. In this part of terrain thera are 5 texture.
5. I am not locking/unlocking every frame.
6. The size of FVF is 36. Does it make a big difference between 24 and 36?
7. I don''t sort terrain. I am rendering according to database hierarchy.


I created one vertex buffer per database. It didn''t help. I am creating vertex buffers using D3DPOOL_MANAGED. I think they stay in video card memory.

One tree has only 12 polygons. The detail comes from texture.

Thank you for helping me.

Bsekerci.

Share this post


Link to post
Share on other sites
What do you mean, per database? Ideally you would have one vertex buffer per texture, or maybe a few per texture. 5 textures should require at most 20 vertex buffers total, if the vertex count is really high.

~CGameProgrammer( );

-- Post screenshots of your projects. 100+ posts already in the archives.

Share this post


Link to post
Share on other sites
Normally, I hold geometries in GeometryNodes. Every GeometryNode has one vertex/index buffer and one texture.

I tried to create one vertex buffer per database. So, GeometryNodes have no vertex buffer just index buffer.
I used the SetStreamSource command once every frame.

It didn''t change FPS.

Share this post


Link to post
Share on other sites