• 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
The Magical Pot

Uptading parts of data in a VBO

9 posts in this topic

Hi!

 

I'm currently trying to set up a function that renders a textured 2D quad using VBOs. The function changes the vertex data of the VBO every time it's called so that you can stretch it, but the texture data of the VBO doesn't change. In other words I want to be able to change the vertex data without having to change the texture data of the VBO.

 

When I store my VBO I have a struct that contains 4 GLfloats (VertexData2D), the first two GLfloats represent the vertex data and the last two GLfloats represent the texture data. My problem is that I can't find a way to only change the vertex data without having to change the texture data, since the entire VBO contains both vertex data and texture data.

 

This the rendering part in the function:

glBindTexture( GL_TEXTURE_2D, get_texture_id() );		//Set texture

    //Enable vertex and texture coordinate arrays
    glEnableClientState( GL_VERTEX_ARRAY );
    glEnableClientState( GL_TEXTURE_COORD_ARRAY );

glBindBuffer( GL_ARRAY_BUFFER, VertexDataBuffer );		//Bind vertex data

//Update vertex buffer data
glBufferSubData( GL_ARRAY_BUFFER, 0, 4 * 4 * sizeof(GLfloat), VData );	

//Set texture coordinate data
glTexCoordPointer( 2, GL_FLOAT, 4 * sizeof(GLfloat), (GLvoid*)offsetof( VertexData2D, TexCoord ) );		
//Set vertex data
glVertexPointer( 2, GL_FLOAT, 4 * sizeof(GLfloat), (GLvoid*)offsetof( VertexData2D, Position ) );		

//Draw quad using vertex data and index data
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, IndexBuffer );
glDrawElements( GL_QUADS, 4, GL_UNSIGNED_INT, NULL );

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

I first bind the correct texture and VBO, then update the VBO using

glBufferSubData() 

 (the VBO is set with GL_DYNAMIC_DRAW). I update the VBO starting at index 0, VData is the VBO that's going to replace the current one. Each vertex has the size 

4 * sizeof(GLfloat)

and since I'm rendering a quad, the stride results in

4 * 4 * sizeof(GLfloat)

It's in glBufferSubData() that the problem is, my VBO contains both the vertex data and texture data, but I only want to change the vertex data. glBufferSubData() overwrites the current VBO, but I only want it to overwrite parts of it. This is essentially how I want it to work:

 

Update memory equal to: 2 * sizeof(GLfloat)

Skip memory equal to: 2 * sizeof(GLfloat)

Repeat 3 more times

 

What should I do? Is there another function that can do this?

 

Thank you!

0

Share this post


Link to post
Share on other sites

Is there something wrong with creating separate buffers for positions and texture coordinates? This could help, https://www.opengl.org/wiki/Vertex_Specification_Best_Practices#Vertex.2C_normals.2C_texcoords

 

Maybe something like this:

// bind, update and set the pointer for positions
glBindBuffer(GL_ARRAY_BUFFER, position_buffer);
glBufferSubData(...);
glVertexPointer(...)

// bind, update and set the pointer for texture coordinates
glBindBuffer(GL_ARRAY_BUFFER, texcoord_buffer);
glBufferSubData(...);
glTexCoordPointer(...);

// bind index buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);

// Draw
glDrawElements(...);
1

Share this post


Link to post
Share on other sites

Thank you both! I solved the problem by splitting the VBO into 2 parts, one for vertecies and one for texture coordinates. I didn't really know you could do that.

 

Cheers!

0

Share this post


Link to post
Share on other sites

For this kind of thing you're really better off using a vertex shader to manipulate your positions.  The function that changes positions can be coded in GLSL (perhaps with a uniform or two to control it), with all of the vertex data remaining static.

 

Otherwise you can achieve a similar effect by loading a new modelview matrix that represents your stretching.

 

Whichever way you choose, you need to be aware that VBOs are not intended for this kind of partial update.  You can certainly do it, but the best use of VBOs comes from either having completely static data in them, from replacing the entire set of data, or from appending to existing data up to the maximum size of the buffer object.  But trying to brute-force their usage in the same way as if you were still using immediate mode is extremely unlikely to end well.

1

Share this post


Link to post
Share on other sites


But trying to brute-force their usage in the same way as if you were still using immediate mode is extremely unlikely to end well.

 

I feel like GLSL is a little too much for me at this point. Would you say that it's better to replace both the vertex data and the texture coordinates rather than partially update in this case when it comes to performance?

0

Share this post


Link to post
Share on other sites

I think it should be fine to update the data directly, especially when you're rendering just 2D stuff. You can optimize it later if it really becomes a problem with the performance.

 

But yeah, when you have a lot of vertices per object, you should transform those with matrices instead. This way you don't have to modify the actual vertices at all.

0

Share this post


Link to post
Share on other sites

 


But trying to brute-force their usage in the same way as if you were still using immediate mode is extremely unlikely to end well.

 

I feel like GLSL is a little too much for me at this point. Would you say that it's better to replace both the vertex data and the texture coordinates rather than partially update in this case when it comes to performance?

 

 

No, I'd say it's better to profile and see which approach is fastest in your own program.

 

As a general guideline however, (1) interleaved data is going to be faster than non-interleaved data, and (2) updating all of a contiguous region in a VBO is going to be faster than jumping around to update smaller non-contiguous regions.  Using non-interleaved data can help you avoid (2) (as you've discovered) but then you get bitten by (1).

 

To be honest, there are still some situations where not even using VBOs at all may be the best approach, and it looks as though you've got one here.  If you've just got a single quad in that VBO, and if you need to update the data dynamically each frame, then glBegin/glEnd may even be faster.  Remember - Quake used glBegin/glEnd and didn't suffer too much from it, so while it may not be the most optimal, it's still not as slow as some people might lead you to believe.

0

Share this post


Link to post
Share on other sites

Quake used glBegin/glEnd and didn't suffer too much from it, so while it may not be the most optimal, it's still not as slow as some people might lead you to believe.

You should rephrase it as "Quake used glBegin/glEnd with 90s GPU hardware if they had GPU hardware at all". :D

0

Share this post


Link to post
Share on other sites

 

Quake used glBegin/glEnd and didn't suffer too much from it, so while it may not be the most optimal, it's still not as slow as some people might lead you to believe.

You should rephrase it as "Quake used glBegin/glEnd with 90s GPU hardware if they had GPU hardware at all". biggrin.png

 

 

And it still runs nowadays.

 

The point is not to be a glBegin/glEnd lover, the point is to pick the appropriate solution for the problem you're trying to solve.  Using buffer objects the wrong way will be slower.

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