我有一个相当简单的片段着色器,用于处理多个灯光的情况(为了清晰起见,下面的代码被修剪下来,只显示了两个灯光。)
广泛的想法是总结每个片段的各种照明贡献,它工作正常,但我发现它在我的硬件(Android HTX Desire X)上是不稳定的。
测量FPS,很明显有一条vec4附加线导致FPS下降10。
在这样一个看似简单的操作中可能导致这种性能上升的原因是什么?
void main (void)
{
vec4 v = u_ViewModelMatrix * vec4(v_Vertex, 1.0);
vec3 nv = normalize(-v.xyz);
vec3 normalVector = normalize((u_ViewModelTransposeMatrix * vec4(normalize(v_Normal), 0.0)).xyz);
vec4 finalColour = vec4(0.0, 0.0, 0.0, 1.0);
// LIGHT 0
lightPosition = vec4(u_LightData[2], u_LightData[3], u_LightData[4], 1);
lightColour = vec4(u_LightData[5], u_LightData[6], u_LightData[7], 1.0) * u_LightData[0];
lightVector = normalize((u_ViewMatrix * lightPosition).xyz - v.xyz);
halfwayVector = normalize(lightVector + nv);
facing = dot(normalVector, lightVector);
if (facing >= 0.0) {
finalColour = finalColour + diffuseColour * facing * lightColour;
}
// LIGHT 1
lightPosition = vec4(u_LightData[LIGHTS_FLOATS_PER_LIGHT*1+2],
u_LightData[LIGHTS_FLOATS_PER_LIGHT*1+3],
u_LightData[LIGHTS_FLOATS_PER_LIGHT*1+4],
1);
lightColour = vec4(u_LightData[LIGHTS_FLOATS_PER_LIGHT*1+5],
u_LightData[LIGHTS_FLOATS_PER_LIGHT*1+6],
u_LightData[LIGHTS_FLOATS_PER_LIGHT*1+7],
1.0) * u_LightData[LIGHTS_FLOATS_PER_LIGHT*1];
lightVector = normalize((u_ViewMatrix * lightPosition).xyz - v.xyz);
halfwayVector = normalize(lightVector + nv);
facing = dot(normalVector, lightVector);
if (facing >= 0.01) {
vec4 qwe = diffuseColour * facing * lightColour;
// HERE .............
finalColour = finalColour + qwe; // takes 10 fps
// HERE ^^^^^^^^^^^^^
}
gl_FragColor = finalColour;
}
答案 0 :(得分:1)
分支导致这种情况。避免使用ifs和for循环。 取代
if (facing >= 0.0) {
finalColour = finalColour + diffuseColour * facing * lightColour;
}
与
finalColour += max(0.0, facing) * diffuseColour * lightColour;
和
if (facing >= 0.01) {
vec4 qwe = diffuseColour * facing * lightColour;
// HERE .............
finalColour = finalColour + qwe; // takes 10 fps
// HERE ^^^^^^^^^^^^^
}
与
finalColour += step(0.01, facing) * facing * diffuseColour * lightColour;
即使您不需要计算某些值,也不要担心。由于着色器是并行执行的,因此不能比最慢的实例快得多。
此外,您应该尽可能多地向顶点着色器移动,因为对于每个顶点和片段着色器中的每个像素,它只执行一次;基本上你计算(tri)在顶点着色器中插值并将其作为变化传递的所有内容: