I have a question regarding interleaved vbo's. I have a structure that looks like this
struct VertexData{
float x,y,z; //vertex coordinates
float normalx,normaly,normalz; //vertex normal
float cx,cy,cz; //vertex color
};
And this is how i create my VBO,VAO,IBO:
//creat OpenGL objects to use in drawing
unsigned int gl_vertex_array_object, gl_vertex_buffer_object, gl_index_buffer_object;
//vertex array object
glGenVertexArrays(1, &gl_vertex_array_object);
glBindVertexArray(gl_vertex_array_object);
//vertex buffer object -> we hold the vertices
glGenBuffers(1,&gl_vertex_buffer_object);
glBindBuffer(GL_ARRAY_BUFFER, gl_vertex_buffer_object);
glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(VertexData), &vertices[0], GL_STATIC_DRAW);
//index buffer object -> we hold the index of vertex
glGenBuffers(1,&gl_index_buffer_object);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gl_index_buffer_object);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
//the connection between attributes, interleaved data
glEnableVertexAttribArray(0);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(VertexData),(void*)0); //send positions on pipe 0
glEnableVertexAttribArray(1);
glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof(VertexData),(void*)(sizeof(float)*3)); //send normals on pipe 1
glEnableVertexAttribArray(2);
glVertexAttribPointer(2,3,GL_FLOAT,GL_FALSE,sizeof(VertexData),(void*)(3*sizeof(float)*3)); //send colors on pipe 2
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glNormalPointer(GL_FLOAT,sizeof(VertexData),(void*)(sizeof(float)*3));
glColorPointer(3,GL_FLOAT,sizeof(VertexData),(void*)(3*sizeof(float)*3));
vao = gl_vertex_array_object;
vbo = gl_vertex_buffer_object;
ibo = gl_index_buffer_object;
num_indices = indices.size();
If my VBO is a vector of VertexData , does it mean it is interleaved ? And did i send the data correct above ? with stride and offset ? All this is in another class. Here is how i load the mesh and draw it in the main class
//load
teren::loadTerrain("resurse\\heightmap.bmp","resurse\\heightmap_color.bmp",mesh_vao_ground, mesh_vbo_ground, mesh_ibo_ground, mesh_num_indices_ground,20);
//draw
glUniformMatrix4fv(glGetUniformLocation(gl_program_shader_curent, "model_matrix"),1,false,glm::value_ptr(matrice_translatie));
glBindVertexArray(mesh_vao_ground);
glDrawElements(GL_TRIANGLES, mesh_num_indices_ground, GL_UNSIGNED_INT, 0);
My terrain is drawn but it has a weird colouring. It has pink and blue and whatnot, doesn't look anything like the color image from which i get my vertex colors. Here is my gourard vertex shader:
layout(location = 0) in vec3 in_position;
layout(location = 1) in vec3 in_normal;
layout(location = 2) in vec3 in_color;
uniform mat4 model_matrix, view_matrix, projection_matrix;
uniform vec3 light_position;
uniform vec3 eye_position;
uniform int material_shininess;
uniform float material_kd;
uniform float material_ks;
out vec3 light;
void main(){
gl_Position = projection_matrix*view_matrix*model_matrix*vec4(in_position,1.0);
float fDiffuseIntensity = material_kd * max(0.0, dot(normalize(in_normal), normalize(light_position)));
light = material_ks * in_color * fDiffuseIntensity;
}
And my gourard fragment shader:
in vec3 light;
out vec4 out_color;
void main()
{
out_color = vec4(light,1.0);
}
I am really stuck right now. Is it a problem with my shaders or my vbo/attributes,etc or maybe even both. I would really appreciate some help.(PS:If in the vertex shader i change to light=in_color , everything is white).I also have a light rotating above the terrain. Here is a photo of what is happening: http://i44.tinypic.com/69j0cg.jpg
This line:
glVertexAttribPointer(2,3,GL_FLOAT,GL_FALSE,sizeof(VertexData),(void*)(3*sizeof(float)*3));
Should be:
glVertexAttribPointer(2,3,GL_FLOAT,GL_FALSE,sizeof(VertexData),(void*)(sizeof(float)*6));
Also you don't need these stuffs:
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glNormalPointer(GL_FLOAT,sizeof(VertexData),(void*)(sizeof(float)*3));
glColorPointer(3,GL_FLOAT,sizeof(VertexData),(void*)(3*sizeof(float)*3));
All the rest is correct.
does it mean it is interleaved?
Yes.
Language lawyers will probably tell you that since the compiler is allowed to add padding anywhere inside the VertexData
struct, the correct approach to pass these data to GL would be to manually convert your vector of VertexData
to a buffer of floats. Practically speaking, no compiler pads floats inside a struct like that.