Adorn
Adorn

Reputation: 1421

glGetUniformLocation returns -1 for USED variable, Hell with optimization

I understand that if some uniform variable is not actively contributing to pipeline's output, it is optimized and it should return -1. Consider a fragment shader below.

const char fShader[] =  "precision mediump float;                                               \n"

    "uniform float  uGlobalTime;                                            \n"

    "const int iMaxIterations = 6;                                          \n"
    "float fCircleSize = 1.0 / (3.0 * pow(2.0, float(iMaxIterations)));     \n"

    "vec2 Rotate(vec2 uv, float a)                                          \n"
    "{                                                                      \n"
        "return vec2(uv.x * cos(a) - uv.y * sin(a), uv.y * cos(a) + uv.x * sin(a));  \n"
    "}                                                                      \n";


    "void main()                                                    \n"
    "{                                                              \n"
        "vec2 uv = vec2(1280.0, 720.0);                                             \n"
        "uv = -0.5 * (uv - 2.0 * gl_FragCoord.xy) / uv.x;           \n"

        "uv = Rotate(uv, uGlobalTime);                          \n"
        "uv *= sin(uGlobalTime) * 0.5 + 1.5;                        \n"

        "float s = 0.3;                                             \n"
        "for(int i = 0 ; i < iMaxIterations; ++i)                   \n"
        "{                                                          \n"
            "uv = abs(uv) - s;                                      \n"
            "uv = Rotate(uv, uGlobalTime);                      \n"
            "s = s / 2.0;                                           \n"
        "}                                                          \n"

        "float c = length(uv) > fCircleSize ? 0.0:1.0;              \n"

        "gl_FragColor = vec4(c * uGlobalTime, c * uGlobalTime, c * uGlobalTime, 1.0);                           \n"

    "}                                                              \n";

This sincerely tries to use passed uniform at several location, and in the final output color as well. But I am still getting -1 as return value. There is no error though. I don;t think anything wrong on my side as well.

Optimization is done, I am sure. I checked no of active uniforms, and there are 2 only. I am using 3. BUT WHY on the earth..., is compiler blind..?? I can get around by using attribute, but why should I?

Edit

Please see my vertex shader as well

const char vShader[] =  "attribute vec3 vPosition;                                      \n"

"uniform mat4 uMVMatrix;                                        \n"
"uniform mat4 uPMatrix;                                         \n"

"void main(void)                                                \n"
"{                                                              \n"
    "gl_Position = uPMatrix * uMVMatrix * vec4(vPosition, 1.0);                     \n"
"}                                                              \n";

I am listing my own workaround:

adding 3 lines in vertex shader at appropriate locations:

"attribute float vGlobalTime                                    \n"
"varying float globalTime;                                      \n"
"globalTime = vGlobalTime;                                      \n"

and 1 new line in fragment shader:

"varying float globalTime;                                      \n"

And now using globalTime in all places where I had earlier used uGlobalTime

PS: I have not tested this; but I don't see any reason why it should not work.

Upvotes: 0

Views: 965

Answers (1)

Stacker
Stacker

Reputation: 1210

There is a wild semicolon at the end of line 7 of your fragment shader C++ source string definition.

const char* source =
  "line 1"
  "line 2"; // <- semicolon intended?
  "line 3+ ignored"; // <- lose string constant which is never assigned to anything

This causes the whole main function of your fragment shader to be skipped and shouldn't even link at all. Did you check for errors after linking your program?


Think about outsourcing your shader code into an external file, which prevents typos like this and also removes the need for recompiling your application each time you change a shader.

bool Shader::compileFromFile(const std::string& filename)
{
    std::ifstream stream(filename, std::ios_base::in);
    if (!stream.is_open())
        return false;
    std::string source{std::istreambuf_iterator<char>(stream),
                       std::istreambuf_iterator<char>()};
    return compile(source);
}

Upvotes: 5

Related Questions