Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (576)
games submitted by our members
Games in WIP (498)
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  
  LWJGL Tutorial Series - Vertex Arrays  (Read 2005 times)
0 Members and 1 Guest are viewing this topic.
Offline SHC
« Posted 2013-09-08 17:31:49 »

LWJGL Tutorial Series - Vertex Arrays


Welcome to the part 6 of the LWJGL Tutorial Series. If you didn't read the previous ones, here is the link to the contents of this series. I recommend to read the previous ones if you are new to OpenGL, but otherwise there should be no problem with skipping them. In this tutorial, I'm going to explain Vertex Arrays. If there are any mistakes or need corrections or improvements, please notify them so that I can improve the article as well as my knowledge.

Vertex Arrays


Vertex Arrays are invented to solve a problem with Display Lists, that is they can be modified unlike display lists. There is no much performance gain than display lists these days but vertex arrays give good performance than immediate mode. (There is almost 10 fps gain over display lists and over 100 fps gain over immediate mode when tested on my computer)

The process involves creation of buffers and fill them with values. You can change the values later if you want. These give some gain in performance since these are only arrays in OpenGL's managed memory. Then we bind the buffers to OpenGL context and render them. In this example, we are going to render a square first and texture it. Now that you know the process, let's now get into their creation.

Creating Vertex Arrays


We're now ready for some code so let me show you the creation code first and later explain it line by line.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
// VA of the rectangle.
FloatBuffer rect;

public void init()
{
    // OpenGL setup code

    // Create a float buffer with the help of BufferUtils.
   rect = BufferUtils.createFloatBuffer(2 * 4);
}

We have a float buffer and we initialized it. The argument
2 * 4
means
two coordinates of four vertices
that is we will specify the two x and y coordinates of the four vertices of the rectangle. This creates an empty vertex array and it's time for us to fill it with values. Let's now fill the vertices as an array of float values.

1  
2  
3  
4  
5  
6  
7  
8  
rect.put(new float[]
{
  // X    Y
    0,   0,    // <- First vertex
    100, 0,    // <- Second vertex
    100, 100,  // <- Third vertex
    0,   100   // <- Fourth vertex
});

We are done with the first part, creating vertex arrays. The next part remaining is to render the rectangle to screen.

Rendering to Screen


Ok, we are now ready to render it to the screen. Before rendering, we have to say OpenGL that we want to render a vertex array. In the render method, we do

1  
glEnableClientState(GL_VERTEX_ARRAY);

This enables the rendering of vertex arrays. Now, we've to rewind the buffer to reset the reading pointer and set the vertex pointer to the float buffer we made.

1  
2  
3  
rect.rewind();
// Set the vertex pointer.
glVertexPointer(2, 0, rect);

This is the syntax of
glVertexPointer()
function.

1  
2  
3  
4  
5  
6  
7  
8  
9  
/**
 * Set the vertex pointer. If stride is 0, the vertices
 * are understood to be tightly packed in the array.
 *
 * @param size The number of components in each vertex
 * @param stride The byte offset between consecutive vertices.
 * @param pointer The float buffer of our vertex array
 */

void glVertexPointer(int size, int stride, FloatBuffer pointer);

And now to finally render, we use the
glDrawArrays()
function. We call it like this.

1  
2  
// glDrawArrays(int type, int start, int count)
glDrawArrays(GL_QUADS, 0, 4);

What does this mean? The
type
says what does those vertices make. We say
GL_QUADS
since we want to render a rectangle. The parameter
start
represents the start of index in the buffer and the parameter
count
refers to the number of vertices to be rendered from that buffer. This sends the vertex data from the buffer and now, we disable that client state.

1  
glDisableClientState(GL_VERTEX_ARRAY);

And when you run this, you can see the usual white rectangle but this time, it is rendered with vertex arrays. Okay that we've learnt how to draw a rectangle. What about the texture? Well, let's see that too.

Texture Arrays


We create another float buffer and fill it the texture coordinates. Next we enable texture arrays and set the texture pointer. Let's start with the making the float buffer. Make sure you loaded the texture using our Texture class.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
tex = BufferUtils.createFloatBuffer(2 * 4);

tex.put(new float[]
{
    // X    Y
      0,   0,    // <- First texture coord
      1,   0,    // <- Second texture coord
      1,   1,    // <- Third texture coord
      0,   1     // <- Fourth texture coord
});

Now that we've created and filled in values, let's go to the render method. We have to enable
GL_TEXTURE_COORD_ARRAY
but bind the texture before we enable the arrays.

1  
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

And now we set the texture pointer with
glTexCoordPointer()
function which accepts the same parameters as the
glVertexPointer()
function.

1  
2  
3  
glTexCoordPointer(2, 0, tex);
// Rewind the buffer
tex.rewind();

Place the above calls before the call to
glDrawArrays()
function. At the end, disable this client state as well. Now, the complete render function looks like this. Please do not confuse with variables
texture
and
tex
which are the texture and texture coordinates respectively.

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  
public void render()
{
    // Clear the screen
   glClear(GL_COLOR_BUFFER_BIT);

    // Bind the texture
   glBindTexture(GL_TEXTURE_2D, texture.id);

    // Enable Vertex Arrays and Texture Coord Arrays
   glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    // Rewind the buffers to beginning
   rect.rewind();
    tex.rewind();

    // Set the pointers to them
   glTexCoordPointer(2, 0, tex);
    glVertexPointer(2, 0, rect);

    // Draw them
   glDrawArrays(GL_QUADS, 0, 4);

    // Disable vertex arrays and texture coord arrays
   glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}

Now running the code, you can see this.



If there are any mistakes or corrections, please notify me with comments. That's the end of part 6 and in the next tutorial in this series, we'll learn about 'Vertex Buffer Objects'

Source Code


Tutorial6.java

Offline RobinB

JGO Knight


Medals: 37
Projects: 1
Exp: 3 years


Spacegame in progress


« Reply #1 - Posted 2013-09-08 18:16:33 »

Nice tutorial!
However you cant really know how much 10/100 fps is.
It would be more clear if you would say something like "500 to 400 fps", or just "the fps increased with X%".
Offline SHC
« Reply #2 - Posted 2013-09-08 18:20:51 »

@RobinB

Thanks. What I mean with it was "the fps is more than the fps of display list by 10 and it is more than immediate mode by 100". Here are the readings after 5 seconds of launch.

Immediate mode: 568 fps
Display Lists: 689 fps
Vertex Arrays: 703 fps

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Online Magn919

Junior Member


Medals: 6
Exp: 4 years



« Reply #3 - Posted 2013-09-08 18:45:35 »

You do know that Vertex Arrays and Vertex Array Objects aren't the same thing right?

VAOs are used to store the state of Vertex Buffer Objects and VAs are for batching data like what your are describing in the tutorial.

For every new problem, a new source of solutions has come to exist.
Offline quew8

JGO Coder


Medals: 23



« Reply #4 - Posted 2013-09-08 18:52:58 »

Nice, except what you describe here isn't a VAO. From the OpenGL wiki:
Quote
A Vertex Array Object (VAO) is an OpenGL Object that encapsulates all of the state needed to specify vertex data (with one minor exception noted below). They define the format of the vertex data as well as the sources for the vertex arrays. Note that VAOs do not contain the arrays themselves; the arrays are stored in Buffer Objects (see below). The VAOs simply reference already existing buffer objects.
. I'm not sure what you would call this technique, maybe a vertex stream?

Edit: Magn919 beat me to it AND got the name right.
Offline SHC
« Reply #5 - Posted 2013-09-08 18:57:37 »

@quew8
@Magn919

That's what I'm doing right? I'm creating buffers with arrays and setting VAO pointer to those buffers. I didn't understand what you say completely though. I studied this topic this morning only. Can you explain a bit more?

Offline RobinB

JGO Knight


Medals: 37
Projects: 1
Exp: 3 years


Spacegame in progress


« Reply #6 - Posted 2013-09-08 19:01:07 »

VAO is an buffer for these pointers.
VBO is using these pointers to draw stuff.
Offline SHC
« Reply #7 - Posted 2013-09-08 19:04:08 »

@RobinB

I'm thinking that VBO is an ARB extension that tries to keep the buffers on the GPU itself without sending them every loop. Am I correct?

Offline quew8

JGO Coder


Medals: 23



« Reply #8 - Posted 2013-09-08 19:05:17 »

Nah.

VBO - An OpenGL buffer containing vertex or index data.
VAO - An OpenGL object listing which VBOs to use and how to use them.
Vertex Array - An (non-OpenGL) array containing vertex or index data. It's a little confusing calling it an array when in LWJGL we use java Buffers but that's just the method LWJGL uses to move data to the native layer.
Offline SHC
« Reply #9 - Posted 2013-09-08 19:22:34 »

Thanks. Changed the name of article to 'Vertex Arrays'

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline HeroesGraveDev

JGO Kernel


Medals: 212
Projects: 11
Exp: 2 years


If it wasn't Awesome, it wasn't me.


« Reply #10 - Posted 2013-09-09 07:50:18 »

It should be noted that while for one quad, immediate mode is faster, for any game, you should use Vertex Arrays (or better, VBOs) as they are faster when it comes to more vertices.

Offline davedes
« Reply #11 - Posted 2013-09-09 19:46:51 »

Quote
It should be noted that while for one quad, immediate mode is faster, for any game, you should use Vertex Arrays (or better, VBOs) as they are faster when it comes to more vertices.
This is a pretty vague generalization that is highly dependent on the hardware.

Regarding Vertex Arrays vs. VBOs, at least on many Android drivers, Mario had found vertex arrays to be more performant than VBOs for the specific use-case of sprite batching (i.e. many flushes per frame). See here:
https://github.com/libgdx/libgdx/pull/346

On desktop you can use mapped VBOs which should be faster than vertex arrays:
http://www.java-gaming.org/index.php?topic=28209.0

Or another technique, like texture arrays to improve batching.

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.

xsi3rr4x (16 views)
2014-04-15 18:08:23

BurntPizza (14 views)
2014-04-15 03:46:01

UprightPath (27 views)
2014-04-14 17:39:50

UprightPath (12 views)
2014-04-14 17:35:47

Porlus (29 views)
2014-04-14 15:48:38

tom_mai78101 (51 views)
2014-04-10 04:04:31

BurntPizza (110 views)
2014-04-08 23:06:04

tom_mai78101 (211 views)
2014-04-05 13:34:39

trollwarrior1 (179 views)
2014-04-04 12:06:45

CJLetsGame (185 views)
2014-04-01 02:16:10
List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:05:20
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!