1
votes

Problem: I have a VBO containing an array of structs (MyStruct), which contain a boolean attribute. I want to pass this boolean to my vertex shader, but GL_BOOL is not allowed according to the documentation of glVertexAttribPointer(...);.

Specifies the data type of each component in the array. The symbolic constants GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, and GL_UNSIGNED_INT are accepted by glVertexAttribPointer and glVertexAttribIPointer. Additionally GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE, GL_FIXED, GL_INT_2_10_10_10_REV, GL_UNSIGNED_INT_2_10_10_10_REV and GL_UNSIGNED_INT_10F_11F_11F_REV are accepted by glVertexAttribPointer. GL_DOUBLE is also accepted by glVertexAttribLPointer and is the only token accepted by the type parameter for that function. The initial value is GL_FLOAT. Source: https://www.opengl.org/sdk/docs/man/html/glVertexAttribPointer.xhtml

What did I try: As shown in the moc-up i tried to use in int myBoolean; instead but the boolean values of the struct (which are set properly, I've checked) are not correctly mapped to the ints in the vertex shader (this might be something on my end though?).

Moc-up code of the problem:

MyStruct

struct MyStruct{
 ...
 bool myBoolean;
 ...
}

Vertex Shader

#version 400 compatibility // Can be set higher if needed
in vec3 position;
//in bool  myBoolean;
//in int myBoolean; -> doesn't work either

out vec4 color;

void main( void )
{
 //if (myBoolean){ // (myBool == 1) for the int
 // color = vec4(1,0,0,1);
 //} else {
 color = vec4(position, 1);
 //}
 ...
};

How I set up the buffers:

    // Build OpenGL VBO
    glGenBuffers( 1, &m_glVBO );
    glBindBuffer( GL_ARRAY_BUFFER, m_glVBO );
    glBufferData( GL_ARRAY_BUFFER, numOfMyStructs*sizeof(MyStruct), myStructs, GL_DYNAMIC_DRAW );

    // Build OpenGL VAO
    glGenVertexArrays( 1, &m_glVAO );
    glBindVertexArray( m_glVAO );

    // Position attribute
    glEnableVertexAttribArray( 0 );
    glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, sizeof(myStruct), (GLvoid*)offsetof(MyStruct, position) );

    // Does not work, all booleans in the vertex buffer are false
    // and GL_BOOL is not allowed.
    //glEnableVertexAttribArray( 1 );
    //glVertexAttribPointer( 1, 1, GL_INT, GL_FALSE, sizeof(MyStruct), (GLvoid*)offsetof(MyStruct, myBoolean) );

    glBindVertexArray( 0 );
    glBindBuffer( GL_ARRAY_BUFFER, 0 );

Binding the shader:

myShader = new QGLShaderProgram( QGLContext::currentContext() );
...
myShader->bindAttributeLocation( "position", 0 );
//myShader->bindAttributeLocation( "myBoolean", 1);
glBindFragDataLocation( myShader->programId(), 0, "color" );
...

Rendering: (I want to use instance rendering (a sphere) in the future but that doesn't matter)

...
glEnable( GL_POINT_SMOOTH );
glHint( GL_POINT_SMOOTH_HINT, GL_NICEST );

glBindVertexArray( m_glVAO );
glDrawArrays( GL_POINTS, 0, numMyStructs );
glBindVertexArray( 0 );
... 

Additional information: I work with QtCreator (3.6.1), C++11, OpenGL (4.5), GLM (0.9.7.4), GLEW(1.13), Nvidia card (364.16 driver + CUDA 7.5), Linux 64bit. I'm an OpenGL novice. I would prefer to use no additional libraries if possible. It works fine without the myBoolean (so with the commented sections as set in the moc-up code). The moc-up code is quickly typed for stackoverflow, my apologies for possible syntax errors feel free to point them out (the real world code does work without the myBoolean). I can provide additional information if required.

Thanks in advance.

1

1 Answers

1
votes

You probably want glVertexAttribIPointer (note the letter 'I' nestled in there) - that's for passing integral values in. And since everything in a struct is at least byte aligned, a single bool can't be smaller than GL_UNSIGNED_BYTE

https://www.opengl.org/sdk/docs/man/html/glVertexAttribPointer.xhtml