为啥 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 属性而不是片段属性。顶点着色器的out
s 应该与片段着色器的in
s 匹配。
textureSampler
的位置之所以为-1,是因为你注释掉了代码。
orthoTransform
的位置之所以为-1,是因为它实际上从未被使用和优化出来。 out
outPosition
从未被片段着色器使用,这反过来又导致orthoTransform
统一被优化。
我想你要找的是gl_Position
。
【讨论】:
哎呀,我曾一度将颜色设为inout
,但当我将其更改为单独的变量时忘记将 glBindFragDataLocation 改回来。另外,我知道 textureSampler 不会像我发布的那样工作,我可能应该改变它以避免混淆。希望暗示我只是想在屏幕上获得一些颜色进行测试,但通常我会尝试从纹理中读取。以上是关于为啥 glGetUniformLocation 让我失望了?的主要内容,如果未能解决你的问题,请参考以下文章
glGetUniformLocation() 在使用过的制服上返回 -1?
即使我在着色器中使用了变量,glGetUniformLocation 仍返回 -1