GLSL Vertex Shaders and Rendering Multiple Objects?

Started by
3 comments, last by compugeekpro 13 years, 11 months ago
Hi, I currently am working on a small game engine that is able to load in a .obj file and place the vertices, normals, and texture data in a VBO to allow for quick rendering. I have an Object class (static objects) which holds and array containing the VBO IDs for reference later. This way, I can draw only a certain object, or run through the entire list and render all objects. I had this concept working perfectly when I was using the glVertexPointer() function to set the location of the current object data, but I have just switched to using shaders because the 'glVertexPointer()' function is marked for removal (along with other fixed-function pipeline routines). I am able to render an object to the screen, but whenever I try rendering more than one object, the last Render Function called results in the last object passed in to be rendered. For example, if I have three objects (two boxes and a table) that I would like to be rendered, only the table is appearing because it is the last render function called in my game loop. The code for my Object class' render function is shown below:

// BEGIN FUNCTION

// Enable the attributes (of shader program)
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);

// Vertex
glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, m_uiVertexBufferID[staticObject->id]);
//glVertexPointer(3, GL_FLOAT, 0, (char *) NULL);
glVertexAttribPointer((GLint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);
		
//Color
glEnableClientState(GL_COLOR_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, m_uiColorBufferID[staticObject->id]);
//glColorPointer(3, GL_FLOAT, 0, 0);
glVertexAttribPointer((GLint)1, 3, GL_FLOAT, GL_FALSE, 0, 0);

// Texture (TBI)
//glBindBuffer(GL_ARRAY_BUFFER, m_uiTextureBufferID[staticObject->id]);
//glVertexAttribPointer((GLint)2, 2, GL_FLOAT, GL_FALSE, 0, 0);	
		
// Index
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_uiVertexIndexBufferID[staticObject->id]); // for indices
//glIndexPointer (GL_UNSIGNED_INT, 0, (char *) NULL );

// Only for closed polygons, no lines or points
glDrawElements(GL_TRIANGLES, m_uiNumIndices[staticObject->id], GL_UNSIGNED_INT, static_cast< void * >(0));
		
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);

glDisableClientState(GL_VERTEX_ARRAY);

// END FUNCTION

And in my main game loop I have:

// BEGIN FUNCTION

Graphics->beginScene();

// Render Objects
Graphics->render(Box);
Graphics->render(Box2);
Graphics->render(Table);
		
mWindow1->swapScreenBuffers();		// Display to screen
					
// Run Game Loop at a Specific FrameRate

// END FUNCTION

My guess is that the first two objects are being overwritten on the screen somehow...maybe because my shader program is run once for each object and the previous scene data isn't preserved? If anyone has any clue on how to fix this, I'd greatly appreciate it...I only have until Friday to get to a good stopping point on this project (it's for a beginning graphics course). Thanks!
Advertisement
What does your shader look like? I'm not sure if this has anything to do with your problem, but I think you should clean up your code some, you're mixing all kinds of new and depreciated calls together.

You might be able to get away with calling glEnable/DisableClientState, but you should remove all of these from your code (use glEnable/DisableVertexAttribArray exclusively instead). They are meant to be used with fixed attribute pointers, not the generic ones.

Also, are you using the special variables gl_* in your shader? With generic attribute arrays I think you should be defining your own variables, and getting the Attrib location with glGetAttribLocation, instead of hardcoding 0,1,2 for the attrib locations. I think you might be able to get away with that, but I'm not positive if it is guaranteed to work.

Other than that I can't say that I see anything wrong with your new code that would cause that behavior. If you comment out the table draw, do you see only box2? There must be something else going on that you're not showing.

Finally a small point, I see you have it commented out, but you should probably never be calling glIndexPointer. It doesn't do what you think it does.
[size=2]My Projects:
[size=2]Portfolio Map for Android - Free Visual Portfolio Tracker
[size=2]Electron Flux for Android - Free Puzzle/Logic Game
Here is my updated function:

// Enable the attributes of the shader (Values are hard coded)glEnableVertexAttribArray(0);glEnableVertexAttribArray(1);//glEnableVertexAttribArray(2); //Enable the texture coordinate attribute// VertexglBindBuffer(GL_ARRAY_BUFFER, m_uiVertexBufferID[staticObject->id]);//glVertexPointer(3, GL_FLOAT, 0, (char *) NULL);glVertexAttribPointer((GLint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);		// Using shaders (new way)		//ColorglBindBuffer(GL_ARRAY_BUFFER, m_uiColorBufferID[staticObject->id]);//glColorPointer(3, GL_FLOAT, 0, 0);glVertexAttribPointer((GLint)1, 3, GL_FLOAT, GL_FALSE, 0, 0);		// Using shaders (new way)// Texture (TBI)//glBindBuffer(GL_ARRAY_BUFFER, m_fTextureBufferID[staticObject->id]);//glVertexAttribPointer((GLint)2, 2, GL_FLOAT, GL_FALSE, 0, 0);			// IndexglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_uiVertexIndexBufferID[staticObject->id]); // Only for closed polygons, no lines or pointsglDrawElements(GL_TRIANGLES, m_uiNumIndices[staticObject->id], GL_UNSIGNED_INT, static_cast< void * >(0));		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);glBindBuffer(GL_ARRAY_BUFFER, 0);// Disable the attributes of the shaderglDisableVertexAttribArray(0);glDisableVertexAttribArray(1);


If I comment out the "Table" line in my game loop code (shown above), it does render the second box, but only that. As for my shader, here is the code that sets up my two custom variables:

//Bind the attribute locationsm_GLSLProgram->bindAttrib(0, "a_Vertex");m_GLSLProgram->bindAttrib(1, "a_Color");//m_GLSLProgram->bindAttrib(2, "a_TexCoord");	//Re link the programm_GLSLProgram->linkProgram();	m_GLSLProgram->bindShader(); //Enable our shader


I am using a class to manage GLSL. The bindAttrib function takes the index and the name of the variable. I have passed this in manually (0 and 1) earlier in the program when I loaded the simple vertex and fragment shaders. My simple VERTEX shader program is shown below:

#version 120uniform mat4 projection_matrix;uniform mat4 modelview_matrix;attribute vec3 a_Vertex;attribute vec3 a_Color;varying vec4 color;void main(void) {		color = vec4(a_Color, 1.0);	vec4 pos = modelview_matrix * vec4(a_Vertex, 1.0);	gl_Position = projection_matrix * pos;	}


My simple FRAGMENT shader program is shown below (pass in and pass out the color):

#version 120varying vec4 color;void main(void) {	gl_FragColor = color;	}


I've verified that the vertex information is read in and stored correctly in each file. As I mentioned before, I am use Vertex Buffer Objects to store the data on the graphics card. This program did work when I used VBOs and the "glVertexPointer()" function (the commented out items). Thanks for your help so far...my code is a little messy because I am worried more about function than form right now.
Hmm that's a stumper :S


Are you sure you're not hiding anything else in your render function? I see you've clipped some section out of the actual function, but there's absolutely no other lines in between open brace and close brace of the graphics->render function?

I can't think of any reason why changing to glVertexAttribPointer would cause that kind of behavior to change. Are you positive you made no other changes? If you change back to using glVertexPointer will it work properly again?

The only reason I could think of that your other objects are not showing is if you're clearing the framebuffer somehow before rendering.

One quickie test you could try is something like this (assuming that your box has some red component, or you can use whatever color mask you want):
Graphics->render(Box2);glColorMask(FALSE,TRUE,TRUE,TRUE);Graphics->render(Table);glColorMask(TRUE,TRUE,TRUE,TRUE);

This should lock the red channel of the framebuffer after rendering Box2, such that rendering the table can have no effect on the red channel. Maybe see if you can still see a red shadow of your Box2 after rendering the table? I don't know what this proves exactly, but could be a good step for debugging. Also throw up a picture also if you can of the complete scene, I'd like to get some idea of how the objects are in relation to each other, if this could be a Z issue or something.

Best of luck.

[size=2]My Projects:
[size=2]Portfolio Map for Android - Free Visual Portfolio Tracker
[size=2]Electron Flux for Android - Free Puzzle/Logic Game
I finally found the error...it was a glClear() command placed in a more top-level render function. I can't believe I didn't see it...I guess that's what I get for running on 4 hours of sleep...thanks again for the help.

This topic is closed to new replies.

Advertisement