• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
BytePtr

Upgrading from glVertex3f to Vertex Arrays

7 posts in this topic

Hi.

Many times i have read that glVertex calls are deprecated and shouldn't be used.
I work on my map editor that currently uses: glBegin, glEnd, glVertex3f etc.

Map is made of blocks (maximum 50 different blocks). The coordinates of each block are hard-coded into header file.
Array is made for getting the coordinates by block index: 1..50.

One cube example of that data (these coordinates is used by glVertex3f):

[code]float CUBE_RAW_DATA[numCubeTypes][numSides][4][3] = {
{ // CUBE1
{ // FACE 1
{ 0.00, 0.00, 1 },
{ 1.00, 0.00, 1 },
{ 1.00, 0.50, 0 },
{ 0.00, 0.50, 0 }
},
{ // FACE 2
{ 1.00, 0.00, 1 },
{ 0.00, 0.00, 1 },
{ 0.00, 0.00, 1 },
{ 1.00, 0.00, 1 }
},
{ // FACE 3
{ 0.00, 0.50, 0 },
{ 1.00, 0.50, 0 },
{ 1.00, 0.00, 0 },
{ 0.00, 0.00, 0 }
},
{ // FACE 4
{ 0.00, 0.00, 1 },
{ 0.00, 0.50, 0 },
{ 0.00, 0.00, 0 },
{ 0.00, 0.00, 1 }
},
{ // FACE 5
{ 1.00, 0.50, 0 },
{ 1.00, 0.00, 1 },
{ 1.00, 0.00, 1 },
{ 1.00, 0.00, 0 }
}
},
...
};[/code]

Each cube face is drawn like this:

[code]int Which = 1; // Draw CUBE NR 1 :: SIDE1

glBindTexture(GL_TEXTURE_2D, SIDE1_TEX);
glBegin(GL_QUADS);
for (int j=0; j < 4; j++) {
glVertex3f(CUBE_RAW_DATA[Which][0][j][0],
CUBE_RAW_DATA[Which][0][j][1],
CUBE_RAW_DATA[Which][0][j][2]);
}
glEnd();
};[/code]

These ( i mean commands to draw each side) are called in every frame. Because i need to react to map array changes. If in some map coordinates the CUBE ID changes, then it means, it must take specific cube with that index from the CubeData array and draw it.
Same is done for texture coordinates, i mean they are also hard-coded.

So, what's the "best" way to convert this to vertex arrays?
Of course, i need to include texture coordinates. Each cube side can have it's own textureID.


Can somebody please post me some structs or something like that, just to restructure my rendering method using vertex arrays.
Should i make struct like:

[code] struct TVertex {
float position[3];
float normal[3];
int textureID;
struct TTexCoord {
float tu, tv;
};
};[/code]

Make some array and use it for each cube? Maybe im completely wrong. I just don't know how to make it better or rewrite it for vertex arrays.

I don't ask you to code for me but just general directions how i should do this.


That's why i ask your help.

TIA.
0

Share this post


Link to post
Share on other sites
[quote name='BytePtr' timestamp='1312325152' post='4843808']
Hi.

Many times i have read that glVertex calls are deprecated and shouldn't be used.
I work on my map editor that currently uses: glBegin, glEnd, glVertex3f etc.

Map is made of blocks (maximum 50 different blocks). The coordinates of each block are hard-coded into header file.
Array is made for getting the coordinates by block index: 1..50.

One cube example of that data (these coordinates is used by glVertex3f):

[code]float CUBE_RAW_DATA[numCubeTypes][numSides][4][3] = {
{ // CUBE1
{ // FACE 1
{ 0.00, 0.00, 1 },
{ 1.00, 0.00, 1 },
{ 1.00, 0.50, 0 },
{ 0.00, 0.50, 0 }
},
{ // FACE 2
{ 1.00, 0.00, 1 },
{ 0.00, 0.00, 1 },
{ 0.00, 0.00, 1 },
{ 1.00, 0.00, 1 }
},
{ // FACE 3
{ 0.00, 0.50, 0 },
{ 1.00, 0.50, 0 },
{ 1.00, 0.00, 0 },
{ 0.00, 0.00, 0 }
},
{ // FACE 4
{ 0.00, 0.00, 1 },
{ 0.00, 0.50, 0 },
{ 0.00, 0.00, 0 },
{ 0.00, 0.00, 1 }
},
{ // FACE 5
{ 1.00, 0.50, 0 },
{ 1.00, 0.00, 1 },
{ 1.00, 0.00, 1 },
{ 1.00, 0.00, 0 }
}
},
...
};[/code]

Each cube face is drawn like this:

[code]int Which = 1; // Draw CUBE NR 1 :: SIDE1

glBindTexture(GL_TEXTURE_2D, SIDE1_TEX);
glBegin(GL_QUADS);
for (int j=0; j < 4; j++) {
glVertex3f(CUBE_RAW_DATA[Which][0][j][0],
CUBE_RAW_DATA[Which][0][j][1],
CUBE_RAW_DATA[Which][0][j][2]);
}
glEnd();
};[/code]

These ( i mean commands to draw each side) are called in every frame. Because i need to react to map array changes. If in some map coordinates the CUBE ID changes, then it means, it must take specific cube with that index from the CubeData array and draw it.
Same is done for texture coordinates, i mean they are also hard-coded.

So, what's the "best" way to convert this to vertex arrays?
Of course, i need to include texture coordinates. Each cube side can have it's own textureID.


Can somebody please post me some structs or something like that, just to restructure my rendering method using vertex arrays.
Should i make struct like:

[code] struct TVertex {
float position[3];
float normal[3];
int textureID;
struct TTexCoord {
float tu, tv;
};
};[/code]

Make some array and use it for each cube? Maybe im completely wrong. I just don't know how to make it better or rewrite it for vertex arrays.

I don't ask you to code for me but just general directions how i should do this.


That's why i ask your help.

TIA.
[/quote]

You could use Display Lists instead, they would speed up your rendering adn you don't need to change much.

It is like:

int dl;
glGenList(dl);

glNewList(id);
//your rendering here
glEndList();

Then to call it:
glCallList(dl);
0

Share this post


Link to post
Share on other sites
You shouldn't quote so long posts.

The display lists do not help anything. I have tried them and i don't see any difference. And they are also old.
I tried to draw "some" cubes with vertex arrays and i saw performance improvements i really liked.

In my editor there could be alot of cubes visible and there always is, so speed is important.


But i don't know how to restructure the code / array of coordinates for vertex arrays.
So i could still draw them by index.


Thank you anyway.
0

Share this post


Link to post
Share on other sites
[quote name='BytePtr' timestamp='1312325152' post='4843808']
Should i make struct like:

[code] struct TVertex {
float position[3];
float normal[3];
int textureID;
struct TTexCoord {
float tu, tv;
};
};[/code]

Make some array and use it for each cube? Maybe im completely wrong. I just don't know how to make it better or rewrite it for vertex arrays.
[/quote]

Yeah, switching to modern 3D API idioms sometimes requires rethinking your thinking, if you'd allow me such pun. If you're concerned about glVertex3f deprecation, then you should probably be ready to migrate not just to vertex arrays, but to programmable pipeline entirely. There's little gain in partial migration anyway: you [i]could[/i] switch to client-side vertex arrays, but these are also deprecated.

For your situation, I'd advise you to thoroughly divide your raw data and your metadata. Raw data is geometry only: positions, normals, texture coordinates. These you can store in vertex buffer (if your map is hard coded as you say you may store it in one large buffer, or divide it into several buffers if you plan to use some space partitioning scheme).

Keep in mind that GL_QUADS as primitive type is removed in core profiles of modern GL as well, so you may need to store six vertices instead of four for each face (two triangles per face).

To render geometry stored in vertex buffer (or buffers) you'll need some metadata as well: this will include indices for individual faces along with TextureIDs. Since your vertices don't seem to share any data, there'd be no point in using index buffers, so you can store all your metadata in one additional client-side array. For example, you may end up with something like this:

[code]
// Raw data
struct Vertex {
float pos[3];
float normal[3];
float uv[2];
};

// Store all your vertices in a contiguous array (to load it into vertex buffer later)
Vertex CUBE_RAW_DATA[numCubeTypes*numSides*6] = { /* ... */ }; // 6 vertices per single face

// Metadata
struct FaceDescr {
int index; // index for the first vertex of this face inside vertex buffer. No point to store number of vertices, as it is fixed constant for any face
int textureID; // texture ID for this face
};

// Store the geometry layout in a separate array
FaceDescr CUBE_FACES[numCubeTypes][numSides] = { /* ... */ };
[/code]

Note that CUBE_RAW_DATA is a contiguous array of Vertex. Chunks of 6 Vertex structs store all the data for a single face. "numSides" of such chunks form single cube.
Thus, CUBE_RAW_DATA[0] stores first vertex of the first face of the first cube, CUBE_RAW_DATA[6] stores first vertex of the second face of the first cube, CUBE_RAW_DATA[numSides*6] stores first vertex of the first face of the second cube and so on, so that CUBE_FACES array will look like this (pseudo-code):

[code]
FaceDescr CUBE_FACES[numCubeTypes][numSides] =
{
{ 0, CUBE1_FACE1_TEX },
{ 6, CUBE1_FACE2_TEX },
// ...
{ numSides*6, CUBE2_FACE1_TEX },
{ (numSides+1)*6, CUBE2_FACE2_TEX },
// ...
};
[/code]

To store your raw vertex data in vertex buffers you may use the same approach as described in [url="http://www.opengl.org/wiki/Tutorial2:_VAOs,_VBOs,_Vertex_and_Fragment_Shaders_(C_/_SDL)"]this article[/url]. Basically, you create vertex array object (VAO) that stores your vertex layout (e.g. vertex attribute types, sizes and offsets) and vertex buffer object (VBO) that stores actual data. When it's time to render a face you fetch face metadata from CUBE_FACES array, bind the VAO and texture and call glDrawArrays() with the GL_TRIANGLES primitive type, index of the first vertex and number of vertices in the face:

[code]
glBindVertexArray(vao);


int Which = 1;


// Draw faces
for (int i = 0; i < numSides; ++i)
{
glBindTexture(GL_TEXTURE_2D, CUBE_FACES[Which][i].textureID);
// Each face is drawn with a single command:
glDrawArrays(GL_TRIANGLES, CUBE_FACES[Which][i].index, 6);
}
[/code]


If you're going after GL2.1, which does not have VAOs, there would be a little more work, because you'll need to manually set up arrays and array pointers every time:

[code]
glBindBuffer(GL_ARRAY_BUFFER, vbo);

glEnableVertexAttribArray( 0 ); // 0 is assumed to be attribute index for vertex position
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0 );

glEnableVertexAttribArray( 1 ); // 1 is assumed to be attribute index for vertex normal
glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(3*sizeof(float) );

glEnableVertexAttribArray( 2 ); // 2 is assumed to be attribute index for vertex texture coordinates
glVertexAttribPointer( 2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(6*sizeof(float) );

// draw as above
[/code]

Another word of advice: modern GL does not allow using client-side memory to store geometry. Thus, there is no point in hard-coding your coordinates. You may consider storing them in a file instead, and load them only to transfer to vertex buffer.
1

Share this post


Link to post
Share on other sites
Thank you for such long reply and explanation.

Just a question to you, don't you think that VAO make things so complicated?

[quote]if your map is hard coded as you say[/quote]

Well basically map file contains only cube indexes (from 1 to 50).
Renderer reads the index from mapfile, takes vertex coordinates from the cubes array and draws specific cube.
This is done for each cube.

So you say that vertex arrays are also deprecated? Pretty hard to believe. And they will be removed from newer OpenGL?
And old code stops working?


I will re-read your post many times to understand this all better.
I basically got the idea but it seems pretty complicated. Or im wrong?
0

Share this post


Link to post
Share on other sites
No, old code will not stop working just because a new version of GL is out.
0

Share this post


Link to post
Share on other sites
[quote name='BytePtr' timestamp='1312363555' post='4843973']
Just a question to you, don't you think that VAO make things so complicated?
[/quote]


No, they actually do quite the contrary. VAOs are usually set up once and used many, many times. They potentially make your code shorter, but what's more important, save function calls and also [i]may[/i] save some GPU performance.

[quote]
So you say that vertex arrays are also deprecated? Pretty hard to believe. And they will be removed from newer OpenGL?
[/quote]

Client-side vertex arrays are already removed in core profile of modern GL. You can take a look at current GL specification (4.1), there's a whole section there that lists everything that is being removed. This whole deprecation/removal thing may require some getting used to when you come from pre-3.0 GL.

[quote]
And old code stops working?
[/quote]

As V-man said, old code won't stop working per se, because legacy GL context creation routines cannot create non-backwards compatible GL contexts: they will either create a 2.1 context (possibly a 3.0 one, because technically it doesn't remove anything by itself), or 3.0+ context with compatibility profile (when applicable: 3.1, for example, has no compatibility profile, but may expose GL_ARB_compatibility extension instead). At the very least, if old code stopped working, we'd have already lost a bunch of good applications and games created before they even invented GL3.0 :)



[quote]
I will re-read your post many times to understand this all better.
I basically got the idea but it seems pretty complicated. Or im wrong?
[/quote]

It may seem complicated at first, but actually it's all pretty straight. Actually, the code would be quite similar even for client-side vertex arrays: glEnableClientState vs glEnableVertexAttribArray, glVertexPointer et al. vs glVertexAttribPointer and so on.
1

Share this post


Link to post
Share on other sites
Ok, once i got this all i will try to render one cube first with your pseudo code. I don't mean to copy paste but i will try to make your explanation to work.
If i will get into problems, i will let you know.


Thanks.
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0