PDA

View Full Version : How to pass 3 vertex arrray to vertex shader ?



pitruki
04-04-2013, 05:22 AM
Hello, I'm new to this forum.

I'm using OpenGL and C++ language in order to do my degree project and I have a problem.

I need to pass positions, colors and textures to vertex shader. But I don't know why it doesn't work.

Shaders are well compiled and linked. But when I try to pass dates to vertex shader, it shows my widget black. So, it doesn't work.

In my code I've made an struct like this:

typedef struct
{
point4 points[NumVerticesC]; // punts dels triangles
color4 colors[NumVerticesC]; // color en cada cara
vec4 tex_coords3D[NumVerticesC];

} vertexElements;

Where point4 and color4 are a type created by me as a vec4 of floats. NumVerticesC is 24 (the vertex of a cube). In points I store the positions, in colrs the colors and in tex_coords3D the 3D texture.

Then, after read, initialize, compile and link my shaders, I do this:

// Create a vertex array object
GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );

// Crate and initialize a buffer object
GLuint buffer;
glGenBuffers( 1, &buffer );
glBindBuffer( GL_ARRAY_BUFFER, buffer );
glBufferData( GL_ARRAY_BUFFER, sizeof(vsh.points) + sizeof(vsh.colors) + sizeof(vsh.tex_coords3D),
NULL, GL_STATIC_DRAW );
glBufferSubData( GL_ARRAY_BUFFER, 0, sizeof(vsh.points), vsh.points );
glBufferSubData( GL_ARRAY_BUFFER, sizeof(vsh.points), sizeof(vsh.colors), vsh.colors );
glBufferSubData( GL_ARRAY_BUFFER, sizeof(vsh.points)+sizeof(vsh.colors), sizeof(vsh.tex_coords3D), vsh.tex_coords3D);
// set up vertex arrays

GLuint loc = glGetAttribLocation( program, "vPosition" );
glEnableVertexAttribArray( loc );
glVertexAttribPointer( loc, 4, GL_FLOAT, GL_FALSE, ?, ? );


GLuint col = glGetAttribLocation( program, "vColor" );
glEnableVertexAttribArray( col );
glVertexAttribPointer( col, 4, GL_FLOAT, GL_FALSE, ?, ? );

GLuint tex = glGetAttribLocation( program, "vTexCoord3D" );
glEnableVertexAttribArray( tex );
glVertexAttribPointer( tex, 4, GL_FLOAT, GL_FALSE, ?, ?);


You can see that I create 3 glBufferSubData for points, colors and textures in my buffer object. Now I need to pass it to the location of my vertex shader program. In "vPosition" the points in "vColor" the colors and "vTexCoord3D" the textures. My biggest problem is determine which 2 last paramethers I have to pass in the 'glVertexAttribPointer'. I don't understand what it does, even reading the documentation.

In my display function there are:
glClear( GL_COLOR_BUFFER_BIT );
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDrawArrays( GL_QUADS, 0, NumVerticesC );
glFlush();

Anyone can help me to finish this code correctly ? Please, I've spent so time for this !

pitruki
04-04-2013, 05:27 AM
Sorry, I forgot tell you that 'vsh' is my name of an instancied 'vertexElements' struct

Dan Bartlett
04-04-2013, 06:38 AM
You have uploaded the 3 arrays to offsets 0, sizeof(vsh.points) and sizeof(vsh.points)+sizeof(vsh.colors) within the buffer object, so these would be the value to pass in as the offset parameter. Because the attributes are tightly packed (within their own arrays) you could use stride = 0, which would give:

glVertexAttribPointer( loc, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
glVertexAttribPointer( col, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(vsh.points)) );
glVertexAttribPointer( tex, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(vsh.points)+sizeof(vsh.colors )) );
This is the same as if you gave the stride (distance between 2 consecutive elements in the array) explicitly:

glVertexAttribPointer( loc, 4, GL_FLOAT, GL_FALSE, sizeof(point4), BUFFER_OFFSET(0) );
glVertexAttribPointer( col, 4, GL_FLOAT, GL_FALSE, sizeof(color4), BUFFER_OFFSET(sizeof(vsh.points)) );
glVertexAttribPointer( tex, 4, GL_FLOAT, GL_FALSE, sizeof(vec4), BUFFER_OFFSET(sizeof(vsh.points)+sizeof(vsh.colors )) );
I'm assuming the point4, color4 and vec4 types all consist of 4 floats.


If instead you were to interleave elements, the distance between an attribute value and the next attribute value would be the size of the combined vertex. The offset would be the starting location of the data you uploaded plus the offset of the field within the vertex. Something like this:



typedef struct
{
point4 point; // punts dels triangles
color4 color; // color en cada cara
vec4 tex_coord3D;
} vertexElement;
vertexElement vertexElements[NumVerticesC];
...
glBufferData( GL_ARRAY_BUFFER, sizeof(vertexElement)*NumVerticesC, vsh, GL_STATIC_DRAW );

glVertexAttribPointer( loc, 4, GL_FLOAT, GL_FALSE, sizeof(vertexElement), BUFFER_OFFSET(0) );
glVertexAttribPointer( col, 4, GL_FLOAT, GL_FALSE, sizeof(vertexElement), BUFFER_OFFSET(sizeof(point4)) );
glVertexAttribPointer( tex, 4, GL_FLOAT, GL_FALSE, sizeof(vertexElement), BUFFER_OFFSET(sizeof(point4)+sizeof(color4)) );

pitruki
04-05-2013, 10:08 AM
Thanks !

It works.