glGetUniformLocation为USED变量返回-1,带有优化的地狱

Ado*_*orn 2 opengl opengl-es fragment-shader glsles

我知道如果某个uniform变量没有主动为管道输出做出贡献,那么它会被优化并返回-1.考虑下面的片段着色器.

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";
Run Code Online (Sandbox Code Playgroud)

这真诚地尝试在多个位置使用传递的制服,并且在最终输出颜色中也是如此.但我仍然得到-1作为返回值.但是没有错误.我也不认为我身上有任何不妥之处.

我确信,优化已经完成.我检查了没有活动的制服,只有2个.我正在使用3.但是为什么在地球上...,编译器是盲目的.?? 我可以通过使用属性来解决,但我为什么要这样做?

编辑

请参阅我的顶点着色器

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";
Run Code Online (Sandbox Code Playgroud)

我列出了我自己的解决方法:

在适当位置的顶点着色器中添加3行:

"attribute float vGlobalTime                                    \n"
"varying float globalTime;                                      \n"
"globalTime = vGlobalTime;                                      \n"
Run Code Online (Sandbox Code Playgroud)

片段着色器中有1个新行:

"varying float globalTime;                                      \n"
Run Code Online (Sandbox Code Playgroud)

现在globalTime在我之前使用的所有地方使用uGlobalTime

PS:我没有测试过这个; 但我没有看到为什么它不应该工作的任何理由.

Sta*_*ker 5

在片段着色器C++源字符串定义的第7行末尾有一个狂野分号.

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

这会导致片段着色器的整个主要功能被跳过,甚至根本不应该链接.链接程序后是否检查过错误


考虑将着色器代码外包到外部文件中,这可以防止这样的拼写错误,并且无需在每次更改着色器时重新编译应用程序.

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);
}
Run Code Online (Sandbox Code Playgroud)