vertex buffers

Started by
6 comments, last by V-man 16 years, 3 months ago
ok, I am working on a model editor with another person and I'm trying to upgrade our renderer to use VBOs whenever possible. now due to some bad design decisions I'm not going to be able to use index buffers for the moment, so I'm just trying to use a triangle list of interleaved verticese. I think I have most of it in place, I make VBOs of the geometry for each texture on model load, then when drawing I go thropugh each texture, set the VBO for it, go through and set the texture and some associated material effects then draw. now the reason I'm posting, is when I draw I get an access violation, now I'm somewhat inexperienced with OGL so I have likely made some super simple noob mistake like forgetting to enable something. so would someone please do me the favor of looking over this code and tell me if they see any glaring errors?

struct ogl_vertex_buffer
{
	unsigned int n_verts;
	unsigned int vertex_size;
	GLenum format;
	GLuint buffer;
};

//sets up all vertex buffers for this model
void PCS_Model::make_vertex_buffers(){
//	return;
	for(unsigned int i = 0; i<subobjects.size(); i++){
		subobjects.vertex_buffer.resize(textures.size());
		for(unsigned int j = 0; j <textures.size(); j++){
			subobjects.make_vertex_buffer(j);
		}
	}
}

//set's up a specific vertex buffer
void pcs_sobj::make_vertex_buffer(int tid){
	struct OGL_vert{
		float u,v;
		vector3d norm;
		vector3d pos;
	};

	kaz_vector<OGL_vert> tri;
	kaz_vector<OGL_vert> poly;

	for(unsigned int i = 0; i<polygons.size(); i++){
		if(polygons.texture_id != tid)continue;

		OGL_vert vert;

		poly.resize(polygons.verts.size());

		for(unsigned int v = 0; v<polygons.verts.size(); v++){
			vert.pos = polygons.verts[v].point;
			vert.norm = polygons.verts[v].norm;
			vert.u = polygons.verts[v].u;
			vert.v = polygons.verts[v].v;
			poly[v] = vert;
		}
		for(unsigned int t = 1; t<polygons.verts.size()-1; t++){
			tri.push_back(poly[0]);
			tri.push_back(poly[t]);
			tri.push_back(poly[t+1]);
		}
	}
	vertex_buffer[tid].n_verts = tri.size();
	if(tri.size() <1)return;

	glGenBuffers(1,&vertex_buffer[tid].buffer);
	vertex_buffer[tid].format = GL_T2F_N3F_V3F;
	vertex_buffer[tid].vertex_size = sizeof(OGL_vert);
	glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertex_buffer[tid].buffer);
	glBufferDataARB(GL_ARRAY_BUFFER_ARB, tri.size()*sizeof(OGL_vert), &tri[0], GL_STATIC_DRAW_ARB );

}


void pcs_sobj::destroy_vertex_buffer(){
	for(unsigned int i = 0; i<vertex_buffer.size(); i++){
		glDeleteBuffers(1, &vertex_buffer.buffer);
	}
}

//replaces all the rendering code in our current model rendering code
void pcs_sobj::set_vertex_buffer(int tid){
	ogl_vertex_buffer&buffer = vertex_buffer[tid];

	glInterleavedArrays(buffer.format, buffer.vertex_size, (void*)NULL);
	glTexCoordPointer( 2, GL_FLOAT, buffer.vertex_size, (void*)NULL );
	glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer.buffer);
	glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
}

void pcs_sobj::draw_vertex_buffer(int tid){
	ogl_vertex_buffer&buffer = vertex_buffer[tid];
	glDrawArrays(GL_TRIANGLES, 0, buffer.n_verts/3);
}

and the actual drawing code edited for clarity (removed a bunch of material effect code that would do nothing but obfuscate what I was doing)

void PCS_Model::RenderGeometry_vertex_buffers(int sobj, TextureControl &tc){
	// Prep for rendering the geometry
	float light_one[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
	float light_zero[4] = { 0.0f, 0.0f, 0.0f, 1.0f };

	glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, light_one );
	glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, light_zero );

	// render geometry
	int tex_id = -1, glow_tex_id = -1, shine_tex_id = -1;
	glColor4f(1.0, 1.0, 1.0, 1.0); // clear any color

		glEnable(GL_LIGHTING);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
		glEnable(GL_ALPHA_TEST);
		glAlphaFunc(GL_GREATER, 0.01f);

	ERROR_CHECK;
	for(unsigned int t = 0; t<textures.size(); t++){
		if(subobjects[sobj].vertex_buffer.size() <1)
			continue;
		if(subobjects[sobj].vertex_buffer[t].n_verts <1)
			continue;

		tex_id = tc.TextureTranslate(t, TC_TEXTURE);

		subobjects[sobj].set_vertex_buffer(t);

		if (tex_id != -1 && !Textureless){
			glActiveTexture(GL_TEXTURE0);
			glEnable(GL_TEXTURE_2D);
			glBindTexture(GL_TEXTURE_2D, tex_id);
		//for completness, set the first stage to multiply the base texture with light
			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
			glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
			glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
			glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
			glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
			glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
			glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE, 1.0f);

				glActiveTexture(GL_TEXTURE1);
				glDisable(GL_TEXTURE_2D);
				glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
				glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
				glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
			
		}else{
			glActiveTexture(GL_TEXTURE0);
			glDisable(GL_TEXTURE_2D);

		}
	ERROR_CHECK;
		subobjects[sobj].draw_vertex_buffer(t);
		


	}
}

Bobboau, bringing you products that work... in theory
Advertisement
Just use glVertexPointer, glTexCoordpOinter, glNormalPointer
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);
I have interleaved formated data, I would basically have to redo everything, and I simply don't like haveing all of my geometry data in nineteen different locations, and that probably still wouldn't solve my problem.
Bobboau, bringing you products that work... in theory
Try looking here in the section titled "Interleaved Arrays".
that seems to cover how it's suposed to work but I can't see anything I'm missing.

ok, hows this, is this the right sequence to draw a VBO full of triangles without an index buffer assuming all the textures and there states have been set properly beforehand?

glBindBufferARB (passing the VBO handle)
glInterleavedArrays (passing the format flag and a NULL pointer for the array cause it's suposed to be useing the VBO)
glDrawArrays (passing gl_triangles obviusly)

assuming the vbo was formed correctly, am I missing a step?
Bobboau, bringing you products that work... in theory
Quote:Original post by Bobboau
I have interleaved formated data, I would basically have to redo everything, and I simply don't like haveing all of my geometry data in nineteen different locations, and that probably still wouldn't solve my problem.


glInterleavedArrays() just uses gl*Pointer() under the hood anyways, it's a short cut function, nothing more; gl*Pointer() functions can point to the same VBO as each other, you just provide offsets.

Anyway, in the code above, unless I'm going blind, I can't see where you bind the VBO to draw from, only the bind for the index buffer.

Also, I'm not sure why you are setting the TexCoordPointer() after using glInterleavedArrays, more so when you don't even give an offset to the data?
I figured that out just recently, I was misunderstanding how they worked somewhat.

the TexCoordPointer call was put there because I was looking at someone elses working code and that was the only difference I could find between theres and mine, I have no idea why they did it.

"Anyway, in the code above, unless I'm going blind, I can't see where you bind the VBO to draw from, only the bind for the index buffer."
from set_vertex_buffer()
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer.buffer);
I see now that probably should have been the first line, but same as above I was trying to emulate someone else's code that was somehow working
I have sense removed those two functions cause they are basicly one liners and only serve to complicate and obfuscate.

anyway, I just now got it to work, I'm still not quite sure how I did that, but I did find a big part of my problem was I was makeing the VBOs in a separate thread than I was rendering them in and apparently this was causing problems big enough that they were not getting formed but small enough that it, somehow, didn't crash with an access violation.
Bobboau, bringing you products that work... in theory
This explains all the technical details

http://www.opengl.org/wiki/index.php/GL_ARB_vertex_buffer_object

I think you are interested in this part, but read the all the document as well

glNormalPointer(GL_FLOAT, 64, BUFFER_OFFSET(12));glTexCoordPointer(2, GL_FLOAT, 64, BUFFER_OFFSET(24));glClientActiveTexture(GL_TEXTURE1);glTexCoordPointer(2, GL_FLOAT, 64, BUFFER_OFFSET(32));glClientActiveTexture(GL_TEXTURE2);glTexCoordPointer(2, GL_FLOAT, 64, BUFFER_OFFSET(40));
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);

This topic is closed to new replies.

Advertisement