OpenGL 有预着色器吗?

3
我的问题很简单,但是我在网上找不到答案。OpenGL / OpenGL ES是否有类似于DirectX的预着色器?
这样你就可以写出像这样的东西:
mat4 wvpMat = worldMat * viewMat * projMat;
gl_Position = wvpMat * position;

它将仅在preshader中计算wvpMat一次。或者这不被支持,应该在CPU上进行操作?

参见Riemers示例(XNA):

XNA with preshaders

2个回答

4

OpenGL 定义了几个着色器阶段

  1. 顶点着色器:首先运行所有要绘制的点

  2. 可选的2个着色器进行曲面细分:控制着色器指定如何细分和评估着色器执行实际细分

  3. 可选的几何着色器:为每个绘制的基元发射可变数量的基元

  4. 片段着色器:对每个片段运行

驱动程序允许在链接程序时根据需要对每个着色器进行优化,这可能包括生成预着色器。但是,这是实现定义的。


这意味着根据驱动程序的不同,它可能会生成一个预着色器?为了保险起见,我应该在 CPU 上执行此操作。 - HellGate
@HellGate 不,为了保持“理智”,你应该测量时间并与预期结果进行比较。 - Bartek Banachewicz
这并不是真的,你的测量结果只适用于你特定的平台、驱动程序版本等,而且有许多不同的配置可能会导致事情变慢。我通常在 CPU 上生成我的模型-视图-投影矩阵,它没有任何惩罚(3 个 4x4 矩阵乘法几乎不需要时间),并且仅针对每个(可能很大的)几何批次执行一次。 - Marius
当我有时间时,我会尝试在我的平台上进行性能分析,但是在CPU上运行它不需要太多时间,正如msdn所说,它也在CPU上执行preshader。这更像是你习惯写它的方式,我发现将mat4分离到着色器中很方便。 - HellGate
3
您也可以查看来自不同供应商的建议。例如,Imagination(可能与opengl-es标签相关)指出:“PowerVR着色器编译器能够从着色器中提取基于uniform的计算,并在每个绘制调用中执行这些计算一次。” - GuyRT
很好的总结。请注意,镶嵌着色器和几何着色器仅适用于桌面OpenGL,而不适用于OpenGL ES。 - rickster

2

目前的OpenGL版本并没有类似预着色器的东西。个人认为它们实际上并没有什么好处,但其他人可能非常喜欢它们,因此即将推出的OpenGL版本可能会有它们。


谢谢你的回答,即使它不是我想听到的答案 :P。看来我得重新写一些东西了。 - HellGate
@HellGate 在你重写任何东西之前,请检查驱动程序是否实际上优化了指令。预着色器的整个概念基于手动优化与机器优化的想法,后者现在往往更加优越。 - Bartek Banachewicz
@HellGate:就像Bartek告诉你的那样,驱动程序有很大的自由度来优化事物。与Direct3D的主要区别在于,Direct3D中的HLSL代码被编译为一个中间件,然后您将其发布。正是这个中间件实现了预着色器。然而,在OpenGL中,您使用GLSL进行编译时运行。最初,GLSL编译器非常糟糕。如今,它们已经变得相当不错了。一些OpenGL实现(如Mesa)实际上利用现有的编译器基础设施,例如LLVM(也用于clang)。 - datenwolf
@HellGate:好的GLSL编译器会检测所有输入值相同的表达式并进行优化。以前在NVidia上是一个性能问题,因为他们的编译器有点过于热心,每当一个uniform值被改变时就重新编译着色器,但现在这不再是一个问题了。 - datenwolf
@datenwolf:感谢您的信息,但我无法确定我的平台编译器是否是“好”的。所以最好还是自己动手,这样我就知道发生了什么。正如之前所说,dx9编译器也会在CPU上进行预着色,因此结果应该是相同的,只是没有自动化。 - HellGate

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接