[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] Faster OBJ loader



It should be noted that display lists are deprecated (but for all intents and purposes still there) in the anti-fixed function opengl 3.1+ (and perhaps completely unavailable in open gl es 2.0?). So learning vbos is probably a good idea, and like display lists it also means you aren't passing vertex arrays over the graphics bus on every draw call because the vertex arrays are stored on the graphics card. The advantage of vbos over display lists is you can store static or dynamic data, the disadvantage is you can only store certain kinds of data and not operations, so on some cards display lists are still faster than vbos.

Devon

On Tue, Sep 28, 2010 at 1:05 PM, Ian Mallett <geometrian@xxxxxxxxx> wrote:
On Mon, Sep 27, 2010 at 8:05 PM, Christopher Night <cosmologicon@xxxxxxxxx> wrote:
Thanks for the response! Assuming that rendering means what I think it means (actually drawing the thing on the screen, right?),
Absolutely.
I was able to improve the rendering performance significantly using vertex arrays in the test I did a few months ago. I was still using a display list as well, but I greatly reduced the number of GL commands within the display list. The trick was to triangulate all the faces, and render all the faces for a given material using a single call to glDrawArrays(GL_TRIANGLES...). I realize this is hardware-dependent, but the speedup was dramatic on 2 out of 2 systems that I've tried. Maybe it's not the vertex arrays that matter, and triangulating all the faces and using a single call to glBegin(GL_TRIANGLES) would yield the same speedup. Either way, it's worth looking into I think....
You must not be using the calls as you think you are, then.  Graphics cards have a "graphics bus" that handles data transfer to and from the card.  Unfortunately, this graphics bus is slower than either the CPU or the GPU themselves. 

Fixed function (glVertex3f(...), glNormal3f(...), etc.) sends the data to the card on each call.  So, if you have 900 such calls, you send 900 state changes to OpenGL across the graphics bus each time the data is drawn.  This can get slow. 

Vertex arrays work similarly, except the data is stored as an array, and the equivalent of the 900 fixed function calls are sent across the graphics bus each frame.  Although this batched approach is faster than fixed function, all the data is still transferred to the card each time the data is drawn. 

Display lists work by caching operations on the graphics card.  You can specify nearly anything "inside" a display list, including fixed function (and I think) vertex arrays.  To use display lists, you wrap the drawing code in glGenLists()/glNewList() and glEndList() calls.  The code inside, after being transferred to the GPU, is stored for later use.  Later, you can call glCallLists(), with the appropriate list argument.  The list's NUMBER is transferred to the GPU, and the relevant set of cached operations is executed.  The practical upshot of all this is that each time you draw the object, you pass a single number to the graphics card, and the appropriate cached operations are executed.  This is the way the Wiki .obj loader works. 

Vertex Buffer Objects are a more advanced topic, but they work by caching vertex arrays on the GPU.
Improved loading performance comes from the fact that these arrays can be pickled, so you don't have to read them directly from the OBJ file after the first time. You only need to distribute the pickled OBJ/MTL files with your actual game. Psyco or C might be just as good, but this solution was pretty simple, and reduces the (subsequent) load times to almost nothing.
This is actually a fantastic idea; I love it!
-Christopher
Ian