为啥 glGetUniformLocation 让我失望了?

Posted

技术标签:

【中文标题】为啥 glGetUniformLocation 让我失望了?【英文标题】:Why is glGetUniformLocation failing me?为什么 glGetUniformLocation 让我失望了? 【发布时间】:2011-11-12 11:59:33 【问题描述】:

几天前我找到了 Gwen,并认为它看起来是我项目的完美 GUI 工具包。但是,亲爱的,看看渲染器中的所有 OpenGL 2 代码。所以我想我会写一个 OpenGL 3 渲染器,这样我就可以实际使用它了,但是我对 CG 比对 GLSL 更熟悉,而且我一直在编写示例。我想如果我能把这些统一的变量设置好的话,应该基本就搞定了。

着色器编译和链接没有问题。我将范围缩小到 glGetUniformLocation 为正交矩阵和纹理采样器返回 -1,但我不知道它为什么会这样做。典型的问题似乎是,如果您实际上不使用它们,它们会被优化,但我已经使用了它们。

如果有人有任何想法,我会全力以赴。一旦它正常工作,将非常乐意发布/链接完整的东西。这是我第一次尝试 GLSL,所以我很容易做一些愚蠢的事情。我刚刚完成了另一个项目的 CG 设置,所以我并不是完全一无所知。

设置 OpenGL 上下文后调用的着色器初始化代码:

void InitializeShaders(void)

    g_ShaderProgram = glCreateProgram();
    g_VertexShader = glCreateShader(GL_VERTEX_SHADER);
    g_FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

    glShaderSource(g_VertexShader, 1, (const GLchar **)&VertexShaderData, 0);
    glShaderSource(g_FragmentShader, 1, (const GLchar **)&FragmentShaderData, 0);

    glCompileShader(g_VertexShader);
    CheckShaderCompile(g_VertexShader);

    glCompileShader(g_FragmentShader);
    CheckShaderCompile(g_FragmentShader);

    glAttachShader(g_ShaderProgram, g_VertexShader);
    glAttachShader(g_ShaderProgram, g_FragmentShader);

    glBindAttribLocation(g_ShaderProgram, 0, "position");
    glBindAttribLocation(g_ShaderProgram, 1, "color");
    glBindAttribLocation(g_ShaderProgram, 2, "texCoord");

    glBindFragDataLocation(g_ShaderProgram, 0, "color");

    glLinkProgram(g_ShaderProgram);
    CheckShaderLink();

    g_OrthoTransformLocation = glGetUniformLocation(g_ShaderProgram, "orthoTransform");
    g_TextureLocation = glGetUniformLocation(g_ShaderProgram, "textureSampler");

着色器作为字符串存储在头文件中,但我去掉了所有的换行符和反斜杠,因此它们看起来不那么痛苦。

顶点着色器:

#version 330

in vec4 position;
out vec4 outPosition;
uniform mat4x4 orthoTransform;
void main(void)

    outPosition = position * orthoTransform;

片段着色器:

#version 330

in vec2 texCoord;
in vec4 color;
out vec4 outColor;
uniform sampler2D textureSampler;
void main(void)

    //outColor = texture(textureSampler, texCoord) * color;
    outColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);

【问题讨论】:

另外,除非orthoTransform 是一个转置矩阵(或者如果你喜欢,你应该右乘position,而不是像你现在做的那样在左边。如果你确实转置了它,那么在你的 glUniformMatrix 调用上正确设置转置标志并右乘它。 【参考方案1】:

问题很简单:你的顶点着色器什么都不做,所以 OpenGL 正在优化它。

为了渲染一个三角形,OpenGL 需要一个三角形的每个顶点的剪辑空间位置。提供这个是顶点着色器的工作。因为 OpenGL 无法告诉您打算将哪个顶点着色器输出作为剪辑空间位置,所以 OpenGL 要求您写入 gl_Position 作为输出。避免这种情况是合法的,这就是您的着色器编译和链接的原因。但正如您所发现的,渲染失败了。

【讨论】:

呸,我什至有一次在里面有gl_Position,但我想我还在乱搞其他东西,在我改变它之前从未尝试过运行它。我想我读到了一些关于在 3.3 中弃用的所有其他内置 gl_* 变量的内容,并假设 gl_Position 也是如此。真的希望有更多最新信息可供查看。 @Apostate:关于 OpenGL 的信息很多。例如,GLSL specification 非常易读。还有 OpenGL Wiki page on GLSL is pretty comprehensive.【参考方案2】:

首先,glBindFragDatalocation 应该绑定 outColor 而不是 color 在这种情况下。其次,你给着色器程序的是 vertex 属性而不是片段属性。顶点着色器的outs 应该与片段着色器的ins 匹配。

textureSampler的位置之所以为-1,是因为你注释掉了代码。 orthoTransform 的位置之所以为-1,是因为它实际上从未被使用和优化出来。 out outPosition 从未被片段着色器使用,这反过来又导致orthoTransform 统一被优化。

我想你要找的是gl_Position

【讨论】:

哎呀,我曾一度将颜色设为inout,但当我将其更改为单独的变量时忘记将 glBindFragDataLocation 改回来。另外,我知道 textureSampler 不会像我发布的那样工作,我可能应该改变它以避免混淆。希望暗示我只是想在屏幕上获得一些颜色进行测试,但通常我会尝试从纹理中读取。

以上是关于为啥 glGetUniformLocation 让我失望了?的主要内容,如果未能解决你的问题,请参考以下文章

每帧调用 glGetUniformLocation()

glGetUniformLocation() 在使用过的制服上返回 -1?

即使我在着色器中使用了变量,glGetUniformLocation 仍返回 -1

glGetUniformLocation为第一个以外的采样器返回-1?

GLM 视图矩阵导致模型矩阵无效

为啥 .htaccess 让