GLSL着色器不适用于AMD/ATI,但适用于NVIDIA

 ouyan1985_998 发布于 2023-01-08 17:19

我真的很奇怪,我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种状态 - 当我使用灯光时,当我不使用灯光时,但是使用每顶点颜色,并且当我对所有顶点使用单一颜色时.我删除了所有的光计算代码,因为我将问题追溯到属性.这是着色器的输出:
着色器与bug 正如你所看到的,一切都是蓝色的(所以它渲染了没有阴影或颜色的所有东西(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{

我得到以下内容:
没有in_Color属性
所以你可以看到它呈现的所有内容都没有着色仍然是蓝色,但现在它也渲染了所有使用en_LightingEnabled == true绿色的灯光().应该是这样的.问题是in_Color属性不应该干扰灯光,因为如果启用灯光,它甚至都不会运行.您还可以看到图像中的任何内容都不是红色,这意味着在此场景en_ColorEnabled中始终是false.所以in_Color在这里完全没用,但它在逻辑上不应该导致错误.在Nvidia它上面工作正常,绿色区域有或没有in_Color.

我用的东西AMD不支持吗?我使用的是GLSL规格以外的东西吗?我知道比规范AMD更严格,所以我可能做一些未定义的事情.我使代码尽可能简单,仍然有问题,所以我没有看到它. 另外,我注意到如果顶点属性被禁用(no ),它将不会在屏幕上绘制任何(甚至蓝色区域),但为什么呢?我甚至不使用这种颜色.禁用属性需要通过规范返回()吗?我试着改变那种颜色,但仍然变黑.编译器和链接器不会返回任何错误或警告.找到属性in_Color就好了.但正如我所说,这一点都不重要,因为该分支永远不会在我的代码中执行.有任何想法吗?GLNvidia
in_ColorglEnableVertexAttribArray0,0,0,1glVertexAttrib4fglGetAttribLocation

测试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;
}

我明白了: 没有按预期分支

最后一个是我所期望的,但前一个没有绘制任何东西,即使我做add(+)而不是其他任何东西.因此,如果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.所以我想这会慢一点我浪费带宽?但至少它是有效的...但如何更好地做到这一点的帮助将是有用的.

撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有