【发布时间】:2018-05-05 01:27:06
【问题描述】:
我有一个这样的顶点着色器
void main (){
vec4 wPos = modelMatrix * vec4( position , 1. );
vWorldPosition = wPos.xyz;
float mask = step(
0.,
dot(
cameraDir,
normalize(normalMatrix * aNormal)
)
);
gl_PointSize = mask * uPointSize;
gl_Position = projectionMatrix * viewMatrix * wPos;
}
我不完全确定如何测试着色器的性能,并排除其他因素,如过度绘制。我想一个大小为 1 的点,在屏幕空间中以网格形式排列,没有任何重叠会起作用吗?
否则我会对这些调整感到好奇:
(删除step,删除一个乘法,引入ifelse)
void main (){
if(dot(
cameraDir,
normalize(normalMatrix * aNormal) //remove step
) < 0.) {
gl_Position = vec4(0.,.0,-2.,.1);
gl_PointSize = 0.;
} else {
gl_PointSize = uPointSize; //remove a multiplication
vec4 wPos = modelMatrix * vec4( position , 1. );
vWorldPosition = wPos.xyz;
gl_Position = projectionMatrix * viewMatrix * wPos;
}
}
对比这样的:
void main (){
if(dot(
cameraDir,
normalize(normalMatrix * aNormal)
) < 0.) {
gl_Position = vec4(0.,.0,-2.,.1);
return;
}
gl_PointSize = uPointSize;
vec4 wPos = modelMatrix * vec4( position , 1. );
vWorldPosition = wPos.xyz;
gl_Position = projectionMatrix * viewMatrix * wPos;
}
这些着色器的行为会有所不同吗?为什么/如何?
如果有什么东西可以量化性能差异,我很感兴趣。
- 是否有一些值,例如 MAD 的数量或不同代码显然会产生的其他值?
- 不同代的 GPU 会以不同的方式处理这些差异吗?
- 如果保证步骤版本最快,是否有一个已知的模式列表来说明如何避免分支,以及首选哪些操作? (比如使用
floor代替step也可以?):
.
float condition = clamp(floor(myDot + 1.),0.,1.); //is it slower?
【问题讨论】:
-
有一个明显的区别,即您修改后的着色器不会在所有路径上设置输出 (gl_pointSize/gl_Position),而原始着色器会在所有路径上设置输出,因此遇到这些情况的任何顶点都可能产生垃圾。
-
啊,我没有意识到
gl_PointSize也很重要。我想我已经看到它在不同的浏览器上表现不同,有时是 0,这意味着规范没有定义它? -
我会编辑那个更有意义的,让返回的那个作为它自己的样本?
-
第二个示例现在确实设置了两个输出,但在一个分支中的计算量较少。
-
第二个示例似乎仍然在第一个
if中命中返回路径,而没有写入gl_PointSize或gl_Position,因此仍然是非法的。