some snippets from javagaming.org
One more thing...
Capability bits in the scene graph allow or PREVENT J3D from optimizing your geoemtry. It's critical to get them the way you want, i.e. performance vs. dynamicness.
Be sure to set them appropriately.
Here's a snippet from the J3D mailing list. On transforms. By_Copy vs. By_Ref geoemtry and other things are important as well.
.
.
.
One of the optimizations in BranchGroup.compile() is to flatten
the graph. Currently in Java3D 1.3, only non-modifiable TransformGroups
will be removed, and the transformation will be recursively applied
down the graph as low as into the geometry if
. the geometry is not readable AND
. the geometry is not being shared by more than one Shape3D AND
. the geometry is not BY-REF AND
. the Shape3D is not pickable or collidable AND
. the Shape3D does not have TransparencyAttributes
Charmaine Lee
Sun Microsystems
- Get rid of SimpleUniverse. Code the thing yourself from scratch. If you're going to compare apples with apples, at least start by coding an apple first, not an orange.
- Don't use a behaviour to do the timing. A behaviour nominally runs as a separate thread. That means synchronisation overheads for every frame between the two (or more) threads that Java3D uses internally. In addition, the J3D runtime has to work out every frame whether the behaviour has to run or not so theres' more computation overhead there. Instead, do your timing based on a call to pre/postRender() of Canvas3D.
- Use immediate mode rendering. That's what you're doing with the OpenGL code (unless you're doing something with display lists as well, in which case you will never get a decent comparison).
Ok, to make your benchmark faster.
1. Using quads may be slightly unpredictable for comparison puropses. Java3d sometimes turns them into triangles depending on the driver, so you might not actually be comapring the same thing.
2. Make sure that the proper capability bits are set to indicate static from dynamic.
3. Make sure that zbuffer, FoV, etc are the same.
4. Unless every cube has a completely unique appearance, re-use the sub-pieces where possible. So for example if every cube has the same material, rendering attributes, etc.. use one instance of the proper object. This speeds up java3d's ability to detect the same attributes in the rendering pipeline. So you can have unique Appearance objects, but still share the RenderingAttribute object.
5. Compile the objects. This removes the nested transformations and flattens the geometry arrays where applicable.
6. Create one shape for the cube, create a SharedGroup and Link nodes and then use alternate appearance to change each instance's appearance. This might be unfair in Java3d's favor though. But this will basically force Java3d to use a single display list for the geometry, rather than N copies. So it depends on how your OPenGL is coded. If you have one display list and you are just pushing the T&L and then rendering the list, then that is not the same as what java3d will do with N un-shared shapes. If you have N unshared shapes it will have to have N display lists, and since there is a limited number you an have it will probably switch back to vertex arrays.
7. If you are not doing any behaviors then you might try disabling the behavior scheduler (in the View object).
8. Make sure that garbage collection is not kicking in, so make sure your benchmark does not hemmorage objects during the run.
9. Make sure that backface culling is the same, that the lighting is the same. Make sure texture filtering is the same, perspective correction is same, mipmapping same... etc.
10. Move your camera using a transform you update per frame, not using a behavior. Make sure the view's virtual world mapping is the same.
Hope those help.
Dave Yazel