2

我有一个相当简单的片段着色器,用于处理多灯的情况(为了清楚起见,下面的代码被剪掉了,只显示了两个灯)。

大致的想法是总结每个片段的各种照明贡献,它工作正常,但我发现它在我的硬件(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;
}
4

1 回答 1

1

分支导致这种情况。避免使用 if 和 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;

即使您不需要计算某些值,也不必担心。由于着色器是并行执行的,因此您无法比最慢的实例快得多。

此外,您应该将尽可能多的东西移动到顶点着色器,因为它将对每个顶点执行一次,而不是对片段着色器中的每个像素执行一次;基本上,您计算在顶点着色器中(三)插值良好的所有内容并将其作为变量传递:

  • 灯的位置和颜色
  • 向量 L、V 和 H(至少在这个例子中)
于 2013-11-18T21:02:45.250 回答