openglglslfragment-shadervertex-shadergouraud

GLSL 1.5 can't get color input


I just want to do a simple Gouraud Shading with some different colors on my objects. Basically my problem is, that I can't get the color values into the shaders, it just renders black. If I define a vector in the shader as a color for the whole object it works fine.

Main program:

protected void initOpenGL() {
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);
    startTime = Sys.getTime();

    m = new Matrix4f();
    m.m00 = 1;
    m.m11 = 1;
    m.m22 = -(101.0f / 99);
    m.m32 = -(200.0f / 99);
    m.m23 = -1;
    m.m33 = 0;

    makeCube();

    sp = new ShaderProgram("gouraud");
    glBindAttribLocation(sp.getId(), 0, "corners");
    glBindAttribLocation(sp.getId(), 1, "colors");

}

@Override
protected void render() {

    gamma = gamma + 1;
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    Matrix4f newMat = new Matrix4f(m);
    Matrix4f.translate(new Vector3f(0, 0, -5), newMat, newMat);
    newMat.rotate(gamma/100, new Vector3f(0, 1, 0));
    newMat.rotate(gamma/200, new Vector3f(1, 0, 0));

    FloatBuffer fb = BufferUtils.createFloatBuffer(16);
    newMat.store(fb);
    fb.flip();
    GL20.glUniformMatrix4(GL20.glGetUniformLocation(sp.getId(), "matrix"),
            false, fb);

    GL20.glUseProgram(sp.getId());


    glBindVertexArray(vaoId);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glDrawArrays(GL_QUADS, 0, corners.length/3);
    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(0);
    glBindVertexArray(0);

}

private void makeCube(){
    corners = new float[] {
            // cube
            // front
            -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1,
            // left
            -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1,
            // bottom
            -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1,
            // right
            1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1,
            // top
            -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1,
            // back
            -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1,

    };

    FloatBuffer eckenBuffer = BufferUtils.createFloatBuffer(corners.length);
    eckenBuffer.put(corners);
    eckenBuffer.flip();

    vaoId = glGenVertexArrays();
    glBindVertexArray(vaoId);
    int vboId = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vboId);
    glBufferData(GL_ARRAY_BUFFER, eckenBuffer, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);


    colors = new float[] {
            // front
            1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,

            // right
            1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,

            // back
            1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,

            // left
            0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,

            // top
            0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,

            // bottom
            1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f };

    FloatBuffer colorBuffer = BufferUtils.createFloatBuffer(colors.length);
    colorBuffer.put(colors);
    colorBuffer.flip();

    int vboIdB = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vboIdB);
    glBufferData(GL_ARRAY_BUFFER, colorBuffer, GL_STATIC_DRAW);
    glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

Shader:

Vertex

#version 150
in vec4 corners;
in vec4 colors;

vec4 colorTest = vec4(1.0,0.0,0.0,1.0);

out vec4 colorToFrag;

uniform mat4 matrix;

void main(void) {
colorToFrag = colors ;
gl_Position = matrix * corners;

}

Fragment

#version 150
in vec4 colorToFrag;

out vec4 colorOut;

void main(void) {
colorOut = colorToFrag;
}

Solution

  • You didn't post the code for your shader compilation/linking, but since you call glBindAttribLocation but do not call glLinkProgram in the rest of the code, I make the educated guess that the linking takes place only in the ShaderProgram constructor.

    The glBindAttribLocation calls will only affect any linking operations that come after it (obviously). So your location bindings are not effective at all - the GL assigns them.

    Now if you don't use the colors attribute in the shader, it will be optimized out and the attribute will not be active - so it will get no location at all, and corners is likely to get index 0, as you expect it. Note that the GL is not required to assing attribute locations sequentially, beginning from zero, but most do. If you actually use 'colors', it might end up with location 0, breaking your rendering completely.

    As another side note: on nvidia, I observed that attribute locations assigned by the GL seem to actually be lexicographically ordered by the variable names in the shader - so 'colors' would come before 'corners'. I'm not sure if that was just a coincidence or how other implementations handle that.