I am writing a basic view manager using GL on ubuntu 13 and eeepc with a nvidia ION2 (optimus in use using bumblebee project). I've an XML file from which shaders are created when the system starts (like plugins) and added to a dictionary. Once these are compiled and linked and ready for use, a wrapper function is used to select the appropriate shader program based on the program name passed.
void ShadingProgramManager::useProgram(const std::string& program){
GLuint id = getProgramId(program);
glUseProgram(id);
if(GL_INVALID_VALUE == glGetError() || GL_INVALID_OPERATION == glGetError()){
printf("Problem Loading Shader Program");
return;
}
printf("%s is in use", program.c_str());
}
Where getProgramId simply looks inside the pre created dictionary and returns the id of the shader program.
When I render the object, I put the program to use by calling:
ShadingProgramManager::getInstance()->useProgram('vc');
'vc' is formed of the following shaders
Vertex Shader - vc.vert
#version 330
layout(location = 0) in vec3 position;
layout(location = 1) in vec4 color;
out vec4 vertcolor;
void main(){
vertcolor = color;
gl_Position = vec4(position, 1.0); //I've tried setting this as position * 10 also for any apparent changes on screen, but nothing changes
}
Fragment Shader - vc.frag:
#version 330
in vec4 vertcolor;
out vec4 outputcolor;
void main(){
outputcolor = vertcolor;
}
My vertex buffer is interleaved as:
VertexColor vertices[] =
{
{-1.0, -1.0, 0.0, 1.0, 1.0, 1.0, 1.0}, /*first 3 floats for pos, 4 for color */
{ 1.0, -1.0, 0.0, 1.0, 0.0, 0.0, 1.0},
{ 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0},
{-1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0},
};
Index Buffer is as:
GLuint indices[] =
{
0, 1, 2,
0, 2, 3,
};
VertexColor defined as:
class VertexColor{
GLfloat x;
GLfloat y;
GLfloat z;
GLfloat r;
GLfloat g;
GLfloat b;
GLfloat a;
/** some constants as below **/
};
const int VertexColor::OFFSET_POSITION =0;
const int VertexColor::OFFSET_COLOR =12;
const int VertexColor::SIZE_POSITION =3;
const int VertexColor::SIZE_COLOR =4;
const int VertexColor::STRIDE =28;
Then I use the following code to render the quad:
ShadingProgramManager::getInstance()->useProgram('vc');
glBindBuffer(GL_ARRAY_BUFFER, &vb);
glBufferData(GL_ARRAY_BUFFER, size_of_vertices_array, vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, &ib);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size_of_indices_array, indices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribArrayPointer(0, VertexColor::SIZE_POSITION, GL_FLOAT, GL_FALSE, VertexColor::STRIDE, (GLvoid*)VertexColor::OFFSET_POSITION);
glVertexAttribArrayPointer(1, VertexColor::SIZE_COLOR, GL_FLOAT, GL_FALSE, VertexColor::STRIDE, (GLvoid*)VertexColor::OFFSET_COLOR);
glDrawElements(GL_TRIANGLES, size_of_indices, GL_UNSIGNED_INT, 0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
However, I only see a white quad. I suspect it's the fixed function pipeline that comes into effect.
Even if I remove the call to glUseProgram(id) or use glUseProgram(0), I'm still getting the same results. I also tried multiplying the position in the vertex shader by 10.0 but no effect on screen. I am sure that the shaders are being compiled and linked as well. When I change to use something like glUseProgram(40) or any invalid number, I get the requisite error messages but elsewise, I only see a white unit square!
Sorry for the obtrusively long post but I am stumped on this one...I just get a white unit square no matter what changes I do to the vert or frag shader. I suspect GL is defaulting to the FFP, and for some reason my shader program is not falling into effect. I am hoping it's a noobish mistake, but any pointers would be appreciated.
PS: There are no compile errors so please excuse any syntactical errors in the code. I've typed the complete code above.
UPDATE: I've added the last parameter in the call to glVertexAttribArrayPointer as suggested by Andon, Dinesh and Spektre, and I had missed earlier, but still same results.
glVertexAttribArrayPointer (...)is an offset from the base address of the VBO's data store. It should be (void *)0 for the first pointer in your VBO, something like (void *)sizeof (GLfloat)*<num_previous_components> for each following pointer. Using the stride instead of the proper offset is causing the VBO to reference the second vertex position in your VBO and both color and position start at this location. You are effectively short-changing your vertex buffer by 1 vertex. - Andon M. Coleman