Skip to main content
GameDev.net gamedev.net
🔒 Locked

vbo question

Started by esr_ever Aug 8, 2007 at 3:51 AM 10 replies 1.2k views
Original Post
esr_ever
esr_ever
Hello, I've been trying to convert the immediate mode rendering of my app to vbos. In every example I've read, vertex data are the same in count as the texcoord, normal data. Could I send arbitrary sized data (vertex & normal for example) with same-sized index arrays? For example, in the case of a plane, consisting of 16x16 vertices & only one normal,same for all vertices, how could this be set up as a vbo & rendered without copying the normal? Thanks in advance,I'm really stuck here
V-man
V-man
It's not possible. But don't worry, VBOs is more efficient (faster) than immediate mode, specially if you have a large data set.

Make something like for your vertices

struct myvertexformat
{
x, y, z
nx, ny, nz
s, t
}
esr_ever
esr_ever
Thank you for your answer, I wanted to be sure before I changed anything. I've used VBOs before, but with same-sized data sets. You propose interleaved arrays, which may be better in many cases, but what happens when you've got multiple texcoord sets?
V-man
V-man
Put them in your structure

struct myvertexformat
{
x, y, z
nx, ny, nz
s1, t1
s2, t2
s3, t3, r3
}

and make the necessary calls to GL.

glBindBuffer(.....);
glVertexPointer(3, GL_FLOAT, sizeof(myvertexformat), 0);
glNormalPointer(GL_FLOAT, sizeof(myvertexformat), sizeof(float)*3);
glTexCoordPointer(2, GL_FLOAT, sizeof(myvertexformat), sizeof(float)*6);
glClientActiveTexture(GL_TEXTURE1);
glTexCoordPointer(2, GL_FLOAT, sizeof(myvertexformat), sizeof(float)*8);
glClientActiveTexture(GL_TEXTURE2);
glTexCoordPointer(3, GL_FLOAT, sizeof(myvertexformat), sizeof(float)*10);
esr_ever
esr_ever
Ok, the struct grows to support vertice,normals, 2 2D tex & 1 3d tex. But what if you need to support vertex colors also? In the end the struct will be too large and in many cases only a subset of the data would be used. I am reluctant to use interleaved arrays because I think they lack flexibility in these matters, and there would be too much redundant data passed in video memory, correct me if I'm wrong!
V-man
V-man
For vertex color, I add a unsigned int for the "RGBA"

and do

glColorPointer(4, GL_UNSIGNED_BYTE,.......)

Do whatever you feel is necessary to get the results you want.
I'm just giving you the most typical case, which is also guranteed to be fast.

You can always keep some things in a different VBO, specially if it will be dynamic. Like for water, xy doesn't change but maybe you want to compute z on the CPU.
Some people just keep xy and they get the z from another location, like vertex texture.
esr_ever
esr_ever
Ok V-man, I'll have all these in mind, thanks for your answers!
zedz
zedz
FWIW from my benchmarking interleaved arrays is only ~3% quicker than non-interleaved (in an actual game there should be no speed difference)
esr_ever
esr_ever
ok, I've set up VBOs but they crash in glDrawElements (Access violation reading 0x00000000). I've mapped only one array buffer & element buffer to check them, & they have the correct values. Below is a snippet of code of init & rendering, is there something terribly wrong & am I completely blind??


_vstart = starting index
_vsize = index count
_indices = stl vector
_vertex = stl vector of a vertex class holding 3 float members
Init code :
	glGenBuffers(1,_buffer);	glGenBuffers(1,&_ibuffer);	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,_ibuffer);	glBufferData(GL_ELEMENT_ARRAY_BUFFER,_indices.size()*sizeof(unsigned int),&(_indices[0]), GL_STATIC_DRAW);	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);		glBindBuffer(GL_ARRAY_BUFFER, _buffer);	glBufferData(GL_ARRAY_BUFFER, _vertex.size()*sizeof(float)*3, &(_vertex[0]), GL_STATIC_DRAW);	glVertexPointer(3, GL_FLOAT, 0, 0);	glBindBuffer(GL_ARRAY_BUFFER, 0);


Draw code (VBO relevant)
	glBindBuffer(GL_ARRAY_BUFFER, _buffer);	glVertexPointer(3, GL_FLOAT, 0, 0);	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,_ibuffer);	glEnableClientState(GL_VERTEX_ARRAY);	int i;		for(i=0;i<_groups.size();++i)	{		glDrawElements(GL_TRIANGLE_STRIP,_groups._vsize,GL_UNSIGNED_INT,BUFFER_OFFSET(_groups._vstart * sizeof(unsigned int)));	}		glDisableClientState(GL_VERTEX_ARRAY);	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);	glBindBuffer(GL_ARRAY_BUFFER, 0);


Thanks again for your responses & your patience..I know that there are a million forum posts/articles on the net about vbo's, but after going through a lot of them, my mind got completely f#cked up..
Krohm
Krohm
Quote:
Original post by zedz
FWIW from my benchmarking interleaved arrays is only ~3% quicker than non-interleaved (in an actual game there should be no speed difference)

Copy.
I didn't even measured a difference, so it was probably <3% in my case.
Previously "Krohm"
dpadam450
dpadam450
You cannot bind two buffers such as your case, you put all the data into one buffer.

glGenBuffers(1, &buffer);

glBufferSubData() , i think is the function.
NBA2K, Madden, Maneater, Killing Floor, Sims 
esr_ever
esr_ever
Ok, found the problem, the initialization/setup was done in instances of a class containing the buffers, and then the instances were pushed back(copied) in a vector container (of aforementioned class instances), so the actual addresses were *gone*..stupid & repeated mistake! :)

Problem solved here, thank you for all your answers!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.