Jump to content

  • Log In with Google      Sign In   
  • Create Account

Uptading parts of data in a VBO


Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.


  • You cannot reply to this topic
9 replies to this topic

#1 The Magical Pot   Members   -  Reputation: 178

Like
0Likes
Like

Posted 16 February 2014 - 04:47 AM

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!



#2 Sponji   Members   -  Reputation: 2059

Like
1Likes
Like

Posted 16 February 2014 - 05:17 AM

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(...);

Derp

#3 Aliii   Members   -  Reputation: 1455

Like
1Likes
Like

Posted 16 February 2014 - 06:14 AM

Use glMapBuffer or use separate VBOs.



#4 The Magical Pot   Members   -  Reputation: 178

Like
0Likes
Like

Posted 16 February 2014 - 09:20 AM

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!



#5 mhagain   Crossbones+   -  Reputation: 11248

Like
1Likes
Like

Posted 16 February 2014 - 09:24 AM

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.


It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.


#6 The Magical Pot   Members   -  Reputation: 178

Like
0Likes
Like

Posted 16 February 2014 - 09:55 AM


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?



#7 Sponji   Members   -  Reputation: 2059

Like
0Likes
Like

Posted 16 February 2014 - 12:01 PM

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.


Derp

#8 mhagain   Crossbones+   -  Reputation: 11248

Like
0Likes
Like

Posted 17 February 2014 - 12:18 PM

 


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.


It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.


#9 TheChubu   Crossbones+   -  Reputation: 8223

Like
0Likes
Like

Posted 17 February 2014 - 02:37 PM

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


"I AM ZE EMPRAH OPENGL 3.3 THE CORE, I DEMAND FROM THEE ZE SHADERZ AND MATRIXEZ"

 

My journals: dustArtemis ECS framework and Making a Terrain Generator


#10 mhagain   Crossbones+   -  Reputation: 11248

Like
0Likes
Like

Posted 17 February 2014 - 04:58 PM

 

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.


It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.





Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.




PARTNERS