1

此着色器程序在 Radeon 3450M、GT 550Ti、GT430 等上运行良好,但在 Intel HD4000 上失败。有什么想法可能是错误的,或者建议让着色器对英特尔更友好?

顶点着色器:

uniform mat4    uniform_Projection;
attribute vec4  attribute_Position;
attribute vec4  attribute_Color;
varying vec4    varying_Color;
vec4    varying_Color_Bak;

void main(void)
{
  varying_Color.x = clamp(abs((attribute_Position.x + 3.0f) / 5.0f), 0.1f, 1.0f);
  varying_Color.y = clamp(abs((attribute_Position.y + 3.0f) / 5.0f), 0.1f, 1.0f);
  varying_Color.z = 0.0f;//clamp(abs((attribute_Position.x + attribute_Position.y + 4.0f) / 7.0f), 0.1f, 1.0f);
  varying_Color.w = 0.9f;
  gl_Position = uniform_Projection * attribute_Position;
}

片段着色器:

uniform mat4    uniform_Projection;
varying   vec4    varying_Color;
vec4    varying_Color_Bak;
void main (void)
{
   varying_Color_Bak = varying_Color;
   varying_Color = uniform_Projection * varying_Color;
   for (int i = 0; i < 3; i++) {
      varying_Color = sin(varying_Color);
      varying_Color = inversesqrt(abs(varying_Color));
      varying_Color = abs(log(varying_Color));
   }
   varying_Color = clamp(varying_Color, 0.1f, 1.0f);
   varying_Color = mix(varying_Color, varying_Color_Bak, 0.9f);
   gl_FragColor = sin(varying_Color);
}
4

2 回答 2

3

使这个可移植的第一件事是添加#version 120到着色器的顶部。正如评论中所讨论的,可选的f浮点精度后缀是 GLSL 1.2 添加的。在 GLSL 1.1 中,规范不包括这一点,如果严格遵守的编译器在 GLSL 1.1 着色器中遇到这一点,则会发出解析错误。

这里的基本问题是,如果您不在#version着色器顶部包含指令,则兼容的 GLSL 编译器应该假定着色器是根据 GLSL 1.1 规范编写的。许多编译器会放宽这些规则,您可以使用 GLSL 1.1 中不存在的语法而无需发出警告,但其他编译器则非常严格。如果没有办法提示 GLSL 编译器实现在其警告中更加冗长,您必须自己熟悉每个 GLSL 版本之间的差异。ANGLE 项目提供了一个可移植的着色器验证器(大多数 WebGL 实现都使用它),但它针对的是 OpenGL ES 2.0 的 GLSL 版本,在这里真的帮不了你。

着色器中的所有其他内容似乎对 GLSL 1.1 有效。这里#version的要点是 GLSL 着色器顶部的指令比您想象的更重要。glGetShaderInfoLog (...)那,如果你不阅读和的输出,很难诊断着色器问题glGetProgramInfoLog (...)- 每个实现都有不同的详细程度,但它们通常都会在编译/链接失败时产生有用的东西;)

于 2013-10-31T21:12:05.977 回答
2

谢谢大家的建议。从我的测试人员那里得到反馈需要一段时间,但我最终让我的程序在 Intel HD4000 上运行,而没有在其他平台上破坏程序。

我几乎没有对顶点着色器进行任何更改:

#version 120

uniform mat4    uniform_Projection;
attribute vec4  attribute_Position;
attribute vec4  attribute_Color;
varying vec4    varying_Color;

void main(void)
{
  varying_Color.x = clamp(abs((attribute_Position.x + 3.0) / 5.0), 0.1, 1.0);
  varying_Color.y = clamp(abs((attribute_Position.y + 3.0) / 5.0), 0.1, 1.0);
  varying_Color.z = 0.0;//clamp(abs((attribute_Position.x + attribute_Position.y + 4.0) / 7.0), 0.1, 1.0);
  varying_Color.w = 0.9;
  gl_Position = uniform_Projection * attribute_Position;
}

我删除了“f”修饰符,添加了一个语言版本,并删除了一个未使用的变量声明。

我对片段着色器进行了更多更改:

#version 120

uniform mat4    uniform_Projection;
varying   vec4    varying_Color;
void main (void)
{
   vec4 varying_Color_Bak;
   vec4 varying_Color_2;
   varying_Color_Bak = varying_Color;
   varying_Color_2 = uniform_Projection * varying_Color;
   for (int i = 0; i < 3; i++) {
      varying_Color_2 = sin(varying_Color_2);
      varying_Color_2 = inversesqrt(abs(varying_Color_2));
      varying_Color_2 = abs(log(varying_Color_2));
   }
   varying_Color_2 = clamp(varying_Color_2, 0.1, 1.0);
   varying_Color_2 = mix(varying_Color_2, varying_Color_Bak, 0.9);
   gl_FragColor = sin(varying_Color_2);
}

除了重复顶点着色器的所有更改之外,我还将varying_Color值复制到局部变量。这解决了 HD4000 上的错误,即 Intel 芯片不允许片段着色器修改变量。

我还发现如果我在我的 NVidia GT430之外声明我的局部变量 (varying_Color_bak和),我在 Linux 上崩溃了。但是使用里面声明的局部变量,一切似乎都可以稳定运行。varying_Color_2main()main()

于 2013-11-15T19:25:30.590 回答