Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 4 of 4

Thread: [C++] Passing array to opengl

  1. #1
    Junior Member Newbie
    Join Date
    Dec 2012
    Posts
    9

    Question [C++] Passing array to opengl

    I don't have much experience with glsl yet and I've run into a problem I can't figure out.
    I have an array that contains 4 integer values for each vertex of my mesh.
    Since these values never change, I figured the best way of doing it would be by using a buffer.
    Below isn't the actual code, just a representation.
    Generating the buffer(C++):
    Code :
    int numValues = vertexCount *4;
    int *values = new int[numValues];
    for(int i=0;i<numValues;i++)
    {
    	values[i] = 0; // For testing purposes
    }
    GLuint buf;
    glGenBuffers(1,&buf);
    glBindBuffer(GL_ARRAY_BUFFER,buf);
    glBufferData(GL_ARRAY_BUFFER,numValues *sizeof(int),&values[0],GL_STATIC_DRAW);
    delete values;
    When I retrieve the values using glGetBufferSubData they're correct, so I'm assuming so far it's fine.

    Inside the shader(GLSL):
    Code :
    layout(location = 3) in int values[4];

    Passing the buffer(C++):
    Code :
    glEnableVertexAttribArray(3);
    glBindBuffer(GL_ARRAY_BUFFER,buf);
    glVertexAttribPointer(
    	3, // location inside the shader
    	4, // 4 integer values per vertex
    	GL_INT,
    	GL_FALSE,
    	0,
    	(void*)0
    );
    glDrawArrays(GL_TRIANGLES,0,vertexCount);
    glDisableVertexAttribArray(3);

    However, as far as I can tell, the values inside the 'values' array in the shader are incorrect.
    I wouldn't be surprised if I did this entirely wrong, although it looks fine to me.
    Any suggestions?

  2. #2
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,948
    Code :
    4, // 4 integer values per vertex

    No, that's 4 floating-point values per-vertex.

    glVertexAttribPointer can only feed floating-point attributes. It can feed them integers, but they will be converted to floats (either with normalization or without). If you want GLSL to receive a real, true integer, then you must use glVertexAttribIPointer.

  3. #3
    Junior Member Newbie
    Join Date
    Dec 2012
    Posts
    9
    Thanks, I've changed that.
    Code :
    glEnableVertexAttribArray(3);
    glBindBuffer(GL_ARRAY_BUFFER,buf);
    glVertexAttribIPointer(
    	3,
    	4,
    	GL_INT,
    	0,
    	(void*)0
    );
    Code :
    layout(location = 3) in int values[4];

    The problem still persists however.
    I've checked the buffer data again, that's definitely correct, so it's caused either by the shader code or the glVertexAttribIPointer-call.

    Also, the first integer inside 'values' appears to be correct for all vertices, it's just the other three that are wrong.
    What could be the cause of that?
    I've checked the size of GLint and int, and they're the same, so that should be fine. (I've tested it with GLint to be sure and got the same result.)

  4. #4
    Member Regular Contributor
    Join Date
    Jun 2013
    Posts
    474
    Quote Originally Posted by Silverlan View Post
    Code :
    layout(location = 3) in int values[4];
    Quote Originally Posted by Silverlan View Post
    Also, the first integer inside 'values' appears to be correct for all vertices, it's just the other three that are wrong.
    What could be the cause of that?
    Each input variable(attribute) is essentially a 4-element vector. Attributes declared as scalars only use the first element of the vector. Matrices use one attribute per column. For attributes declared as arrays, each array element is a separate attribute (or even multiple attributes for arrays of matrices).

    So the above code actually declares 4 attributes, where values[0] has index 3, values[1] has index 4, and so on. The interface would be identical had you used:
    Code :
    layout(location = 3) in ivec4 values[4];
    and replaced values[0] with values[0].x etc.

    You should probably declare values as a single ivec4 rather than as an array of int. Vectors can be accessed using subscript notation (like arrays) as well as member notation (like structures).

    If you absolutely must use an array (e.g. because the size might be increased beyond 4 in future), you'll need a separate glVertexAttribIPointer() call for each element, e.g.:
    Code :
    for (int i = 0; i < 4; i++)
        glVertexAttribIPointer(3+i,1,GL_INT,4*4,(void*)(i*4));

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •