目前,我有两个着色器,用于处理相同类型的对象,但产生不同的输出:屏幕一种颜色,另一种选择信息。
绘制着色器的输出:
results = (from n in foos
where (n.A == false)
&& (n.B == true || n.C == true)
select n
);
选择着色器的输出:
layout(location = 0) out vec4 outColor;
我正在考虑将着色器组合在一起(这两个和我的应用程序中的其他组合)是为了清晰和易于维护(为什么要编辑两个着色器?)。
统一着色器的输出:
layout(location = 0) out vec4 selectionInfo0;
layout(location = 1) out ivec4 selectionInfo1;
根据这个方案,我会设置一个统一来确定需要写入哪些片段。
我可以写一些片段位置而不是其他位置吗?
layout(location = 0) out vec4 outColor;
layout(location = 1) out vec4 selectionInfo0;
layout(location = 2) out ivec4 selectionInfo1;
这是合法的做法吗?有什么我应该关注的吗?
答案 0 :(得分:1)
这是合法的做法吗?
这取决于你如何定义"合法"。它可以用于功能。
片段完全是discarded ,或者不是。如果它被丢弃,那么该片段(大部分)没有效果。如果它没有被丢弃,那么它的所有输出都有定义的值(即:你写给它们),或者它们有未定义的值。
但是,未定义的值可以正常,具体取决于其他状态。例如,frambuffer's draw buffer state路由FS将颜色输出到实际颜色附件。它还可以将它们路由到GL_NONE
,这会将它们抛弃。同样,您可以在每个附件的基础上使用color write masks,关闭对您不想写的附件的写入。
但这意味着您无法基于每个片段确定它。您只能使用着色器外部的状态来确定。 FS无法实现或不发生这种情况;它必须在具有状态变化的绘制调用之间完成。
如果Mode
是某种uniform
值,则应该没问题。但如果它是基于每个顶点或每个片段派生的东西,那么这将无法有效地工作。
至于分支性能,这又取决于Mode
。如果它是uniform
,你就不应该担心。现代GPU可以处理这个问题。如果它是其他东西......好吧,你的整个计划因为已经详细的原因而停止工作,所以没有理由担心它;)
尽管如此,我建议不要这种复杂性。从司机的角度来看,处理事情是一种令人困惑的方式。此外,由于您依赖于其他应用程序不依赖的许多内容,因此您可以自行解决驱动程序错误。您的想法与传统的Ubershader不同,因为您的选择从根本上改变了渲染目标和输出的性质。
所以我建议你尝试以尽可能传统的方式做事。如果您真的想最大限度地减少使用的单独文件的数量,请使用#ifdef
,然后根据您的原因简单地使用#define
修补着色器字符串# 39;重新加载它。所以你有一个着色器文件,但是有2个程序从它构建。