Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (476)
Games in Android Showcase (106)
games submitted by our members
Games in WIP (532)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Buffer Objects with glDrawElements  (Read 1726 times)
0 Members and 1 Guest are viewing this topic.
Offline anarchotron

Junior Member




...precious bodily fluids.


« Posted 2005-09-25 19:02:00 »

Howdy.

I have an engine that up until today have been using Vertex Arrays for various vertex data, and glDrawElements() to pump my Index Buffers into GL for primitive rendering.

I updated my Vertex Arrays to use Vertex Buffer Objects (VBO) and got a noticable speed improvement (~20%).  Right now I just set everything to use GL_STATIC_DRAW_ARB and I don't permit code to modify the Vertex Arrays after initialization.

I applied a similar technique to my Index Buffers, however when I use this technique it renders properly, but at roughly half the speed as before.  I'm using glDrawElements rather than glDrawRangeElements because in every case:
- I want to render using the entire index buffer
- I am already managing the data format of the index based on the range of index values (ByteBuffer, ShortBuffer, IntBuffer, etc...) so I am already passing in the most efficient data format for my indices.

Incidentally I did switch my glDrawElements() calls over to the equivalent glDrawRangeElements() with start=0, end=range, count=count but I still get the same poor performance.

Has anyone had problems using Index Buffers with Buffer Objects?  Please let me know.  I'll paste in a code snippet below.

1  
    private boolean loaded = false;


Here the bufferId has already been generated.  My 'indexBuffer' member is stored as a Buffer reference but was initialized with a ByteBuffer, ShortBuffer, or IntBuffer as appropriate when the Index Buffer itself was initialized.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
    public void loadBuffer()
    {
        loaded = true;
        ARBBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, bufferId);

        switch (getType())
        {
            case Type.T_byte:
                ARBBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB,
                        (ByteBuffer) indexBuffer, ARBBufferObject.GL_STATIC_DRAW_ARB);
                break;
            case Type.T_short:
                ARBBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB,
                        (ShortBuffer) indexBuffer, ARBBufferObject.GL_STATIC_DRAW_ARB);
                break;
            case Type.T_int:
                ARBBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB,
                        (IntBuffer) indexBuffer, ARBBufferObject.GL_STATIC_DRAW_ARB);
                break;
        }

        int err = GL11.glGetError();
        if (err != GL11.GL_NO_ERROR)
        {
            Warning.emit("IndexArray load buffer GL Error: " + GLU.gluErrorString(err));
        }

    }


And finally here's the code path for rendering.  The Vertex Buffers have already been setup, all we need to do here is blast the indices.  If the 'loaded' member is false then we use the old code path, which performs at twice the speed as the new code path.

The 'mode' variable is of course the render mode, GL_TRIANGLES, GL_QUADS, etc...
 
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
    public void drawElements(int mode)
    {
        if (!loaded)
        {
            ARBBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, 0);

            switch (getType())
            {
                case Type.T_byte:
                    GL11.glDrawElements(mode, (ByteBuffer) indexBuffer);
                    break;
                case Type.T_short:
                    GL11.glDrawElements(mode, (ShortBuffer) indexBuffer);
                    break;
                case Type.T_int:
                    GL11.glDrawElements(mode, (IntBuffer) indexBuffer);
                    break;
            }
        }
        else
        {
            ARBBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, bufferId);

            switch (getType())
            {
                case Type.T_byte:
                    GL11.glDrawElements(mode, count, GL11.GL_UNSIGNED_BYTE, 0);
                    break;
                case Type.T_short:
                    GL11.glDrawElements(mode, count, GL11.GL_UNSIGNED_SHORT, 0);
                    break;
                case Type.T_int:
                    GL11.glDrawElements(mode, count, GL11.GL_UNSIGNED_INT, 0);
                    break;
            }

        }
    }


Thanks for any help you can provide.  It is quite baffling that this change would actually decrease performance.  Pushing the indices through JNI into OpenGL has always been the greatest bottleneck in my app, as indicated by JProbe.  I had hoped that this Buffer Object usage would allow OpenGL to keep my indices on the hardware and improve performance.

Thanks!




Offline Spasi
« Reply #1 - Posted 2005-09-25 19:48:13 »

I don't have support for UNSIGNED_BYTE indices in Marathon, but I don't remember why I made that decision. Grin

I'm guessing that UNSIGNED_BYTE is not an optimal format for vertex indices. GPUs should be optimized for UNSIGNED_SHORTs, so try replacing byte with short indices, even if the model has less than 256 vertices.
Offline anarchotron

Junior Member




...precious bodily fluids.


« Reply #2 - Posted 2005-09-25 21:49:31 »

Good call.

I tried that and running with SHORTsinstead of BYTEs renders the same performance as without buffer object indices.  For grins I tried forcing everying to INTs and got the same result.

So at least now the performance is on par with what is was before.  I'm a bit suprised that performance didn't actually increase with index Buffer Objects.  As I mentioned before, performance did increase noticably when I converted my Vertex Arrays to VBOs.

Anyway, thanks for the help!
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Spasi
« Reply #3 - Posted 2005-09-26 01:10:59 »

Cool. Actually, I've seen this before with bone indices. Lousy performance with bytes, but goes full speed with shorts (although only 20-30 bones are necessary).

I'm a bit suprised that performance didn't actually increase with index Buffer Objects.

Pushing the indices through JNI into OpenGL has always been the greatest bottleneck in my app, as indicated by JProbe.

Hmm, I'm seeing this in Marathon too, but I'm sure the data transfer is not the bottleneck. When indices are accessed, the whole rendering pipeline goes to work and you can't be sure what you're actually measuring. It's really difficult for geometry transfer to become a bottleneck for modern GPUs, especially with VBO.

Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

pw (17 views)
2014-07-24 01:59:36

Riven (17 views)
2014-07-23 21:16:32

Riven (14 views)
2014-07-23 21:07:15

Riven (17 views)
2014-07-23 20:56:16

ctomni231 (43 views)
2014-07-18 06:55:21

Zero Volt (40 views)
2014-07-17 23:47:54

danieldean (32 views)
2014-07-17 23:41:23

MustardPeter (36 views)
2014-07-16 23:30:00

Cero (51 views)
2014-07-16 00:42:17

Riven (50 views)
2014-07-14 18:02:53
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!