Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (522)
Games in Android Showcase (127)
games submitted by our members
Games in WIP (590)
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  
  VBO's - teach me please.  (Read 4730 times)
0 Members and 1 Guest are viewing this topic.
Offline Addictman

Senior Devvie


Medals: 3
Projects: 1


Java games rock!


« Posted 2011-03-29 07:51:53 »

Hi.

So, I've started writing a game on the Android platform. Everything is working out quite well so far, except one [major] thing: Performance.
I've always been slow on catching up on the OpenGL stuff since I've always worked under the philosophy "Optimize later" (and never really had to). But on Android, "later" is "earlier" it seems.

I'm working on a standard 800*480 display, and I am filling it with a varying number of 16*16 textured quads (rendered as GL_TRIANGLES) (Ranging from 0 quads to filling the whole screen). I've been using Vertex Arrays with index pointers and glDrawElements, and I've tried several approaches that work from very poor to pretty poor.

Approach 1: Vertex array for one quad, located at 0,0, - render each of the textured quads by translating to their location.
Approach 2: Large vertex array to hold all quads with absolute location, render it all in one go.
Approach 3: Bundling the 16*16 quads where possible (forming larger quads, and using the texture's s&t repeats to fill them).

Approach 1 is horrible. I wasn't too surprised about that, but I figured I'd give it a go. Performance on approach 2 and 3 vary abit, depending on the composition of the quads, and their quantity. But none of the approaches perform sufficiently.

I manage about ~15 FPS on my HTC Hero, when the screen is full.

So, I figured I would give VBO's a shot. I know they aren't too far from Vertex Arrays in regards to implementation, but I'm not really sure how they differ. (Vertex arrays have always been more than good enough for me on the PC platform, so I was always too lazy to learn VBO's).

I'm looking for some help on how to implement them properly, and how they're incorporated and used in the following points.

-> Surface creation
-> Surface resizing
-> Setting up rendering for an entity
-> Rendering the entity
-> Cleaning up after the rendering


I should note that in my specific problem, my grid of textured quads is dynamic, in that it changes based on user action. It does not however, change on every cycle.

Thanks for any help offered Smiley
Offline gouessej
« Reply #1 - Posted 2011-03-29 11:13:54 »

Hi!

Your first approach is not efficient, do not use a VBO to contain a single quad, it is often even worse than immediate rendering. Use static VBOs for things that rarely change and dynamic VBOs for things that changes frequently. Avoid creating too small VBOs. If you don't need to modify some VBOs very often, don't put the data in a new NIO buffer, rather reuse the data store of the GPU (use glMapBuffer if possible). Avoid mixing VBOs with vertex arrays, display lists and immediate mode.

Offline Addictman

Senior Devvie


Medals: 3
Projects: 1


Java games rock!


« Reply #2 - Posted 2011-03-29 13:59:03 »

Hi Goussej.

Thanks for answering. To clarify, I am NOT using VBO's in any form right now, - just basic Vertex Arrays. The reason is simple; I'm not sure how to implement VBO's. I've of course found a plefora of examples on the web, but few of them seems to be implemented identically, so I'm a little unsure on how to approach them. Not to mention that I'd like to understand how they actually work in theory as well.

That's why I'm asking the experts here Wink

If you could provide an example of VBO implementation (the more comments, the better!) I'll be grateful.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline lhkbob

JGO Knight


Medals: 32



« Reply #3 - Posted 2011-03-29 15:24:47 »

VBOs work just like vertex arrays except that the data is on the graphics card.  The only extra steps you need to use VBOs is creating them (using commands like glGenBuffers and glBufferData), and you have to bind them before calling glVertexPointer or glTexPointer. This is done with glBindBuffer(target, id) much like how you bind a texture (the target refers to if the VBO is vertex data or used for indices).

When you actually use glVertexPointer and that family of functions, instead of passing in a Buffer, you will pass in a byte offset into the currently bound VBO (which you usually will want to be 0).  A VBO stays bound until you bind something else or unbind it (using VBO id = 0) and you cannot call glVertexPointer (etc.) with a vertex array when a VBO is bound, so if you're mixing you'll want to make sure to unbind the VBOs when you're done rendering with them.

There aren't many differences between VBOs and vertex arrays.  Also, if the examples online differ I would just pick one to start with since they are likely all almost the same.  If you have problems with one example, you can post that with more specific problems.

Offline Addictman

Senior Devvie


Medals: 3
Projects: 1


Java games rock!


« Reply #4 - Posted 2011-03-29 17:10:54 »

Great explanation, thanks! I'll give my code a spin later tonight, and post a specific example if I run into problems. Again, thanks.
Offline gouessej
« Reply #5 - Posted 2011-03-30 09:19:42 »

If you could provide an example of VBO implementation (the more comments, the better!) I'll be grateful.
Look at the source code of TUER, I had written some wrapper classes for these things:
http://tuer.svn.sourceforge.net/viewvc/tuer/alpha/drawer/StaticVertexBufferObject.java

Offline Addictman

Senior Devvie


Medals: 3
Projects: 1


Java games rock!


« Reply #6 - Posted 2011-03-31 10:32:26 »

Thanks for the help so far Smiley

I currently have my VBO's drawing their stuff now, but sadly I'm still stuck at a sucky FPS. Perhaps the phones just aren't up to it...

Another question; I noticed glBufferSubData. Are there any known performance issues with using glBufferSubData contra glBufferData ? It seems [at least in my case] that it would be cleaner and easier to create buffers early, and bind them with a given size to a null buffer, and later push data to them using glBufferSubData. Thoughts on this?
Offline teletubo
« League of Dukes »

JGO Ninja


Medals: 48
Projects: 4
Exp: 8 years



« Reply #7 - Posted 2011-03-31 13:01:45 »

If you could provide an example of VBO implementation (the more comments, the better!) I'll be grateful.
Look at the source code of TUER, I had written some wrapper classes for these things:
http://tuer.svn.sourceforge.net/viewvc/tuer/alpha/drawer/StaticVertexBufferObject.java

Thank you for sharing this piece of code, Julian . I reached a point yesterday where I needed to use VBO's but was very very lazy to look for some code, glad it appeared magically here .

Offline teletubo
« League of Dukes »

JGO Ninja


Medals: 48
Projects: 4
Exp: 8 years



« Reply #8 - Posted 2011-03-31 17:20:24 »

ok now one question . If I'm using lots of glRotate, glTranslate before rendering stuff, can I use VBO's anyway ? will the rotations and transaltions apply to the vertex data I sent to the buffer in the loading phase ?

Offline lhkbob

JGO Knight


Medals: 32



« Reply #9 - Posted 2011-03-31 20:27:58 »

@Addictman: As long as you use glBufferData to allocate space on the graphics card, you can pass in a null buffer and fill it in with glBufferSubData.  What I like to do is use glBufferData the first time and pass in the data directly, and then any edits (even if it's the full buffer) use glBufferSubData.  I don't know if there is a performance hit or not, but it could be cleaner to do it your way.

@teletubo: You can use glRotate and glTranslate with VBOs.  Those are matrix functions that change the current transform that is applied to the vertices and normals.  This is independent of how you specify the vertices (either with vertex arrays, vbos or using glVertex, etc.)

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline teletubo
« League of Dukes »

JGO Ninja


Medals: 48
Projects: 4
Exp: 8 years



« Reply #10 - Posted 2011-03-31 20:40:11 »

@teletubo: You can use glRotate and glTranslate with VBOs.  Those are matrix functions that change the current transform that is applied to the vertices and normals.  This is independent of how you specify the vertices (either with vertex arrays, vbos or using glVertex, etc.)

Excelent, thanks !

So I guess I've screwed up somewhere in my code, because after I changed to VBO things just disappeared (though I get no errors).

Offline badlogicgames

« JGO Bitwise Duke »


Medals: 71
Projects: 2



« Reply #11 - Posted 2011-03-31 21:08:41 »

Do not use glBufferSubData on Android. The classes in our libgdx repository should give you some hint how to work with VBOs in an OpenGL ES context (no glMapBuffer etc...).

Your performance is unlikely to be related to whether you use VAs or VBOs. The hero is heavily fill-rate limited (like all other current Android devices). You'll have to tweak your texture filters/sizes. A tile map of 16x16 tiles is possible at 40fps on a Hero. Also, screen aligned quads (composed of two triangles) will trigger a fast path on G1 level hardware (Hero, Dream etc.). Don't rotate your stuff so that that gets triggered.

http://www.badlogicgames.com - musings on Android and Java game development
Offline gouessej
« Reply #12 - Posted 2011-04-04 11:21:23 »

Another question; I noticed glBufferSubData. Are there any known performance issues with using glBufferSubData contra glBufferData ? It seems [at least in my case] that it would be cleaner and easier to create buffers early, and bind them with a given size to a null buffer, and later push data to them using glBufferSubData. Thoughts on this?
glBufferSubData is nice to update a relatively small (<32KB, implementation-dependent) region of a VBO (but it has a poor implementation on some mobile phones). You can use it to update the whole data store of a VBO of course. The drawback is that you have to keep a NIO buffer in memory permanently to perform the updates (destroying explicitly a direct buffer is not the thing to do very frequently, look at sun.misc.Cleaner to do so) but it can be faster than mapping a whole VBO into virtual memory (look at glMapBuffer and glUnmapBuffer) to perform only a few updates. glMapBuffer & glUnmapBuffer allows to map a whole VBO into memory, it is less flexible than glBufferSubData as you cannot map/unmap only a region with this pair of calls but it allows to perform updates without having to store a permanent copy of the VBO.

Some people pretends that using glBufferData twice (once with null) to update a whole data store is faster than calling glBufferSubData but such a trick may force the graphics card to destroy a data store and then create a new one, I'm not sure it is a good idea.

As a conclusion, if you don't need to update your data very often, use glBufferData with null as a first step, use glMapBuffer to be able to modify the data store of the VBO and use glUnmapBuffer when your update is finished. If you use glBufferSubData to push your data only once, you will have to create a NIO buffer (instead of using the direct byte buffer returned by glMapBuffer) that you will use only once which is a bit inefficient even though it would work.

Edit.: I have not yet used glMapBuffer on my G1...

Offline princec

« JGO Spiffy Duke »


Medals: 421
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #13 - Posted 2011-04-04 11:48:04 »

Read this guy's blog.

Cas Smiley

Offline Addictman

Senior Devvie


Medals: 3
Projects: 1


Java games rock!


« Reply #14 - Posted 2011-04-05 08:38:07 »

Thanks for continued tips everyone! Smiley

I just came home from Barcelona, where the best friends anyone can have kidnapped me for my Bachelor's party/weekend. My brain is still mush, but I'll digest tidbits on everyone's advice and report back (probably with more questions), once I've done some further tests.

On a quick note, how you get 40 FPS on a Hero phone, with your screen filled with 16x16 tiles is beyond me. I get about 35 FPS without really doing anything but clear the buffer on each cycle Wink (which, I know is pretty curious once I found out).
Offline Addictman

Senior Devvie


Medals: 3
Projects: 1


Java games rock!


« Reply #15 - Posted 2011-04-06 13:45:55 »


Generating and binding buffers ...

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
        GL11 gl11 = (GL11)GLSettings.GL;
         
   int[] tempBuffer = new int[1];
     
   gl11.glGenBuffers(1, tempBuffer, 0);
   vertexBufferID = tempBuffer[0];
   gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, vertexBufferID);
        // Load The Data
        gl11.glBufferData(GL11.GL_ARRAY_BUFFER, getVertexDataSize(), vertexBuffer, GL11.GL_STATIC_DRAW);
        // Generate And Bind The Texture Coordinate Buffer
        gl11.glGenBuffers(1, tempBuffer, 0);  
        textureBufferID = tempBuffer[0];
        gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, textureBufferID);
        // Load The Data
        gl11.glBufferData(GL11.GL_ARRAY_BUFFER, getTexCoordsDataSize(), textureBuffer, GL11.GL_STATIC_DRAW);

        gl11.glGenBuffers(1, tempBuffer, 0);
        indexBufferID = tempBuffer[0];
        gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
        gl11.glBufferData(GL11.GL_ELEMENT_ARRAY_BUFFER, getIndexDataSize(), indexBuffer, GL11.GL_STATIC_DRAW);


Rendering ...
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  
        GL11 gl11 = (GL11)GLSettings.GL;
   gl11.glPushMatrix();
       
   gl11.glEnable(GL11.GL_TEXTURE_2D);
   gl11.glBindTexture(GL11.GL_TEXTURE_2D, textureID );
     
   // Enable Vertex Arrays
   gl11.glEnableClientState(GL11.GL_VERTEX_ARRAY);  
        // Enable Texture Coord Arrays
        gl11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);  
       
   gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, vertexBufferID);
        gl11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0);
       
        gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, textureBufferID);
        gl11.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0);
       
        gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
       
        gl11.glDrawElements(GL11.GL_TRIANGLES, numEntities * vertexConfig.numIndexesPrEntity, GL11.GL_UNSIGNED_SHORT, 0);
       
        // Unbind buffers
        gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, 0);
        gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0);
        // Disable states
        gl11.glDisableClientState(GL11.GL_VERTEX_ARRAY);  
        gl11.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);  
        gl11.glDisable(GL11.GL_TEXTURE_2D);
       
   gl11.glPopMatrix();


When these buffers are filled with vertices to fill my screen with 16*16 textures, I get a whooping 10 FPS (all other updates, and all other rendering commented out). Something must surely be wrong. Can anyone see any glaring errors here?
Offline badlogicgames

« JGO Bitwise Duke »


Medals: 71
Projects: 2



« Reply #16 - Posted 2011-04-06 23:07:42 »

As i said above, your problem is unlikely to be the transforms and hence amount of vertex data, but your textures. What size are they?

http://www.badlogicgames.com - musings on Android and Java game development
Offline badlogicgames

« JGO Bitwise Duke »


Medals: 71
Projects: 2



« Reply #17 - Posted 2011-04-06 23:09:07 »

I have not yet used glMapBuffer on my G1...

Yes, because that is not supported in OpenGL ES 1.x nor 2.0. Also, your advice of using glBufferSubData will be shit on ALL current Android phones.

http://www.badlogicgames.com - musings on Android and Java game development
Offline gouessej
« Reply #18 - Posted 2011-04-07 09:34:20 »

Yes, because that is not supported in OpenGL ES 1.x nor 2.0.
glMapBufferOES is not supported by Android GL but it is in OpenGL ES 1.x and 2.0:
http://www.khronos.org/registry/gles/extensions/OES/OES_mapbuffer.txt
It does not use exactly the same extension.

Also, your advice of using glBufferSubData will be shit on ALL current Android phones.
Ok, it's only fine on computers, thanks for the tip.

Offline Addictman

Senior Devvie


Medals: 3
Projects: 1


Java games rock!


« Reply #19 - Posted 2011-04-07 10:36:02 »

As i said above, your problem is unlikely to be the transforms and hence amount of vertex data, but your textures. What size are they?

16*16
Offline lhkbob

JGO Knight


Medals: 32



« Reply #20 - Posted 2011-04-07 13:51:39 »

Do you pack your 16x16 images into a single texture, or do you have to bind and unbind a different texture every time you draw a quad?

Offline Addictman

Senior Devvie


Medals: 3
Projects: 1


Java games rock!


« Reply #21 - Posted 2011-04-07 16:11:38 »

It's just one 16*16 texture that is rendered from one large VBO (with enough vertices to fill the screen). So, texture bound once pr. cycle, and one VBO is rendered pr. cycle using that texture. I am starting to think my phone is just ... fubar Sad

Thanks for continuing to give tips though Smiley
Offline lhkbob

JGO Knight


Medals: 32



« Reply #22 - Posted 2011-04-07 18:52:54 »

How many vertices are in the VBO?  I wouldn't think it would take that many vertices to tile across a phone's display.  They're smaller than 800x600, right?

To make sure I'm understanding you correctly, you're only use 1 texture and 1 VBO the entire frame (if that's what you mean by cycle).

Offline Addictman

Senior Devvie


Medals: 3
Projects: 1


Java games rock!


« Reply #23 - Posted 2011-04-07 19:07:24 »

Yeah, you're understanding me perfectly Smiley And yep, one frame ( I keep calling it loop cycle ). The display is indeed smaller, the phones are usually around 320 × 480 to 480 x 800. (The HTC Hero has 320x480). I stripped my entire loop down to rendering this one VBO (it currently has no update logic).

I'm more and more confident that something else is bothering my phone though, because even an entirely empty loop (all I'd do is clear the color/depth buffers) gives lousy FPS. I'm going to snag someone from work tomorrow and install it on their phone, to test this.
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.

trollwarrior1 (29 views)
2014-11-22 12:13:56

xFryIx (71 views)
2014-11-13 12:34:49

digdugdiggy (50 views)
2014-11-12 21:11:50

digdugdiggy (44 views)
2014-11-12 21:10:15

digdugdiggy (38 views)
2014-11-12 21:09:33

kovacsa (62 views)
2014-11-07 19:57:14

TehJavaDev (67 views)
2014-11-03 22:04:50

BurntPizza (64 views)
2014-11-03 18:54:52

moogie (80 views)
2014-11-03 06:22:04

CopyableCougar4 (80 views)
2014-11-01 23:36:41
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
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!