Search code examples
c++openglglslshaderbitwise-operators

Opengl shader bitwise operation not working in Windows


I use an integer to use as a "filter" and pass it to a geometric shader and use a bitwise operation to get the bit values. It works in macOS, but not in Windows. To show my point, I used and modified the tutorial code in the geometric shader part in the learnopengl.com found at

https://learnopengl.com/Advanced-OpenGL/Geometry-Shader

Based on the tutorial code, I added the following code in the main.cpp. (I added enabledFaces[] and VFO, and passed them to the shaders.) I only set one bit to each enabledFaces[] integer for simplicity.

int enabledFaces[] = {
    1 << 0, 1 << 1, 1 << 2, 1 << 3
};

unsigned int VBO, VAO, VFO;
glGenBuffers(1, &VBO);
glGenBuffers(1, &VFO);
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(points), &points, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), 0);

glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(2 * sizeof(float)));

glBindVertexArray(VFO);
glBindBuffer(GL_ARRAY_BUFFER, VFO);
glBufferData(GL_ARRAY_BUFFER, sizeof(enabledFaces), &enabledFaces, GL_STATIC_DRAW);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 1, GL_INT, GL_FALSE, sizeof(int), 0);

glBindVertexArray(0);

In the vertex shader as a pass-through:

#version 330 core 
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in int vEnabledFaces;
out int gEnabledFaces;
out VS_OUT {
   vec3 color;
} vs_out;

void main() {
   vs_out.color = aColor;
   gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0); 
   gEnabledFaces = vEnabledFaces;
}

And the geometric shader (added the if statement with the gEnabledFaces):

##version 330 core
layout (points) in;
layout (triangle_strip, max_vertices = 5) out;
in int gEnabledFaces[];
in VS_OUT {
   vec3 color;
} gs_in[];
out vec3 fColor;

void build_house(vec4 position)
{    
   fColor = gs_in[0].color; // gs_in[0] since there's only one input vertex
   gl_Position = position + vec4(-0.2, -0.2, 0.0, 0.0); // 1:bottom-left   
   EmitVertex();   
   gl_Position = position + vec4( 0.2, -0.2, 0.0, 0.0); // 2:bottom-right
   EmitVertex();
   gl_Position = position + vec4(-0.2,  0.2, 0.0, 0.0); // 3:top-left
   EmitVertex();
   gl_Position = position + vec4( 0.2,  0.2, 0.0, 0.0); // 4:top-right
   EmitVertex();
   gl_Position = position + vec4( 0.0,  0.4, 0.0, 0.0); // 5:top
   fColor = vec3(1.0, 1.0, 1.0);
   EmitVertex();
   EndPrimitive();
}

void main() { 
   if ( (gEnabledFaces[0] & 0x01) != 0 || (gEnabledFaces[0] & 0x04) != 0)
       build_house(gl_in[0].gl_Position);
}

No change in the fragment shader:

#version 330 core
out vec4 FragColor;
in vec3 fColor;

void main()
{
   FragColor = vec4(fColor, 1.0);
}

Due to the if statement in the main() in the geometric shader, two houses (the first and the third polygons) out of the 4 polygons should be displayed. It works correctly on Mac, but nothing is displayed in Windows. If I remove the if statement in Windows, all polygons display correctly. Would someone please explain why this does not work in Windows and how to fix it? Thank you.


Solution

  • As suggested by G.M., the use of glVertexAttribIPointer solves the problem.

    But I use Qt and unfortunately, it seems that glVertexAttribIPointer is not available. So I changed the glVertexAttribPointer to float type instead of an integer type. So,

    Changing from glVertexAttribPointer(2, 1, GL_INT, GL_FALSE, sizeof(int), 0);

    to glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(float), 0);

    Then it works in Windows, in spite of the fact that the passing variables (in the C++ and also in shaders) are all integer type. Strange but it works.