basic 3d rendering question

Started by stringplucker, July 09, 2005, 06:23:37

Previous topic - Next topic

stringplucker

Hi All,

  My first idea when I saw LWJGL was to create a completely OO layer over the library. I completed my model class which represented any random 3d model ( w/ meshes, triangles, vertices, materials) similar to the tutorial concerning models at NeHe. But when I go to render even a single model on the screen the frame rate drops to about 2 FPS. My render code is pretty OO in that you call render on the model, it calls render on each one of its meshes, each mesh applies its material / pattern, calls glBegin(GL_TRIANGLES), and calls render on each one of its triangles which calls glVertex3d()...and so on until everything is rendered. I have seen posts concerning display lists. Can you use a lot of display lists? Would it make more sense for my model class to compile the rendering info once and call the list. Does it make sense to do this for all models in a game, ie one list per model? Or is there an even better way to go about it. My model class can import milkshape models so they all have a low polygonal count. I assume it should be possible to display many of these models at once? Thank you in advance for any input.
Mike.
ike Messa (mmessa09)
Georgia Institite of Technology

aldacron

A few tips:

* Use floats instead of doubles for your vertices. Just changing all of your glVertex3d calls to glVertex3f should give you a little bit of a performance boost. Floats are 32 bit where doubles are 64 bit. Unless you're doing something in the name of science, I doubt you need that extra 32-bits of precision. You surely don't need it for a game (these days - in the not so distant future I expect we'll be using doubles more often).

* After switching to floats, get rid of the calls to glVertex. You shouldn't be rendering in immediate mode anymore, particularly not in Java (JNI overhead for each call can add up). Batch everything using vertex arrays or through the vertex buffer object extension when supported by the driver. Check for the VBO extension first, and fall back to vertex arrays if it isn't available. The goal on modern cards is to batch many vertices together and send them to the hardware at the same time. Both VBOs and vertex arrays allow you to do that, and vertex arrays are still more efficient on older cards than individual glVertex calls. As to display lists, they might be useful for static data, but they are crap for dynamic data.

* Meshes shouldn't be rendering themselves. In your current setup, each mesh sets the render states it needs, then renders immediately. This is bad, bad, bad. Render state changes are expensive. If you insist on Mesh objects rendering themselves, then don't do so immediately. Instead, each mesh should pass its vertex buffer and render state (material) data on to a render queue. The render queue then sorts vertex buffers by render state, and when the update is finished it renders everything at once. This cuts down on the number of render state changes each frame. Look into scenegraphs and see how they can help you organize data for rendering.

I suspect that the real problem might lie elsewhere, as even doing what you are doing you should be able to render a single model at a decent framerate. Even so, the set up you have now needs to be scrapped and replaced. Once you have a more efficient rendering system set up, then you can look for problems elsewhere.

stringplucker

Holy cow. This is so much information. First off, thank you for the time you put into this reply. Ok, so I made a mistake I am using floats, not doubles.

1. Sounds like display lists are not the way to go. You said they were good for static data, like what? I think you mean you could use this to render a box which will never do anything expect maybe be translated around a scene, and use the other methods mentioned for a dynamicly animated model of a person for instance? To me this says distinguish in your engine between these 2 types of Objects and render accordingly. Would this be advantageous in anyway?

2. I dont know anything about vertex arrays or VBO's but from your post it sounds like VBO's are only compatible with newer cards or drivers? Are there any tutorials using either?

3. I went with the idea of meshes rendering themselves to preserve the OO nature of the design. I have no problem having the meshes push things onto a queue for further processing. I just happen to like the idea of not having an extremely hairy procedural render code for a model. However; if this is a bottleneck, I'll scrap it. I thought maybe the overhead used for all of the method calls might affect it a little but 2 FPS is not gonna cut it. Do you have a better suggestion?

4. I take it the organization of the rendering data is something I'd have to write myself? Or is there some built in class to help me with that? I mean I can think of some simple stuff like checking to see if it has the same material ID or texture, but other than that, it seams like a daunting task. I'll look into scene graphs now, I just wanted to give you some feedback to your much appreciated post.

Thanks a lot for all of the info. I will look into all the above. Feel free to give more tips.
ike Messa (mmessa09)
Georgia Institite of Technology

Fool Running

1. Yes display lists cannot be changed (they can only be translated and rotated).  I would say that knowing the difference between the static data and the dynamic data is a good idea as VBOs and vertex arrays are slower than display lists (beit only slightly :roll: )

2. http://nehe.gamedev.net - has lots of nice tutorials written in C++ but easily portable

3. I agree with aldacron that it would be better to scrap what you have and create a renderer that renders objects with the same material together.

4. Yes, you have to write it yourself, but it should be pretty easy. :lol:
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

Matzon

just to make ceartain, you are aware of scenegraphs like jMe, Xith and Espresso3d ?

napier

stringplucker,

Display lists and/or vertex buffers will improve performance, but you should be able to get much better than 2 fps with direct mode.  I work with small models and use direct mode only, and typically get 60-70 fps on average hardware.

You may want to take a look at your code to see if there's some other performance hit happening, if just for the learning experience.
penGL/Java/LWJGL demos and code: http://potatoland.org/code/gl