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

Opengl es 在OpenGL着色器中进行main之外的计算是否合理?,opengl-es,glsl,webgl,Opengl Es,Glsl,Webgl,我有一些类似以下的顶点着色器代码(这是一个简化的示例): 特别是,viewportScale矩阵是从主函数外部的uViewportuniform计算出来的。从浏览器(WebGL)使用它,它似乎可以在我测试过的每台机器上正常工作。。。特别是,当我更改uViewport变量时,viewportScale矩阵会正确更新。这样做与在主函数内部进行相同的计算有什么区别吗?我找不到任何与此相关的例子或讨论 我遇到了一个让我对这个问题有点偏执的问题——至少,我想知道发生了什么。这不是GLSL ES 1.00中

我有一些类似以下的顶点着色器代码(这是一个简化的示例):

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


我遇到了一个让我对这个问题有点偏执的问题——至少,我想知道发生了什么。

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

根据GLSL ES 1.00规范第29页“4.3存储限定符”一节(添加了重点):

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

第49页“5.10常量表达式”一节定义了常量表达式的含义。它包括:

以下可用于常量表达式:

  • 制服、属性和变量

本例中的表达式包含一个统一表达式,这使它成为一个非常量表达式。因此,它不能用作全局变量的初始值设定项。

我在Android应用程序中遇到了这个问题

我使用片段着色器中主块外部的统一变量定义了一个变量

uniform u_rotation;
mat2 rotation = mat2(cos(u_rotation), sin(u_rotation), -sin(u_rotation), cos(u_rotation)); 
void main() {}

除了Nexus6之外,这个片段着色器在所有Android设备上都能正常工作。奇怪的是,我有两个Nexus 6,一个每次都崩溃,另一个大部分时间都得到错误的结果。

它会得到优化anyway@ratchetfreak在我链接到的相关问题中,它确实得到了优化。但是对于本文中的代码,它没有(在上一个问题之后,这让我感到惊讶)<每当我更新
uViewport
uniform时,都会更新code>viewportScale。我猜这是因为我在main中直接引用了
viewportScale
,所以编译器认为我在使用它。有编译日志输出吗?(在任何一种情况下)没有——有没有一种简单的方法可以从Firefox/Chrome中获得它?我完全相信这是非法的,但是,为什么它会按照我的意图编译和工作呢?GLSL编译器接受不符合规范的着色器是很常见的。一些供应商在这方面比其他供应商更臭名昭著。我不确定这是否只是缺乏测试,或者他们是否认为允许非一致着色器工作是在帮人们的忙。从一个版本到另一个版本加强错误检查肯定是有风险的,因为您可能会破坏以前工作的应用程序。不幸的是,如果您在一个平台上开发,然后惊奇地发现相同的代码在其他平台上不起作用。事实上,这正是我最初版本的着色器所发生的情况(在任何地方都可以正常工作,但Windows除外)。现在我假设它在将来可能会被破坏,但是我有点好奇编译器到底在做什么。把我的问题链接到这里:在Reto回答之后,你必须将旋转计算移到main()块中。
uniform u_rotation;
mat2 rotation = mat2(cos(u_rotation), sin(u_rotation), -sin(u_rotation), cos(u_rotation)); 
void main() {}