我一直在阅读很多关于制服的文章,如果这些陈述涉及分支以改变大型着色器“超级着色器”的行为。我开始使用超级着色器(opengl lwjgl),但后来我意识到,在没有统一if语句的单独着色器中,在片段着色器中添加if语句设置简单计算的简单操作会使我的fps减少5。我没有为我的fps限制设置任何上限,它只是尽可能快地刷新。我即将添加法线贴图和parrallax贴图,我可以看到两条路线:
Uber顶点着色器:
#version 400 core
layout(location = 0) in vec3 position;
layout(location = 1) in vec2 textureCoords;
layout(location = 2)in vec3 normal;
**UNIFORM float RenderFlag;**
void main(void){
if(RenderFlag ==0){
//Calculate outVariables for normal mapping to the fragment shader
}
if(RenderFlag ==1){
//Calcuate outVariables for parallax mapping to the fragment shader
}
gl_Position = MVPmatrix *vec4(position,1);
}
Uber片段着色器:
layout(location = 0) in vec3 position;
layout(location = 1) in vec2 textureCoords;
layout(location = 2)in vec3 normal;
**UNIFORM float RenderFlag;**
**UNIFORM float reflectionFlag;** // if set either of the 2 render modes
will have some reflection of the skybox added to it, like reflective
surface.
void main(void){
if(RenderFlag ==0){
//display normal mapping
if(reflectionFlag){
vec4 reflectColor = texture(cube_texture, ReflectDirR) ;
//add reflection color to final color and output
}
}
if(RenderFlag ==1){
//display parrallax mapping
if(reflectionFlag){
vec4 reflectColor = texture(cube_texture, ReflectDirR) ;
//add reflection color to final color and output
}
}
gl_Position = MVPmatrix *vec4(position,1);
}
这个(对我来说)的好处是简单的流程,但是使整个程序更复杂,并且我面对丑陋的嵌套if语句。此外,如果我想完全避免if语句,我需要4个单独的着色器,一个用于处理每个可能的分支(正常无反射:正常反射:Parrallax w / o反射:Parrallax with reflection)仅适用于一个特征,反射。
1:GLSL是否执行分支和后续分支并计算BOTH函数然后输出正确的分支?
2:我应该删除if语句而不是反射的统一标志,而不是无论如何计算反射颜色,如果它是一个相对较小的操作,如果
,则将其添加到最终颜色finalColor = finalColor + reflectionColor * X
where X = a uniform variable, if none X == 0, if Reflection X==some amount.
答案 0 :(得分:3)
马上,让我指出GL4添加了子程序,它们是你讨论过的两种东西的组合。但是,除非您使用单个基本着色器的大量排列,这些排列在一帧期间多次换出(如果您在前向渲染引擎中有一些动态材质系统,可能会如此),子程序实际上并不是表现胜利。我在自己的工作中花费了一些时间和精力,并且在一个特定的硬件/驱动程序组合上得到了有价值的改进,并且对大多数其他组合没有明显的改变(好的或坏的)。
为什么我提出子程序?主要是因为你正在讨论什么是微优化,而子程序是一个非常好的例子,说明为什么在开发结束之前投入大量时间来考虑这一点并不值得付出代价。如果您正在努力满足一些性能数字,并且您已经越过列表中的每个高级优化策略,那么您可以担心这些问题。
那就是说,几乎不可能回答GLSL如何执行着色器。它只是一种高级语言;自GLSL创建以来,底层硬件架构已经多次改变。最新一代的硬件具有实际的分支预测和一些非常复杂的线程引擎,GLSL 1.10类硬件从未有过,其中一些实际上直接通过计算着色器直接暴露。
您可以运行这些数字,看看哪种策略最适合您的硬件,但我认为您会发现它是旧的微观优化困境,您甚至可能无法获得足够的可衡量的性能差异猜猜要采取哪种方法。请记住"优步着色器"由于多种原因(并非所有性能相关)都很有吸引力,其中最重要的是,批量绘制命令可能越来越少。如果性能没有明显差异,请考虑设计更简单,更容易实现/维护。