Sign in to follow this  
compugeekpro

GLSL Vertex Shaders and Rendering Multiple Objects?

Recommended Posts

compugeekpro    152
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!

Share this post


Link to post
Share on other sites
karwosts    840
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.

Share this post


Link to post
Share on other sites
compugeekpro    152
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

// Vertex
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); // Using shaders (new way)

//Color
glBindBuffer(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);

// Index
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_uiVertexIndexBufferID[staticObject->id]);

// 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);

// Disable the attributes of the shader
glDisableVertexAttribArray(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 locations
m_GLSLProgram->bindAttrib(0, "a_Vertex");
m_GLSLProgram->bindAttrib(1, "a_Color");
//m_GLSLProgram->bindAttrib(2, "a_TexCoord");

//Re link the program
m_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 120

uniform 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 120


varying 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.

Share this post


Link to post
Share on other sites
karwosts    840
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.

Share this post


Link to post
Share on other sites
compugeekpro    152
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this