GLSL多重着色器程序VS制服开关

我正在着色器pipe理器架构上工作,对于更高级的人员我有几个问题。 我目前的select反对两种devise:

1.每个材质着色器程序

=>为程序中使用的每种材质创build一个着色器程序。

潜在缺点:

  • 考虑到每个对象可能有自己的材料,它涉及到很多glUseProgram调用。
  • 意味着创build了许多shaderprogram对象。
  • 更复杂的架构#2。

优点:

  • 可以为材质中使用的每个“选项”专门生成着色器代码。
  • 如果我没有错,那么制服只能被设置一次(当创build阴影程序时)。

2.全球着色器程序

=>为每个着色器function(闪电,reflection,视差映射…)创build一个着色器程序,并根据要渲染的材质使用configurationvariables启用或放弃选项。

潜在缺点:

  • 制服必须每帧更换多次。

优点:

  • 较低着色器程序计数。
  • 减lessSP swich(glUseProgram)。

你可能会注意到我目前的倾向是#1,但是我想知道你对此的看法。

  • 初始制服设置是否抵消了glUseProgram调用开销(我不是特别的速度怪胎)?
  • 在情况1中,对于任何内存或性能的考虑,我应该在创buildSP时只调用一次glLinkProgram,或者每次调用glUseProgram时都必须取消链接/链接?
  • 有更好的解决scheme吗?

谢谢!

我们来看看#1:

考虑到每个对象可能有自己的材料,它涉及到很多glUseProgram调用。

这并不是什么大事,真的。 交换程序很难,但是你也会交换纹理,所以不是你已经改变了重要的状态。

意味着创build了许多shaderprogram对象。

这将会受到伤害。 事实上,#1的主要问题是着色器的爆炸性组合。 虽然ARB_separate_program_objects会有所帮助,但这仍然意味着您必须编写很多着色器,或者想出一个不写很多着色器的方法。

或者你可以使用延迟渲染 ,这有助于缓解这一点。 其众多优点之一是将材料数据的生成与将该材料数据转换为光reflection(颜色)的计算分开。 正因为如此,你所使用的着色器要less得多。 您有一组着色器可生成材质数据,另一组使用材质数据进行光照计算。

所以我会说使用延迟渲染#1。

这真的取决于你的硬件和你的应用程序的具体要求。

#2的另一个含义是,你的着色器通常最终效率不高,因为它必须根据你传入的制服做一些条件分支。所以你基本上是在更less的时间切换状态与着色器的吞吐量下降之间进行交换。 这取决于哪一个更糟糕。

你绝对只能每个着色器调用一次glLinkProgram。 编译着色器需要比转换已经编译好的着色器长得多的时间。

没有任何更好的解决scheme。 几乎每个编写渲染引擎的人都必须做出你所面临的决定。

在移动设备上,使用着色器进行分支会大大增加渲染时间。 您应该在切换程序的时间上进行一些测量,而在每个顶点/每个纹理元素的重复操作中,要减less与分支相关的绘制速率。 我build议使用方法#1,并且看看GPUImage是如何被设置为一个好的友好的着色器架构。

https://github.com/BradLarson/GPUImage