【问题标题】:GLSL performance issue in fragment shader on vec4 addvec4 添加片段着色器中的 GLSL 性能问题
【发布时间】:2013-05-05 04:37:57
【问题描述】:

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

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

【问题讨论】:

    标签: android performance opengl-es fragment-shader


    【解决方案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(至少在本例中)

    【讨论】:

    • “即使您不需要计算某些值,也不必担心。由于着色器是并行执行的,因此不会比最慢的实例快得多。 " - 是的,就像分支版本一样。并不是说分支立即是邪恶的,只是可能会进行不必要的计算,就像在您的无分支版本中一样,只是基于分支的版本可能会在整个块不采用分支时阻止计算,而您的无分支版本会总是做所有的操作。
    • 这非常有用 - 将一些冗余代码从片段着色器移动到顶点着色器会产生很大的不同。更不用说删除 if/then 调用了。
    猜你喜欢
    • 2020-11-20
    • 1970-01-01
    • 1970-01-01
    • 2017-04-12
    • 1970-01-01
    • 1970-01-01
    • 2016-01-08
    • 2014-07-26
    • 1970-01-01
    相关资源
    最近更新 更多