Search code examples
opengl-esshadervertex-shadergles

How to set uniform in 320 es glsl shader?


I got following glsl vertex shader:

#version 320 es

// Set default precision to medium
precision highp int;
precision mediump float;


layout(binding = 0) uniform Projection
                            {
                                float type;
                                mat4 mvp_matrix;
                            }
                            projection;

layout(location = 0) in vec4  vertex;
layout(location = 1) in vec2  texCoord;

layout(location = 0) out vec4 vPosition;
layout(location = 1) out vec2 vTexCoord;



void main()
{
    // Calculate vertex position in screen space
    //vPosition = matrix * vertex;
    vPosition = projection.mvp_matrix * vertex;

    // Pass texture coordinate to fragment shader
    // Value will be automatically interpolated to fragments inside polygon faces
    vTexCoord = texCoord;
}

I have hard time setting the mvp_matrix. I tried following things to get the location of that uniform variable:

        qDebug() << "--------------- location of Projection.type in vertex shader is " << program->attributeLocation("Projection.type");
        qDebug() << "--------------- location of Projection.mvp_matrix in vertex shader is " << program->attributeLocation("Projection.mvp_matrix");
        qDebug() << "--------------- location of projection.type in vertex shader is " << program->attributeLocation("projection.type");
        qDebug() << "--------------- location of projection.mvp_matrix in vertex shader is " << program->attributeLocation("projection.mvp_matrix");
        qDebug() << "--------------- location of mvp_matrix in vertex shader is " << program->attributeLocation("mvp_matrix");
        qDebug() << "--------------- location of projection in vertex shader is " << program->attributeLocation("projection");

But everything just returns -1. program is QOpenGLShaderProgram and the shader compiled and linked fine.

I also tried to list uniform variables with glGetActiveUniform, and got this:

Active Uniforms: 2
Uniform # 0   Type: 0x 1406   Name:  Projection.type    Size:  1
Uniform # 1   Type: 0x 8b5c   Name:  Projection.mvp_matrix    Size:  1

I also tried to get location with this:

glGetUniformLocation( program->programId(),"projection.mvp_matrix");

and got the same result (-1).

So, how to get location of that uniform variable?


Solution

  • You call the wrong function: glAttributeLocation would work with the in variables, like vertex or textCoord, while glGetUniformLocation would work with individual uniforms, not with a uniform block, which you have. If you want to use individual uniforms, declare them like individual variables, without the uniform block:

    uniform float type;
    uniform mat4 mvp_matrix;
    

    Then you could get the locations with glGetUniformLocation and set the values with glUniformXXX (where XXX is the type). But since you declared a uniform block in the shader, I assume, you want to use a uniform buffer object (which is the more modern and more performant way to do).

    If you want to know the block index of the Projection uniform block, you should call glGetetUniformBlockIndex, something like this:

    int projectionBlockIndex = glGetUniformBlockIndex(program, "Projection");
    

    Then, you can call glUniformBlockBinding to connect the block index with the block binding, like this:

    glUniformBlockBinding(program, projectionBlockIndex, projectionBlockBinding);
    

    However, you don't have to, since, you know that the block binding of the uniform block is 0 (because you wrote this in the shader: binding = 0).

    So the only thing you have to do to connect your uniform buffer object to this uniform block is to call glBindBufferBase, something like this:

    glBindBufferBase(GL_UNIFORM_BUFFER, 0, yourUniformBufferObject);