GLSL 错误:绘制调用中未启用顶点属性

Ale*_*nus 2 android glsl vertex-shader opengl-es-2.0 glsles

我正在 OpenGL ES 2.0 中为 android 编写一个应用程序,但我遇到了一些着色器代码的问题。这里是:

attribute vec4 vPosition;
vec4 tempPosition;

void main() {
    tempPosition = vPosition;
    tempPosition.x = 2 - tempPosition.x;
    gl_Position = tempPosition.yxzw;
}
Run Code Online (Sandbox Code Playgroud)

导致错误的行是这一行:

tempPosition.x = 2 - tempPosition.x;
Run Code Online (Sandbox Code Playgroud)

每次我想绘制一些东西时,我都会启用和禁用顶点 atrrib 数组。在我画画之前我称之为:GLES20.glEnableVertexAttribArray(sPosition);在我画画之后,我称之为 GLES20.glDisableVertexAttribArray(sPosition);

我究竟做错了什么?如何从 2 中减去 x?

编辑:

如果我将导致错误的行更改为:

tempPosition.xz = vec2(2,0) - tempPosition.xz;
Run Code Online (Sandbox Code Playgroud)

比它有效,但为什么我不能用单个数字减去?

Ret*_*adi 5

在与 ES 2.0 一起使用的 GLSL 版本(有点神秘的是版本 1.00)中,没有隐式类型转换。您不能将 type 的值添加int到 type 的值float或浮点数向量中。

这是在规范第 4 章“变量和类型”的介绍中指定的:

OpenGL ES 着色语言是类型安全的。类型之间不存在隐式转换。

对于这种情况,更详细的信息请参见第 5.9 节“表达式”,其中+定义了运算符:

两个操作数必须是同一类型,或者一个可以是浮点标量,另一个可以是浮点向量或矩阵,或者一个可以是整数标量,另一个可以是整数向量。

因此,在使用浮点运算时需要使用浮点常量:

tempPosition.x = 2.0 - tempPosition.x;
Run Code Online (Sandbox Code Playgroud)

更有趣的情况是为什么你的第二次尝试成功了,因为你还混合了不同的类型:

tempPosition.xz = vec2(2,0) - tempPosition.xz;
Run Code Online (Sandbox Code Playgroud)

这是合法的,因为构造函数用于转换类型,并且是执行此操作的主要机制。例如,您可以将原始表达式写为:

tempPosition.x = float(2) - tempPosition.x;
Run Code Online (Sandbox Code Playgroud)

对于常量值来说这看起来很尴尬,但如果整数值在变量中则更有意义:

int foo = ...;
tempPosition.x = float(foo) - tempPosition.x;
Run Code Online (Sandbox Code Playgroud)

回到向量的情况,第 5.4.2 节“向量和矩阵构造函数”指定:

如果构造函数参数的基本类型(bool、int 或 float)与正在构造的对象的基本类型不匹配,则使用标量构造规则(上面)来转换参数。

这意味着您可以使用int值作为 a 构造函数的参数vec2,即使它包含float值。在这种情况下,该值会自动转换。换句话说,你的第二条语句相当于:

tempPosition.xz = vec2(float(2), float(0)) - tempPosition.xz;
Run Code Online (Sandbox Code Playgroud)

恕我直言,不依赖隐式转换仍然更清晰,并编写:

tempPosition.xz = vec2(2.0, 0.0) - tempPosition.xz;
Run Code Online (Sandbox Code Playgroud)

请注意,完整的 OpenGL 在这方面与 OpenGL ES 不同。在完整的 GLSL 中,存在隐式类型转换。我个人认为这很不幸,因为我相信类型安全是一个有用的原则。