我现在有pin down
几天不能解决的非常奇怪的问题。我正在制作一个简单的逐顶点照明,它可以正常工作Nvidia
,但不会渲染任何有灯光阴影的东西AMD/ATI
。我找到了与属性有关的问题——尤其是颜色属性。
这是我的顶点着色器:
#version 140
uniform mat4 modelViewProjectionMatrix;
in vec3 in_Position; // (x,y,z)
in vec4 in_Color; // (r,g,b,a)
in vec2 in_TextureCoord; // (u,v)
out vec2 v_TextureCoord;
out vec4 v_Color;
uniform bool en_ColorEnabled;
uniform bool en_LightingEnabled;
void main()
{
if (en_LightingEnabled == true){
v_Color = vec4(0.0,1.0,0.0,1.0);
}else{
if (en_ColorEnabled == true){
v_Color = in_Color;
}else{
v_Color = vec4(0.0,0.0,1.0,1.0);
}
}
gl_Position = modelViewProjectionMatrix * vec4( in_Position.xyz, 1.0);
v_TextureCoord = in_TextureCoord;
}
这是像素着色器:
#version 140
uniform sampler2D en_TexSampler;
uniform bool en_TexturingEnabled;
uniform bool en_ColorEnabled;
uniform vec4 en_bound_color;
in vec2 v_TextureCoord;
in vec4 v_Color;
out vec4 out_FragColor;
void main()
{
vec4 TexColor;
if (en_TexturingEnabled == true){
TexColor = texture2D( en_TexSampler, v_TextureCoord.st ) * v_Color;
}else if (en_ColorEnabled == true){
TexColor = v_Color;
}else{
TexColor = en_bound_color;
}
out_FragColor = TexColor;
}
所以这个着色器允许 3 种状态——当我使用灯光时,当我不使用灯光但使用逐顶点颜色时,以及当我对所有顶点使用单一颜色时。我删除了所有光计算代码,因为我将问题追溯到一个属性。这是着色器的输出:
如您所见,一切都是蓝色的(因此它渲染所有没有 shading 或 color 的东西
(en_LightingEnabled == false and en_ColorEnabled == false)
)。
当我在顶点着色器中替换此代码时:
if (en_ColorEnabled == true){
v_Color = in_Color;
}else{
有了这个:
if (en_ColorEnabled == true){
v_Color = vec4(1.0,0.0,0.0,1.0);
}else{
我得到以下信息:
所以你可以看到它渲染所有没有阴影的东西仍然是蓝色的,但现在它也将所有使用灯光(en_LightingEnabled == true
)的东西渲染为绿色。应该是这样的。问题是该in_Color
属性不应该干扰灯光,因为如果启用了灯光,它甚至都不会运行。您还可以看到图像中没有任何东西是红色的,这意味着在这个场景en_ColorEnabled
中总是false
。所以in_Color
在这里完全没用,但它会在逻辑上不应该的地方引起错误。在Nvidia
它上面工作正常,绿色区域绘制有或没有in_Color
。
我使用的东西AMD
不支持吗?我使用了超出GLSL
规格的东西吗?我知道spec 比AMD
更严格,所以我可能会做一些未定义的事情。我使代码尽可能简单,但仍然有问题,所以我看不到它。
另外,我注意到如果顶点属性被禁用(否),它不会在屏幕上绘制任何东西(甚至是蓝色区域),但为什么呢?我什至不使用颜色。禁用的属性需要按规范返回( )对吗?我试着用改变那个颜色,但还是变黑了。编译器和链接器不返回任何错误或警告。发现属性 in_Color 很好GL
Nvidia
in_Color
glEnableVertexAttribArray
0,0,0,1
glVertexAttrib4f
glGetAttribLocation
. 但正如我所说,这无关紧要,因为该分支从未在我的代码中执行。有任何想法吗?
在笔记本电脑上测试Nvidia660Ti
并正常工作,在ATI
mobility radeon HD 5000
笔记本电脑上测试并出现此错误。我唯一的想法是,也许我超出了GPU
(太多属性等等)的能力,但是当我把我的代码减少到这个时,我就不再相信了。我在这里只使用了 3 个属性。
此外,我的一些朋友在更新AMD
的显卡上进行了测试,也遇到了同样的问题。
更新 1
顶点属性绑定如下:
if (useColors){
glUniform1i(uni_colorEnable,1);
glEnableVertexAttribArray(att_color);
glVertexAttribPointer(att_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, STRIDE, OFFSET(offset));
}else{
glUniform1i(uni_colorEnable,0);
}
此外,我发现如何更容易地显示怪异 - 使用这个顶点着色器:
void main()
{
v_Color = clamp(vec4(1.,1.,1.,1.) * vec4(0.5,0.5,0.25,1.),0.0,1.0) + in_Color;
gl_Position = modelViewProjectionMatrix * vec4( in_Position.xyz, 1.0);
v_TextureCoord = in_TextureCoord;
}
所以没有分支。我得到了这个:
如果我通过像这样
删除来更改该代码:
in_Color
void main()
{
v_Color = clamp(vec4(1.,1.,1.,1.) * vec4(0.5,0.5,0.25,1.),0.0,1.0);
gl_Position = modelViewProjectionMatrix * vec4( in_Position.xyz, 1.0);
v_TextureCoord = in_TextureCoord;
}
我明白了:
最后一个是我所期望的,但是即使我做了加法(+
)而不是其他任何东西,前一个也没有绘制任何东西。因此,如果attrib
未绑定并且给出 ( 0,0,0,0
) 或 ( 0,0,0,1
),那么它不应该做任何事情。然而它仍然失败。
此外,所有日志都是空的 - 编译、链接和验证。没有错误或警告。尽管我注意到着色器调试信息AMD/ATI
提供的信息远不如Nvidia
提供的信息。
更新 2
我发现的唯一解决方法是attribarray
在所有情况下都启用(因此它基本上会在未启用颜色时将垃圾发送到GPU
),但是由于我使用制服来检查颜色,所以我只是不使用它。所以它是这样的:
if (useColors){
glUniform1i(uni_colorEnable,1);
}else{
glUniform1i(uni_colorEnable,0);
}
glEnableVertexAttribArray(att_color);
glVertexAttribPointer(att_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, STRIDE, OFFSET(offset));
我不知道为什么会发生这种情况或为什么需要使用它。我不需要那个Nvidia
。所以我想这更慢而且我在浪费带宽?但至少它有效......不过,如何更好地做到这一点的帮助会很有用。