Page 6 of 16

Posted: Fri Feb 23, 2007 11:52 am
by sio2
Excellent stuff.

I've been playing around with this. I tried a 32x32 grid of trees (yes, that's 1024) and here's my findings:

1. Lowest fps is about 40.
2. I get about 100fps with them all on screen (LOD in action!). Viewpoint is just above tree (0,0) looking over the forest at toward tree (31,31).
3. Trees don't seem to be frustum culled. I can look at a 1000 trees and then point the camera towards "nothing" and the frame rate doesn't budge.
4. Popping is obvious at LOD transitions.
5. 1024 trees take a second or two to set up.

BTW I also tried a 256x256 grid of trees but after about 30 seconds it crashed. Haven't investigated this yet.

Posted: Fri Feb 23, 2007 12:58 pm
by Klasker
sio2 wrote:I've been playing around with this. I tried a 32x32 grid of trees (yes, that's 1024) and here's my findings:

1. Lowest fps is about 40.
2. I get about 100fps with them all on screen (LOD in action!). Viewpoint is just above tree (0,0) looking over the forest at toward tree (31,31).
Thanks for posting this. I'd be interested in hearing your system specs too. What fps do you get in the demo program I made? I'm getting around 400 fps in my demo app, with my GeForce Go 7300.

3. Trees don't seem to be frustum culled. I can look at a 1000 trees and then point the camera towards "nothing" and the frame rate doesn't budge.
Irrlicht's frustum culling tends to be a bit inaccurate. Try printing out the number of triangles drawn too (using driver->getPrimitiveDrawnCount), to see if it gets culled or not.

4. Popping is obvious at LOD transitions.
Yeah, especially with lighting enabled. Most games fade the meshes between each LOD, but this is very cumbersome in Irrlicht at the moment.
5. 1024 trees take a second or two to set up.
Thanks for the benchmark. In a practical application, I'd recommend re-using existing tree meshes, so you only have about 20-60 unique tree models. Saves memory and generation time.
BTW I also tried a 256x256 grid of trees but after about 30 seconds it crashed. Haven't investigated this yet.
Were all the trees unique? Have you tried loading 65536 meshes into memory? An oak uses around 2500 vertices (not including leaves). Each vertex uses 36 bytes. So roughly estimated, you would need 5625 MB of RAM to store the vertices alone.

Posted: Fri Feb 23, 2007 1:24 pm
by sio2
I get about 470fps on a 7800GTX with your original demo.

Latest SVN seems to have a bug where the triangle count increases each frame (probably not being reset).

Boy, that's some inaccurate culling! I point the camera at 1000 trees - 89fps; I point the camera at nothing - 89fps! :wink:

The trees should not be unique, but I have a hunch I may have made an error. 64K instances of one mesh is a lot different to 64K meshes. :roll:

Posted: Fri Feb 23, 2007 1:32 pm
by hybrid
Please note that culling was not enabled in SVN revisions prior to 487 (wrong init in changes made several weeks ago). I have changed this now.
I have to check with Thomas why he wants the face count like it is (I already fixed it some revisions ago), but I guess that the usual behavior will be restored in the next release.

Posted: Fri Feb 23, 2007 3:25 pm
by sio2
Thanks for the notification, Hybrid. I just recompiled and now the frame rate increases when pointing the camera away from the 1000 trees.

It's interesting that the frame rate only jumps from 89fps to about 210, though. I wonder if it's part of the "drawAll()" issue in that nodes are updating all their internal stuff regardless of whether they are visible or not...

mesh re-use

Posted: Fri Feb 23, 2007 3:46 pm
by buhatkj
how would one go about re-using an already-generated tree mesh? Is there a copy constructor or something for tree nodes?

Posted: Fri Feb 23, 2007 3:58 pm
by Klasker
This is from the CTreeGenerator:

Code: Select all

SMesh* generateTree( s32 radialSegments, s32 seed=0, bool addLeaves=true, s32 cutoffLevel=0 );

CBillboardGroupSceneNode* getLeafNode();
When calling CTreeSceneNode::setup, it simply calls generateTree for you and stores the mesh. There are two setup methods in CTreeSceneNode:

Code: Select all

    void setup( SMesh* highLod, SMesh* midLod=0, CBillboardGroupSceneNode* leafNode=0, video::ITexture* billboardTexture=0 );
    
    void setup( CTreeGenerator* generator, s32 seed=0, video::ITexture* billboardTexture=0 );
In the first one, you manually specify the high detail mesh, the low detail mesh, and the leaf node. The second one does it automatically. So to use the same mesh for many trees, use generateTree manually and call the first setup method.

Posted: Fri Feb 23, 2007 4:01 pm
by buhatkj
ah ok yeh that makes sense. I was looking at the tree level to copy them...silly...

Posted: Fri Feb 23, 2007 6:12 pm
by sio2
Stupid me. I was generating new trees for every instance. :oops: I think my process crashed when it got to 4GB of memory. :wink:

OK, I'm now instancing:
256x256 (65536 trees) = 11fps; default far clip.
256x256 (65536 trees) = 4fps; far clip = 100,000.
32x32 = ~108fps; default far clip.

BTW 64K trees take ~78MB.

BTW2 I'm just playing with this! I know 64K trees with this method is not a good idea! :mrgreen:

Posted: Fri Feb 23, 2007 6:14 pm
by sio2
Mr Klasker, I have a little problem: no leaves on my trees (fps numbers in previous post were without leaves).

Could you post a snippet of how to properly set up, say, two trees from shared meshes?

Posted: Fri Feb 23, 2007 6:35 pm
by Klasker
sio2 wrote:Mr Klasker, I have a little problem: no leaves on my trees (fps numbers in previous post were without leaves).

Could you post a snippet of how to properly set up, say, two trees from shared meshes?
Hmm... there's a problem there. I should have seen that before. I'll have to refactor the code a bit...

Procedural Trees v 2.1

Posted: Sun Feb 25, 2007 11:47 am
by Klasker
Version 2.1 is available.

New in v 2.1
  • Optimized the leaf billboards. Great performance boost in forests.
  • Refactored the code to allow many trees to share the same set of leaves. Previously only the mesh could be shared.
  • Fixed a bug that would hide the leaves near the transition to the billboard LOD.
Download (2.78 MB)

Could you post a snippet of how to properly set up, say, two trees from shared meshes?
With the new version, here you go:

Code: Select all

CTreeGenerator* generator = new CTreeGenerator();
generator->loadFromXML( "../trees/Oak.xml" );

STreeMesh* treeMeshHighLOD = generator->generateTree( 8, 1234, true );
STreeMesh* treeMeshLowLOD = generator->generateTree( 4, 1234, false, 1 );

// Create first tree...
CTreeSceneNode* tree = new CTreeSceneNode( manager->getRootSceneNode(), manager );
tree->setup( treeMeshHighLOD, treeMeshLowLOD, billboardTexture );
tree->drop();

// Create second tree...
tree = new CTreeSceneNode( manager->getRootSceneNode(), manager );
tree->setup( treeMeshHighLOD, treeMeshLowLOD, billboardTexture );
tree->drop();

treeMeshHighLOD->drop();
treeMeshLowLOD->drop();

Re: Procedural Trees v 2.1

Posted: Sun Feb 25, 2007 12:30 pm
by sio2
Klasker wrote:Version 2.1 is available.
Excellent. Will try it out. :D

Thanks for the snippet, also.

Posted: Sun Feb 25, 2007 1:06 pm
by sio2
Got it working. :D My 32x32 test forest (fully textured) runs at 67fps. 128x128 is ~22fps.

A few notes:
1. Your exe (in the zip) crashes for me. I haven't looked why, yet, as I just dumped the new code in my existing project.
2. I'm using the latest SVN and I get the usual compile errors since the prototype of getMaterial() and getMaterialCount() has changed since 1.2 (s32 to u32). Simple enough to solve, but thought I'd mention it for others to know.
3. The snippet gives untextured trees for me. In my demo I added code to set the bark and leaf textures for each tree instance I make.
4. Also, I think both trees are in the same location in the snippet - I'm sure you'll get "I can only see one tree" postings. :wink: I set the position of each instance in my demo.

Posted: Sun Feb 25, 2007 1:12 pm
by sio2
Another tip: trilinear on the leaf textures helps. The HW blends between mips and makes things look smoother. 8)