Vertex Array slowdown (vs. Immediate Mode)

Hello!

I have got a problem using vertex arrays because they give me a slowdown (200FPS -> 12FPS). Here my Rendering Code:

Immediate Mode

		glBegin(GL_TRIANGLES);
		for (int i = 0; i < mesh->num_triangles; i++)
		{
			glVertexAttrib2fvARB(texcoord_index, mesh->buf_texc[mesh->triangles[i].v0].data_pointer());
			glVertexAttrib3fvARB(normal_index, mesh->buf_norm[mesh->triangles[i].v0].data_pointer());
			glVertexAttrib3fvARB(tangent_index, mesh->buf_tang[mesh->triangles[i].v0].data_pointer());
			glVertexAttrib3fvARB(binormal_index, mesh->buf_bino[mesh->triangles[i].v0].data_pointer());
			glVertex3fv(mesh->buf_vert[mesh->triangles[i].v0].data_pointer());

			glVertexAttrib2fvARB(texcoord_index, mesh->buf_texc[mesh->triangles[i].v1].data_pointer());
			glVertexAttrib3fvARB(normal_index, mesh->buf_norm[mesh->triangles[i].v1].data_pointer());
			glVertexAttrib3fvARB(tangent_index, mesh->buf_tang[mesh->triangles[i].v1].data_pointer());
			glVertexAttrib3fvARB(binormal_index, mesh->buf_bino[mesh->triangles[i].v1].data_pointer());
			glVertex3fv(mesh->buf_vert[mesh->triangles[i].v1].data_pointer());

			glVertexAttrib2fvARB(texcoord_index, mesh->buf_texc[mesh->triangles[i].v2].data_pointer());
			glVertexAttrib3fvARB(normal_index, mesh->buf_norm[mesh->triangles[i].v2].data_pointer());
			glVertexAttrib3fvARB(tangent_index, mesh->buf_tang[mesh->triangles[i].v2].data_pointer());
			glVertexAttrib3fvARB(binormal_index, mesh->buf_bino[mesh->triangles[i].v2].data_pointer());
			glVertex3fv(mesh->buf_vert[mesh->triangles[i].v2].data_pointer());
		}
		glEnd();

Vertex Arrays

		glBindBuffer(GL_ARRAY_BUFFER, 0);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

		glVertexAttribPointerARB(texcoord_index, 2, GL_FLOAT, GL_FALSE, 0, (float*)mesh->buf_texc);
		glEnableVertexAttribArrayARB(texcoord_index);

		glVertexAttribPointerARB(normal_index, 3, GL_FLOAT, GL_FALSE, 0, (float*)mesh->buf_norm);
		glEnableVertexAttribArrayARB(normal_index);

		glVertexAttribPointerARB(tangent_index, 3, GL_FLOAT, GL_FALSE, 0, (float*)mesh->buf_tang);
		glEnableVertexAttribArrayARB(tangent_index);

		glVertexAttribPointerARB(binormal_index, 3, GL_FLOAT, GL_FALSE, 0, (float*)mesh->buf_bino);
		glEnableVertexAttribArrayARB(binormal_index);

		glVertexPointer(3, GL_FLOAT, 0, (float*)mesh->buf_vert);
		glEnableClientState(GL_VERTEX_ARRAY);

		glDrawElements(GL_TRIANGLES, mesh->num_triangles*3, GL_UNSIGNED_INT, mesh->buf_ind);

Does anyone has an idea?
Thanks

Sorry for my lack of knowledge, but what’s this line intended for ?

glVertexAttrib2fvARB(...);

I couldn’t find any information about VertexAttrib. If someone could point me to any documentation about it, it will be fine.

To try to answer the question: actually I don’t know. This seems a partial code, isn’t it ? So, maybe with much code, someone will be able to give an interresting explanation of why this doesn’t work as you expected.
Too, I’ve never used VertexAttrib with vertex arrays, neither with VBO.

To have a better comparison between vertex arrays and immediate mode, try not to use any VBO neither VertexAttrib and tell if the performances are the same like with them.

Hope that could help.

EDIT:

Well, after some researches, VertexAttrib are to be used for vertex shaders. You didn’t seem to do any shader here. So, if I’m not wrong, you should not use VertexAttrib at all.
Do some searches for making any Vertex Array and try what I said above.

Originally posted by jide:

Well, after some researches, VertexAttrib are to be used for vertex shaders. You didn’t seem to do any shader here. So, if I’m not wrong, you should not use VertexAttrib at all.
Do some searches for making any Vertex Array and try what I said above.

Well I think that he is using shaders for bumpmapping…this is just a part of the program.

Originally posted by Corrail:
Does anyone has an idea?
Thanks

Try interleaving your arrays.

struct Vertex
{
   float texcoord[2];
   float normal[3];
   float tangent[3];
   float binormal[3];
   float position[3];
};

Pulling (large blocks of) data from five different memory locations isn’t terribly efficient.

How complex is your testing mesh (vertex count)?

The problem with interleaved arrays is that they are not as flexible as I’d like them to be.

Vertex count is 645, 936 triangles

But I noticed something very strange.

Here my Vertex Shader:

attribute vec3 a2v_Normal;
attribute vec3 a2v_Tangent;
attribute vec3 a2v_Binormal;
attribute vec2 a2v_Texcoord;

varying vec3 v2f_LightVec;
varying vec3 v2f_ViewVec;
varying vec2 v2f_Texcoord;

void main()
{
	// Vertex transformation
	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

	// Calculating TBN
	vec3 Tangent = gl_NormalMatrix * a2v_Tangent;
	vec3 Binormal = gl_NormalMatrix * a2v_Binormal;
	vec3 Normal = gl_NormalMatrix * a2v_Normal;
	
	// Calculating Light vector in ModelView Space
	vec3 Vertex_Model = vec3(gl_ModelViewMatrix * gl_Vertex);	
	vec3 LightVec = vec3(gl_LightSource[0].position) - Vertex_Model;

	//v2f_LightVec = vec3(1.0, 0.0, 0.0);
	//v2f_ViewVec = vec3(1.0, 0.0, 0.0);

	v2f_LightVec.x = dot(LightVec, Tangent);
	v2f_LightVec.y = dot(LightVec, Binormal);
	v2f_LightVec.z = dot(LightVec, Normal);
	
	// Calculating View vector in ModelView Space
	v2f_ViewVec.x = dot(-Vertex_Model, Tangent);
	v2f_ViewVec.y = dot(-Vertex_Model, Binormal);
	v2f_ViewVec.z = dot(-Vertex_Model, Normal);
	
	// Passing texture coordinates to fragment shader
	v2f_Texcoord = a2v_Texcoord;
}

When I comment out all Tangent/Normal/Binormal stuff like:

attribute vec3 a2v_Normal;
//attribute vec3 a2v_Tangent;
//attribute vec3 a2v_Binormal;
//attribute vec2 a2v_Texcoord;

varying vec3 v2f_LightVec;
varying vec3 v2f_ViewVec;
varying vec2 v2f_Texcoord;

void main()
{
	// Vertex transformation
	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

	// Calculating TBN
	//vec3 Tangent = gl_NormalMatrix * a2v_Tangent;
	//vec3 Binormal = gl_NormalMatrix * a2v_Binormal;
	//vec3 Normal = gl_NormalMatrix * a2v_Normal;
	
	// Calculating Light vector in ModelView Space
	vec3 Vertex_Model = vec3(gl_ModelViewMatrix * gl_Vertex);	
	vec3 LightVec = vec3(gl_LightSource[0].position) - Vertex_Model;

	v2f_LightVec = vec3(1.0, 0.0, 0.0);
	v2f_ViewVec = vec3(1.0, 0.0, 0.0);

	/*v2f_LightVec.x = dot(LightVec, Tangent);
	v2f_LightVec.y = dot(LightVec, Binormal);
	v2f_LightVec.z = dot(LightVec, Normal);
	
	// Calculating View vector in ModelView Space
	v2f_ViewVec.x = dot(-Vertex_Model, Tangent);
	v2f_ViewVec.y = dot(-Vertex_Model, Binormal);
	v2f_ViewVec.z = dot(-Vertex_Model, Normal);*/
	
	// Passing texture coordinates to fragment shader
	v2f_Texcoord = a2v_Texcoord;
}

it works without problems.

Originally posted by Corrail:
When I comment out all Tangent/Normal/Binormal
it works without problems.

I think thats becouse when you comment them out then these attributes are not send to the shader.

Have you tried sending data for example via texCoords?

i.e. to send normals its common to use glNormalPointer
and then you can bind tangent/binormals to some free texture units by glTexCoordPointer(…)

You are using GLSLang for you vertex shaders, right? We (me and my co-workers) recently submitted a paper for PG’05 about rendering of multiresolution deformations computed on the GPU, and using the latest NVIDIA drivers on both Win32 and Linux platforms with GeForce 5 & 6, GLSLang was incredibly slow compared to the same program written with ARB_vertex_program. Sometimes the GLSLang program was about 9-10 times slower than the ARB program.
Although in your case you are getting slowdown when using vertex arrays vs. intermediate mode, I’m sharing our experience only to suggest that the reason for the strange performance results might be related to the infant stage of GLSlang implementation in the current OpenGL drivers. Also you could try interleaved arrays, this might result in a better performance if your shader is data transfer dependent.

Regards

I really doubt that interleaved arrays can solve his problem. Of course he can get better performance but the problem has to be somewhere else. It rather seems that that he is dropping back to software rendering ( as he wrote he is sending only 900 tris + using quite simple shaders ).