Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (477)
Games in Android Showcase (107)
games submitted by our members
Games in WIP (534)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1] 2
  ignore  |  Print  
  How to use a VBO  (Read 1541 times)
0 Members and 1 Guest are viewing this topic.
Offline AppleSauce
« Posted 2014-06-14 01:03:11 »

I'm trying really hard to understand this, but some of the code I don't understand.

First off, to my understanding, this just creates the points for the triangle.
1  
2  
3  
FloatBuffer vertexData = BufferUtils.createFloatBuffer(amountOfVertices * vertexSize);
        vertexData.put(new float[]{-0.5f, -0.5f, 0, 0.5f, -0.5f, 0, 0.5f, 0.5f, 0});
        vertexData.flip();



Now this here would initialize it?

1  
2  
3  
4  
int vboVertexHandle = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle);
        glBufferData(GL_ARRAY_BUFFER, vertexData, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);


and under my gameloop this would bind/draw the triangle?
1  
2  
glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle);
            glVertexPointer(vertexSize, GL_FLOAT, 0, 0L);


I think this just tells you it's a triangle.
1  
2  
3  
4  
5  
       glEnableClientState(GL_VERTEX_ARRAY);
            glEnableClientState(GL_COLOR_ARRAY);
            glDrawArrays(GL_TRIANGLES, 0, amountOfVertices);
            glDisableClientState(GL_COLOR_ARRAY);
            glDisableClientState(GL_VERTEX_ARRAY);


As you can see, I'm not so knowledgable on VBOs. Can i get some explanation or a link to a good in depth tutorial for this?
Offline Seiya02

JGO Coder


Medals: 4
Projects: 4
Exp: 5 years


No Text Here :x


« Reply #1 - Posted 2014-06-14 01:18:46 »

For VBOs:

Generate an ID for the VBO:
1  
2  
3  
4  
int ID = 0;
IntBuffer buffer = BufferUtils.createIntBuffer(1);
ARBVertexBufferObject.glGenBuffersARB(buffer);
ID = buffer.get(0);


Put Coordinates into Buffer:
1  
2  
3  
FloatBuffer buffer = BufferUtils.createFloatBuffer(amountOfVertices * vertexSize);
buffer.put(new float[]{-0.5f, -0.5f, 0, 0.5f, -0.5f, 0, 0.5f, 0.5f, 0});
buffer.flip();


Connect Generated ID with Buffer that stores Coordinates:
1  
2  
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, ID);
ARBVertexBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, buffer,ARBVertexBufferObject.GL_STATIC_DRAW_ARB);


And finally, for Drawing:
1  
2  
3  
4  
5  
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY); 
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, ID);
GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0);// The 3 stands for each vertex having 3 parts (x y and z) for colors for example it has 4, r g b and a
GL12.glDrawRangeElements(GL11.GL_TRIANGLES, 0, length, length,GL11.GL_UNSIGNED_INT, 0); // So it Renders Triangles, could render Quads too etc. I guess, never tested it
GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);


I think you would need an Index Buffer aswell and "length" stands for the length of the index Buffer Smiley those are some snippets from my code
Offline The Lion King
« Reply #2 - Posted 2014-06-14 01:21:19 »

Your computer contains a CPU and a GPU. Just for simplicity, you can think that the CPU and the GPU has their own memory. In other words The GPU can't directly access memory in your CPU and visa-versa. However, you can send data to the GPU to have it render. One way to do this is to send all your vertices on every single draw call and have the GPU do the rest. This mode of rendering was useful years ago when GPUs were not the powerful beasts they are today. It is known as immediate mode rendering.

Now a more sensical way to go about this problem is to create a place where you can save the data in the GPU, so you don't have to send it every single frame. This memory in the GPU (or in anything in that case) is called a buffer.

Now in C and other system languages you deal with memory a lot more directly and there is no JVM and other things moving things around and doing weird stuff with your data. In Java we have another step in VBO rendering. We make a FloatBuffer, (a buffer on the CPU), and store our data inside it. Now think of your memory as a strip of paper, and the computer memory writer as the head of a printer. Now as the "printer puts data on the paper" the head moves away from the beginning of the data. We need to move the head back to the beggining of the data so that we can specify where the data starts. One call to do that is flip the other is reverse. They both work in this case (but they do have a difference in other cases).

Ok, so we have made our FloatBuffer on the CPU now we have to make our Buffer on the GPU.
This is just a simple glGenBuffers. The "handle" is like the address on the GPU where it resides.

OpenGL is a state based api. A state is like a characteristic or a variable in an object. There can only be one "state" binded to a characteristic at a time. One of these variables in OpenGL is GL_ARRAY_BUFFER, this is just characteristic that explains which VBO is currently being used at the time. You can only have one binded at the time.

So I have a buffer on my CPU and GPU, but the data is only on the CPU. I have to copy my data into the data on the GPU. So first i bind the buffer to tell OpenGL that I am going to make changes to the buffer. Next I send my data over using a glBufferData call.

Cool now i have lots of random 1s and 0s on the GPU, this isn't that useful without explaining to the GPU what these 1s and 0s mean. This is pretty much the part where i turn my Buffer into a Vertex Buffer Object.

I use glVertexPointer, glColorPointer, etc. to explain to the GPU which 1's and 0's mean what. I point to which pieces of the buffer are vertices, colors, texture coords, etc.

Ok, so our VBO is set, The GPU has it's data and an explanation of what every piece means. Now we can run a draw call (with the buffer binded) and openGL will draw whatever we want.

Remember the state things I was talking about earlier. There are a couple "client states" that openGL also has. This states simply tell OpenGL what pieces of data to use when rendering. Should it ignore the color values, or use them. ETC. If not specified it ignores it.

I think I got the majority of it.

Lots of this is metaphorical (aka. not what "actually" happens), but hopefully it will make it much easier for you to visualize.

"You have to want it more than you want to breath, then you will be successful"
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline AppleSauce
« Reply #3 - Posted 2014-06-14 01:24:42 »

@Seiya02 What's the point of ID?

@The Lion King Great, in depth explanation. I'm still pretty lost. Any visuals?

EDIT: I'm learning based off of Oskar Veerhoaks' tutorial:

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  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
 public static void main(String[] args) {
        try {
            Display.setDisplayMode(new DisplayMode(640, 480));
            Display.setTitle("Vertex Buffer Object Demo");
            Display.create();
        } catch (LWJGLException e) {
            e.printStackTrace();
            Display.destroy();
            System.exit(1);
        }

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(1, -1, 1, -1, 1, -1);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        final int amountOfVertices = 3;
        final int vertexSize = 3;
        final int colorSize = 3;

        FloatBuffer vertexData = BufferUtils.createFloatBuffer(amountOfVertices * vertexSize);
        vertexData.put(new float[]{-0.5f, -0.5f, 0, 0.5f, -0.5f, 0, 0.5f, 0.5f, 0});
        vertexData.flip();

        FloatBuffer colorData = BufferUtils.createFloatBuffer(amountOfVertices * colorSize);
        colorData.put(new float[]{1, 0, 0, 0, 1, 0, 0, 0, 1});
        colorData.flip();

        int vboVertexHandle = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle);
        glBufferData(GL_ARRAY_BUFFER, vertexData, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        int vboColorHandle = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vboColorHandle);
        glBufferData(GL_ARRAY_BUFFER, colorData, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        while (!Display.isCloseRequested()) {
            glClear(GL_COLOR_BUFFER_BIT);

           
            //to load a texture, create it then do this
           //glBindTexture(GL_TEXTURE_2D, nameoftexture.getTextureID());
           
           
            glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle);
            glVertexPointer(vertexSize, GL_FLOAT, 0, 0L);

            glBindBuffer(GL_ARRAY_BUFFER, vboColorHandle);
            glColorPointer(colorSize, GL_FLOAT, 0, 0L);
           
           
            glEnableClientState(GL_VERTEX_ARRAY);
            glEnableClientState(GL_COLOR_ARRAY);
            glDrawArrays(GL_TRIANGLES, 0, amountOfVertices);
            glDisableClientState(GL_COLOR_ARRAY);
            glDisableClientState(GL_VERTEX_ARRAY);

            Display.update();
            Display.sync(60);
        }

        glDeleteBuffers(vboVertexHandle);
        glDeleteBuffers(vboColorHandle);

        Display.destroy();
        System.exit(0);
    }
}
Offline The Lion King
« Reply #4 - Posted 2014-06-14 01:27:25 »

No visuals on hand, I could probably draw some up with paint and edit the post tomorrow. Post any specific questions if you have them though.


"You have to want it more than you want to breath, then you will be successful"
Offline AppleSauce
« Reply #5 - Posted 2014-06-14 01:32:32 »

Okay, I'll piece by piece. First off

1  
2  
3  
4  
5  
6  
7  
 final int amountOfVertices = 3; //do I just make this 4 if I want a
       final int vertexSize = 3;    //quad/
       final int colorSize = 3;

        FloatBuffer vertexData = BufferUtils.createFloatBuffer(amountOfVertices * vertexSize);
        vertexData.put(new float[]{-0.5f, -0.5f, 0, 0.5f, -0.5f, 0, 0.5f, 0.5f, 0});
        vertexData.flip();




What exactly are these methods supposed to do? Do they initialize how your going to draw things? If I made a second shape or made a quad, would these change in any way?

1  
2  
3  
4  
  int vboVertexHandle = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle);
        glBufferData(GL_ARRAY_BUFFER, vertexData, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);


Since this is in the game loop, and this gets called every frame, does this actually draw it?
1  
2  
glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle);
            glVertexPointer(vertexSize, GL_FLOAT, 0, 0L);


Since this gets enabled and then disabled, does this draw it?
1  
2  
3  
4  
5  
glEnableClientState(GL_VERTEX_ARRAY);
            glEnableClientState(GL_COLOR_ARRAY);
            glDrawArrays(GL_TRIANGLES, 0, amountOfVertices);
            glDisableClientState(GL_COLOR_ARRAY);
            glDisableClientState(GL_VERTEX_ARRAY);
Offline The Lion King
« Reply #6 - Posted 2014-06-14 01:37:27 »

First one builds the Data Buffer holding your data on the CPU.

The second one builds a buffer on the GPU and move your data from the CPU to the GPU.

The 3rd one tells the GPU which piece of the data is the vertices, colors, etc.

The 4th one tells the GPU to use the vertices and colors from the data in the buffer to draw triangles

"You have to want it more than you want to breath, then you will be successful"
Offline AppleSauce
« Reply #7 - Posted 2014-06-14 02:39:05 »

I sort of got the hang of this(after 5 hours of struggly literally!). So, if I wanted to create another triangle I would make another FloatBuffer and a copy of everything?
Offline AppleSauce
« Reply #8 - Posted 2014-06-14 03:28:48 »

I give up on VBOs  Cranky. I wasted almost 10 hours whatching the same video and doing research. Appearently I can only render one thing with VBO. I tried rearanging things as much as I could. It's driving me insane! I tried initializing everything for a second triangle, but it doesn't appear.  Angry
Offline The Lion King
« Reply #9 - Posted 2014-06-14 03:32:38 »

put the extra data in the FloatBuffer, put that extra data into the VBO, change the length in verticies of the glDrawArrays call, that should be it I believe

"You have to want it more than you want to breath, then you will be successful"
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline AppleSauce
« Reply #10 - Posted 2014-06-14 03:36:19 »

put the extra data in the FloatBuffer, put that extra data into the VBO, change the length in verticies of the glDrawArrays call, that should be it I believe

Wouldn't this just connect to the first triangle? I want to draw a second one to ensure my knowledge.
Offline Mr.CodeIt

Junior Member





« Reply #11 - Posted 2014-06-14 03:49:44 »

Just use Immediate mode. Much better no matter how old  Tongue

I'm not drunk, I've just been up late coding.
Offline theagentd
« Reply #12 - Posted 2014-06-14 04:19:38 »

1  
2  
glDrawArrays(GL_TRIANGLES, 0, 3); //Draw triangle 1 in the VBO
glDrawArrays(GL_TRIANGLES, 3, 3); //Draw triangle 2 in the VBO


If you have multiple VBOs, you need to set up the vertex attribute pointers correctly every time you want to switch between VBOs so OpenGL reads from the correct one.


Just use Immediate mode. Much better no matter how old  Tongue
Immediate mode is deprecated for a reason.

Myomyomyo.
Offline The Lion King
« Reply #13 - Posted 2014-06-14 05:26:21 »

put the extra data in the FloatBuffer, put that extra data into the VBO, change the length in verticies of the glDrawArrays call, that should be it I believe

Wouldn't this just connect to the first triangle? I want to draw a second one to ensure my knowledge.

No, its like sprite batching you send it the data for all the traingles and call glDrawArrays once. It will draw all the triangles seperate, unless you use triangle strips in which case they are attached

"You have to want it more than you want to breath, then you will be successful"
Offline AppleSauce
« Reply #14 - Posted 2014-06-14 17:44:39 »

1  
2  
glDrawArrays(GL_TRIANGLES, 0, 3); //Draw triangle 1 in the VBO
glDrawArrays(GL_TRIANGLES, 3, 3); //Draw triangle 2 in the VBO


If you have multiple VBOs, you need to set up the vertex attribute pointers correctly every time you want to switch between VBOs so OpenGL reads from the correct one.


Just use Immediate mode. Much better no matter how old  Tongue
Immediate mode is deprecated for a reason.

Do I have to create a whole float buffere and vboHandler in order to use glDrawArrays to make another triangle?
Offline Longarmx
« Reply #15 - Posted 2014-06-14 17:50:13 »

Do I have to create a whole float buffere and vboHandler in order to use glDrawArrays to make another triangle?

No, that's what we're trying to tell you. If you're using GL_TRIANGLES, then it will draw a completely separate triangle if you just supply the necessary vertices.

Offline SHC
« Reply #16 - Posted 2014-06-14 17:53:46 »

Wait, is this your question? http://gamedev.stackexchange.com/questions/77622/using-vbos-for-the-begginer

Offline AppleSauce
« Reply #17 - Posted 2014-06-14 18:50:46 »

Do I have to create a whole float buffere and vboHandler in order to use glDrawArrays to make another triangle?

No, that's what we're trying to tell you. If you're using GL_TRIANGLES, then it will draw a completely separate triangle if you just supply the necessary vertices.

So for the first triangle I would do this In my loop:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle);
            glVertexPointer(vertexSize, GL_FLOAT, 0, 0L);


            glBindBuffer(GL_ARRAY_BUFFER, vboColorHandle);
            glColorPointer(colorSize, GL_FLOAT, 0, 0L);


            glEnableClientState(GL_VERTEX_ARRAY);
            glEnableClientState(GL_COLOR_ARRAY);
            glDrawArrays(GL_TRIANGLES, 0, amountOfVertices);
            glDisableClientState(GL_COLOR_ARRAY);
            glDisableClientState(GL_VERTEX_ARRAY);


Then In the second one:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle2);
            glVertexPointer(vertexSize, GL_FLOAT, 0, 0L);


            glBindBuffer(GL_ARRAY_BUFFER, vboColorHandle2);
            glColorPointer(colorSize, GL_FLOAT, 0, 0L);


            glEnableClientState(GL_VERTEX_ARRAY);
            glEnableClientState(GL_COLOR_ARRAY);
            glDrawArrays(GL_TRIANGLES, 0, amountOfVertices);
            glDisableClientState(GL_COLOR_ARRAY);
            glDisableClientState(GL_VERTEX_ARRAY);


Would it require a second handler?



Yeah, I'm trying hard to understand this. Thanks for your website, I forgot about it.
Offline AppleSauce
« Reply #18 - Posted 2014-06-14 19:08:24 »

If anyone could explain visually, I could really use the help.

Skype: minecraft13jay
Offline Longarmx
« Reply #19 - Posted 2014-06-14 19:08:47 »

You don't need a separate handle.

Just add more vertices in your float array.

1  
2  
// You will have to play around with the vertices
new float[]{-0.5f, -0.5f, 0, 0.5f, -0.5f, 0, 0.5f, 0.5f, 0/*end of first triangle*/, -0.75f, -0.75f, 0, 0.75f, -0.75f, 0, 0f, 0f, 0}


Every vertex has a color, so you would add more colors.

1  
new float[]{1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1}


You will also have to change
amountOfVertices
to match how many vertices you have.

Offline AppleSauce
« Reply #20 - Posted 2014-06-14 19:11:11 »

Oh! Thanks very much! No extra handles? Just add 3 verticies for every triangle?  Shocked

EDIT: My triangle just flipped after I added the extra verticies and points to the vertex Data.
Offline SHC
« Reply #21 - Posted 2014-06-14 19:12:23 »

For the second triangle, it is as simple as creating the vertices again, like this.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
vertices.put(new float[]
{
    // First Triangle
   20, 20,
    10, 40,
    30, 40,

    // Second Triangle
   40, 40,
    30, 60,
    50, 60
});

These vertices create two side by side triangles. For more triangles, you can keep adding to the buffer. However, only when using
GL_TRIANGLES
mode. In that mode, OpenGL renders first three vertices as one triangle and the next three as another triangle.

However, if you are using
GL_TRIANGLE_STRIP
mode, then it creates a connected shape (not necessarily a triangle). And since we find ourselves using
GL_TRIANGLE_STRIP
or other primitives rarely except
GL_TRIANGLES
, it will create two separate triangles.

Hope this helps.

Offline AppleSauce
« Reply #22 - Posted 2014-06-14 19:14:55 »

For the second triangle, it is as simple as creating the vertices again, like this.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
vertices.put(new float[]
{
    // First Triangle
   20, 20,
    10, 40,
    30, 40,

    // Second Triangle
   40, 40,
    30, 60,
    50, 60
});

These vertices create two side by side triangles. For more triangles, you can keep adding to the buffer. However, only when using
GL_TRIANGLES
mode. In that mode, OpenGL renders first three vertices as one triangle and the next three as another triangle.

However, if you are using
GL_TRIANGLE_STRIP
mode, then it creates a connected shape (not necessarily a triangle). And since we find ourselves using
GL_TRIANGLE_STRIP
or other primitives rarely except
GL_TRIANGLES
, it will create two separate triangles.

Hope this helps.

It helps. In the
1  
verticies.put
, instead of putting each triangle, could I have just call
1  
put
every time I want to draw another triangle?
Offline SHC
« Reply #23 - Posted 2014-06-14 19:19:26 »

Yes that works too.

Offline AppleSauce
« Reply #24 - Posted 2014-06-14 19:32:28 »

Adding more points only flipped the triangle. Now I can't even get the first one to appear.
Offline AppleSauce
« Reply #25 - Posted 2014-06-14 19:47:59 »

Are there any good tutorials that explain VBOs and VAs? I just can't figure any of this out.
Offline AppleSauce
« Reply #26 - Posted 2014-06-14 20:16:25 »

Oh god, I finally figure it out. Sorry for the horrendous amount of posts, but all I ask now is how do I convert float points to regular integers.(instead of -o.5f, I want to use somthing like 5)
Offline Longarmx
« Reply #27 - Posted 2014-06-14 21:53:26 »

You need to change glOrtho to use pixel coordinates.

1  
glOrtho(0, width, 0, height, -1f, 1f);


Where width and height are the dimensions of your window.

Offline AppleSauce
« Reply #28 - Posted 2014-06-14 22:32:49 »

I did that and I tried the coordinates:

1  
vertexData.put(new float[]{0, 0, 0, /**/ 10, 0, 0, /**/ 10, 10, 0});


Everything disapeared.
Offline Longarmx
« Reply #29 - Posted 2014-06-15 00:04:11 »

A lot of things could have gone wrong...

Try printing out glGetError();

Pages: [1] 2
  ignore  |  Print  
 
 

 

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 (35 views)
2014-07-24 01:59:36

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

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

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

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

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

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

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

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

Riven (56 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!