在OpenGL着色器中进行main之外的计算是否合理?

sta*_*wed 2 opengl-es glsl webgl

我有一些顶点着色器代码有点像下面(这是一个简化的例子):

attribute vec2 aPosition;
attribute vec4 aColor;

varying lowp vec4 vColor;

uniform  vec4 uViewport;
mat4 viewportScale = mat4(2.0 / uViewport.z, 0, 0, 0,    0, -2.0 / uViewport.w, 0,0,    0, 0,1,0,    -1,+1,0,1);

void main() {
  vec2 pos = aPosition;
  gl_Position = viewportScale * vec4(pos, 0, 1);
  vColor = vec4(aColor.rgb*aColor.a, aColor.a);
}
Run Code Online (Sandbox Code Playgroud)

特别地,viewportScale矩阵是从主函数外部uViewport均匀计算的.从浏览器(WebGL)使用它,它似乎在我测试的每台机器上都能正常工作......特别是,当我更改变量时,矩阵会正确更新.这样做和在main函数中进行相同的计算有什么区别吗?我找不到任何与此相关的例子或讨论.viewportScaleuViewport

我遇到了一个相关的问题,这让我对这个问题有点偏执 - 至少,我想了解发生了什么.

Ret*_*adi 6

这不是GLSL ES 1.00中的合法着色器,它是与ES 2.0一起使用的GLSL版本.WebGL共享相同的GLSL定义,WebGL规范中指定了一些例外.我在WebGL规范中找不到这个例外,所以我认为着色器在ES 2.0和WebGL中都是非法的.

从GLSL ES 1.00规范,第29页"4.3存储限定符"部分(增加重点):

没有存储限定符或仅使用const限定符的全局变量的声明可能包括初始值设定项,在这种情况下,它们将在执行main()的第一行之前初始化.这种初始化器必须是一个常量表达式.

第49页的"5.10常量表达式"一节定义了常量表达式.这包括:

以下内容不能用于常量表达式:

  • 制服,属性和变化.

在您的情况下,表达式包括一个统一,这使它成为一个非常量表达式.因此,它不能用作全局变量的初始值设定项.