5

AppleのOpenGLESのベストプラクティスでは、フラグメントシェーダーで計算された結果を分岐しないことを推奨しています。ただし、フォンシェーディングでは、一般に、光源がサーフェスの「間違った」側にある場合に鏡面反射光の用語をスキップする必要があります。この場合、ユニットの法線方向Nと光の方向にドットを付けLて、肯定的な結果を確認するのが簡単です。

シェーダーに分岐を付けずにこれを実行しようとしました。ステートメントを使用する代わりに、鏡面反射項のすべての計算を実行してから、ゼロより大きい場合などifの係数を指定します。(組み込み関数を使用してこれを実現します。組み合わせて同じ結果を生成しますが、少し遅いと言われています。)1.0dot(N, L)0.0step()max()sign()

ただし、これにより、デバイス固有および/またはiOSバージョン固有の奇妙な結果が生じるように見えました。

ブランチ付きブランチなし

  • iOS6.0を実行している私のiPhone4では、ブランチのあるバージョンには広い鏡面ハイライトがあります(左の画像)。ブランチがないと、「光沢」指数は同じままですが、狭い鏡面ハイライト(右の画像)が表示されます。
  • iOS 6.0シミュレーターで、両方のバージョンのシェーダーを含む2番目の画像が表示されます。
  • 私のiPad(元の2010モデル、iOS 5.1でスタック)では、両方のバージョンのシェーダーを含む最初の画像が表示されます。

明らかに、問題は分岐やその欠如ではありません。(ちなみに、右側の画像は「正しい」レンダリングです。)

これが私のフラグメントシェーダーです:

precision mediump float;

uniform lowp vec3 ambientLight;
uniform lowp vec3 light0Color;
uniform lowp vec3 materialAmbient;
uniform lowp vec3 materialDiffuse;
uniform lowp vec3 materialSpecular;
uniform lowp float materialShininess;

// input variables from vertex shader (in view coordinates)
varying vec3 NormDir;
varying vec3 ViewDir;
varying vec3 LightDir;

void main (void)
{
    vec3 L = normalize(LightDir);
    vec3 N = normalize(NormDir);
    vec3 E = normalize(ViewDir);

    lowp vec3 ambient = ambientLight * materialAmbient;

    float cos_theta = dot(L, N);

    lowp vec3 diffuse = materialDiffuse * light0Color * max(0.0, cos_theta);

    lowp vec3 specular = vec3(0.0, 0.0, 0.0);
//  if (cos_theta > 0.0) {
        lowp vec3 R = reflect(-L, N);
        lowp vec3 V = normalize(-E);
        float cos_alpha = dot(R, V);
        specular =  step(0.0, cos_theta) *  materialSpecular * light0Color * pow(max(0.0, cos_alpha), materialShininess);
        //          ~~~~~~~~~~~~~~~~~~~~~~
        //          should produce the same results as the commented branch, right?
//  }
    gl_FragColor = vec4(ambient + diffuse + specular, 1.0);
}

iOSハードウェアでこのシェーダーのパフォーマンスを改善するためのさらなる提案も歓迎します!

4

1 に答える 1

1

@BradLarsonのコメントに記載されているように、lowp上の修飾子materialShininessが問題であることが判明しました。代わりに設定すると、シェーダーのブランチバージョンmediumpまたはブランチなし(with)バージョンが使用されているかどうかに関係なく、手元にあるすべてのデバイスとOSバージョンで正しくレンダリングされます(右側の画像) 。step

(入力にlowpvsを使用し、そこから計算されても、目に見える違いはありません。これは理にかなっています。これらは正規化されたベクトルであるため、それらの成分の大きさは0.0〜1.0の範囲です。これは色成分と同じ範囲です。意図されているようです。)mediumpRVcos_alphalowp

于 2013-02-13T18:35:45.987 に答える