目前我正在学习如何在GLSL中为我正在研究的游戏引擎创建着色器,我对这个令我困惑的语言有疑问.我已经了解到,在低于3.0的着色器版本中,您不能在循环条件下使用统一变量.例如,以下代码不适用于早于3.0的着色器版本.
for (int i = 0; i < uNumLights; i++)
{
...............
}
Run Code Online (Sandbox Code Playgroud)
但是不可能用具有固定迭代量的循环替换它,但是如果i(在这种情况下,i)大于uNumLights,则包含一个条件语句会破坏循环.例如:
for (int i = 0; i < MAX_LIGHTS; i++)
{
if(i >= uNumLights)
break;
..............
}
Run Code Online (Sandbox Code Playgroud)
这些不等同?后者应该使用旧版本的GLSL吗?如果是这样,这比我读过的其他技术更有效,更容易实现,比如使用不同版本的着色器来获得不同数量的灯光?
我知道这可能是一个愚蠢的问题,但我是初学者,我找不到为什么这不起作用的原因.
Dam*_*mon 13
GLSL可能会让for()
你感到困惑,因为必须有条件分支,即使没有条件分支,因为硬件根本无法完成(这同样适用if()
).
什么真正发生在SM3前硬件是你的OpenGL实现内HAL将完全展开你的循环,所以实际上没有任何跳更多.并且,这解释了为什么使用非常数很难做到这一点.
虽然技术上可以使用非常量来实现,但是每次更改该统一时,实现都必须重新编译着色器,如果您只是允许提供任何随机数,它可能会违反最大指令数.
这是一个问题因为......那么呢?那是一个糟糕的情况.
如果提供的常量太大,则在构建着色器时会给出"太多指令"编译器错误.现在,如果你在制服中提供一个愚蠢的数字,并且HAL因此必须产生新的代码并且在这个限制下运行,那么OpenGL可以做什么?
您很可能在编译和链接后验证了您的程序,并且您最有可能查询着色器信息日志,并且OpenGL一直告诉您一切都很好.在某种程度上,这是一个有约束力的承诺,它不能一下子就决定.因此,它必须确保不会出现这种情况,唯一可行的解决方案是不允许在不支持动态分支的硬件代的情况下使用制服.
否则,需要在内部进行某种形式的验证glUniform
,拒绝不良值.但是,由于这取决于成功(或不成功)着色器重新编译,这意味着它必须同步运行,这使得它成为一种"不行"的方法.此外,考虑GL_ARB_uniform_buffer_object
在某些SM2硬件(例如GeForce FX)上暴露,这意味着您可以在OpenGL中抛出具有不可预测内容的缓冲区对象,并且仍然期望它以某种方式工作!在取消映射后,实现必须扫描缓冲区的内存中的无效值,这是疯了.
与循环类似,if()
语句不会在SM2硬件上分支,即使它看起来像它.相反,它将计算两个分支并进行有条件的移动.
归档时间: |
|
查看次数: |
5569 次 |
最近记录: |