2

次のように、WebGL で複数のテクスチャを 1 つのパスでレンダリングする方が高速でしょうか。

varying float materialIndex;
varying vec2 textureCoord; 

uniform sampler2D textureSampler1;
uniform sampler2D textureSampler2;
uniform sampler2D textureSampler3;
uniform sampler2D textureSampler4;

vec4 getMaterial(float materialId, textureCoord) {
    vec4 color;

    if (materialId == 1.0)
    {
        color = texture2D( textureSampler1, textureCoord );
    }
    else if (materialId == 2.0)
    {
        color = texture2D( textureSampler2, textureCoord );
    }
    else if (materialId == 3.0)
    {
        color = texture2D( textureSampler3, textureCoord );
    }
    else
    {
        color = texture2D( textureSampler4, textureCoord );
    }

    return color;
}

void main()               
{                  
    vec4 color = getMaterial(materialIndex, textureCoord);
    gl_FragColor = color;        
}

これにより、CPU が GPU に送信する必要がある命令の 4 分の 1 を節約できるため、頂点シェーダーが渡す必要のある追加の情報に加えて、多くの場合、4 倍のプログラム呼び出しを行うよりも高速ではないでしょうか。 OpenGL でさえ、最大のパフォーマンス ヒットは CPU であると読んだことがありますが、これは Webgl の場合にさらに当てはまります。それとも、これはおそらくより速いでしょうか?

uniform float materialIndex;
varying vec2 textureCoord; 

uniform sampler2D textureSampler1;
uniform sampler2D textureSampler2;
uniform sampler2D textureSampler3;
uniform sampler2D textureSampler4;


void main()               
{                  
    vec4 color = getMaterial(materialIndex, textureCoord);
    gl_FragColor = color;        
}

それとも、機能的なユニフォームを変更することは、CPU が実行しなければならない呼び出しの数に関して、新しいシェーダーをロードすることと同じくらい悪いことですか?

4

1 に答える 1

2

はい、バッチ処理は重要です。しかし、それはそれほど重要ではありません。特に、一部のハードウェアが4 つのテクスチャすべてからサンプリングできる可能性に直面した場合は特にそうです。

さまざまなケースでは、コンパイラは値がどのように変化するかを認識していません。したがって、任意のフラグメントが任意の値を取得できると想定されます。したがって、すべてに対してランタイム ブランチを実行する必要があります。また、条件分岐のコストがかかるため、コンパイラは通常、利用可能なすべてのパスを単純に実行し、非分岐ロジックを使用して最終結果を計算することにより、4 つの連続する条件分岐を回避しようとします。

一部の古いハードウェアは機能的に重要な命令の条件付き分岐をまったく実行できないため、均一なケースもそのような「最適化」から安全ではありません。したがって、ユニフォームを変更するたびにシェーダーを再コンパイルするか (これは誇張ではありません。古いハードウェアの NVIDIA コンパイラーは実際にそれを行っていました)、4 つのテクスチャ アクセスすべてを行うしかありません。

ああ、もう1つtexture2D、不均一な制御フロー(条件付きで実行されるブロックなど)では、関数は未定義になります。さて、あなたがそれをどのように使っているかという理由で、おそらくここであなたを傷つけることはありません. ただし、一般的に言えば、明示的なグラデーションを使用するか、条件付きブロックからテクスチャ アクセス関数を削除する必要があります。また、WebGL にはグラデーション テクスチャ機能がありません。

要するに、テクスチャを変更して再度レンダリングするだけです。JavaScript でも、4 つのテクスチャ アクセスを実行する可能性があるほど、パフォーマンスが低下することはありません。レンダー間でテクスチャをバインドするだけで (つまり、プログラムやその他の状態を変更していない)、適切な方法を守っている (状態変更間でできる限り多くのレンダリングを行う) 限り、比較的問題はありません。 .

于 2013-03-02T05:28:36.867 に答える