Architecture GLSL多着色器程序与统一开关

Architecture GLSL多着色器程序与统一开关,architecture,glsl,shader,Architecture,Glsl,Shader,我正在研究着色器管理器体系结构,我有几个问题要问更高级的人。 我目前的选择反对以下两种设计: 1。每材质着色器程序 =>为程序中使用的每个材质创建一个着色器程序 潜在的缺点: 考虑到每个对象都可能有自己的材质,它涉及到大量GluseProgramm调用 意味着创建大量着色器程序对象 比#2更复杂的架构 赞成的意见: 可以专门为材质中使用的每个“选项”生成着色器代码 如果我没有错的话,制服只需设置一次(创建着色器程序时) 2。全局着色器程序 =>为每个着色器功能(闪电、反射、视差贴图…)创

我正在研究着色器管理器体系结构,我有几个问题要问更高级的人。 我目前的选择反对以下两种设计:


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

潜在的缺点:
  • 考虑到每个对象都可能有自己的材质,它涉及到大量GluseProgramm调用
  • 意味着创建大量着色器程序对象
  • 比#2更复杂的架构
赞成的意见:
  • 可以专门为材质中使用的每个“选项”生成着色器代码

  • 如果我没有错的话,制服只需设置一次(创建着色器程序时)

2。全局着色器程序 =>为每个着色器功能(闪电、反射、视差贴图…)创建一个着色器程序,并根据要渲染的材质使用配置变量启用或放弃选项

潜在的缺点:
  • 每帧的制服都要换很多次
赞成的意见:
  • 较低的着色器程序计数
  • 少SP开关(glUseProgram)

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

  • 初始制服设置是否抵消了GluseSprogram呼叫开销(我不是特别喜欢速度)
  • 在案例#1中,出于任何内存或性能考虑,我应该在创建SP时只调用一次glLinkProgram,还是每次调用glUseProgram时都必须取消链接/链接
  • 有更好的解决方案吗

谢谢

这实际上取决于您的硬件和应用程序的特定需求

#2的另一个缺点是,着色器通常没有那么有效,因为它必须根据传入的一致性执行一些条件分支。因此,您基本上是在着色器中切换状态的时间减少与吞吐量减少之间进行权衡。这取决于哪个更糟

每个着色器只能调用一次glLinkProgram。编译着色器比关闭已编译的着色器花费更长的时间

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

让我们看看#1:

考虑到每个对象都可能有自己的材质,它涉及到大量GluseProgramm调用

这没什么大不了的,真的。交换程序是困难的,但你也会交换纹理,所以这并不是说你还没有改变重要的状态

意味着创建大量着色器程序对象

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

或者您可以使用,这有助于缓解这种情况。它的许多优点之一是,它将材质数据的生成与将材质数据转换为光反射(颜色)的计算分离开来。因此,可以使用的着色器要少得多。您有一组生成材质数据的着色器,以及一组使用材质数据进行照明计算的着色器


所以我想说使用#1进行延迟渲染。

在移动设备上,着色器中的分支会大大增加渲染时间。在逐顶点/逐纹理重复操作中,您应该测量切换程序的时间与减少的绘制速率之间的关系。我推荐方法#1,并了解如何为良好的面向对象友好着色器体系结构设置GPUImage


确切地说,我计划使用延迟渲染。我从暴雪的星际争霸II引擎文件中读到这个,我不确定它的确切含义:<代码>。因此,在我们的游戏中编写着色器代码通常非常接近于在我们的项目中添加一个常规的C++文件。形象地说,我们把着色器代码视为C++调用的一个外部库,着色器代码是一个自由形式的代码体,它在结构上是C++代码库。 <代码>,着色器的概念可以是星际争霸II中的一个胡松代码。着色器代码库定义了几个不同的着色器的入口点,但有一个入口点可以自由调用着色器代码的任何部分。因此,很难说星际争霸II使用了多少个“单独的”着色器,因为它是一个代码体,对于一个视频选项配置,通常会从中派生出上千个着色器排列。@Profet:这与延迟渲染没有任何关系。这是暴雪在引擎中设置的处理着色器的机器的一部分。是的,我知道,但这台机器看起来像一种动态着色器生成器,不是吗?:)有人能举个例子,通过不同的着色器保持一致性,而不在着色器之间复制代码吗?我想到的第一件事是能够通过着色器保持MVP矩阵不变。有没有这方面的示例代码?要强调的是,顶点/片段着色器中的分支是不好的。使用更复杂的GPU(例如,在分支上刷新更长的管道)不会更好。我认为这不太正确——着色器中的分支本身不需要管道刷新。改变着色器。据我所知,现代卡将状态存储在状态寄存器中,并通过管道线发送带有命令的寄存器名称,以防止着色器/纹理更改时刷新。另一方面,如果分支预测错误,它必须中止所有已完成的工作(如纹理提取..极高的延迟),然后重新开始。读得好:啊,好的。谢谢你的链接。@fscan:“顶点/片段着色器中的分支不好。使用更复杂的GPU不会变得更好”,这已经不是真的了。PS4 GPU可以处理br