Semicolon
Semicolon

Reputation: 163

Passing a uint to shader changes its value

I'm trying to pass a uint to my shader but I must be doing something wrong because in the shader the value is 3212836864 and not 4294967295.

I have a Vertex array that I store each vertex in before sending them to the shader using glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertex) * 4 * vertexBufferArrayInserts, vertexBufferArray);

These are my glVertexAttribPointer calls:

    shaderPosAttrib = glGetAttribLocation(shaderProgram, "position");
    glVertexAttribPointer(shaderPosAttrib, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position));
    glEnableVertexAttribArray(shaderPosAttrib);

    shaderTexCoordAttrib = glGetAttribLocation(shaderProgram, "texCoord");
    glVertexAttribPointer(shaderTexCoordAttrib, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texCoords));
    glEnableVertexAttribArray(shaderTexCoordAttrib);

    shaderColorAttrib = glGetAttribLocation(shaderProgram, "color");
    glVertexAttribPointer(shaderColorAttrib, 1, GL_UNSIGNED_INT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, color));
    glEnableVertexAttribArray(shaderColorAttrib);

And this is the Vertex struct

struct Vertex
{
    Vector2<GLfloat> position;
    Vector2<GLfloat> texCoords;
    GLuint color;

    Vertex() {

    }

    Vertex(Vector2<GLfloat> position, Vector2<GLfloat> texCoords, GLuint color) {
        this->position = position;
        this->texCoords = texCoords;
        this->color = color;
    }
};

Vertex shader:

#version 150

in vec2 position;
in vec2 texCoord;
in uint color;

out vec2 TexCoord;
out uint Color;

uniform mat4 projMat;

void main()
{
    TexCoord = texCoord;
    Color = color;
    gl_Position =  projMat * vec4(position, 0.0, 1.0);
}

Fragment shader:

#version 150

in vec2 TexCoord;
in uint Color;

out vec4 outColor;

uniform sampler2D tex;

void main()
{
    float colorr = 0;

    if(Color == 3212836864)
        colorr = 1;

    outColor = texture(tex, TexCoord) * vec4(colorr, colorr, colorr, 1.0);
}

Obviously I'm doing something wrong somewhere but I just can't see it... Help is very much appreciated!

Upvotes: 2

Views: 1308

Answers (2)

derhass
derhass

Reputation: 45362

The problem here is that glVertexAttribPointer does specify floating point data, so you must access them as float/vec in the shader. The normalized parameter of that function just specifies it the resulting floats will be normalized to [0,1] or just directly converted. In theory, you could use unnormalized uints as you do, and just use in float color in the shader - but you will be losing precision.

If you want to directly pass integral values to the shader, you have to use glVertexAttribIPointer, which was originally introduced in the EXT_gpu_shader4 extension and is part of GL core since version 3.

Upvotes: 5

datenwolf
datenwolf

Reputation: 162319

Okay, this

struct Vertex
{
    Vector2<GLfloat> position;
    Vector2<GLfloat> texCoords;
    GLuint color;

    Vertex() {

    }

    Vertex(Vector2<GLfloat> position, Vector2<GLfloat> texCoords, GLuint color) {
        this->position = position;
        this->texCoords = texCoords;
        this->color = color;
    }
};

is a problem: Between the templates and that it is a class containing class members, the exact alignment of each element within that structure is completely undetermined; add to this the possible addition of a v-table (table of virtual functions instance pointers). Vertex2 itself is probably another class or templated structure without exact alignment. Using offsetof you're going to see only where the instance data structure of Vertex2 starts, but not where the variables inside it are.

When it comes to interfacing with foreign APIs (by which I mean everything that's not been compiled with the very same compiler as your own project) or flat memory locations classes and templates are your worst enemy.

What you actually need are packed structures. Don't use classes; there's just too much of an incentive to derive from them and add virtual functions which will completely mess things up. Add syntactic sugar by using global scope binary operators.

Upvotes: 0

Related Questions