3

入力テクスチャのチャネルの 1 つ (R など) から読み取り、出力テクスチャの同じチャネルに書き込む GLSL シェーダがあります。このチャンネルはユーザーが選択する必要があります。

私が今考えることができるのは、int ユニフォームと大量の if ステートメントを使用することです。

uniform sampler2D uTexture;
uniform int uChannelId;
varying vec2 vUv;

void main() {

    //read in data from texture
    vec4 t = texture2D(uTexture, vUv);
    float data;
    if (uChannelId == 0) {
        data = t.r;
    } else if (uChannelId == 1) {
        data = t.g;
    } else if (uChannelId == 2) {
        data = t.b;
    } else {
        data = t.a;
    }

    //process the data...
    float result = data * 2;  //for example

    //write out
    if (uChannelId == 0) {
        gl_FragColor = vec4(result, t.g, t.b, t.a);
    } else if (uChannelId == 1) {
        gl_FragColor = vec4(t.r, result, t.b, t.a);
    } else if (uChannelId == 2) {
        gl_FragColor = vec4(t.r, t.g, result, t.a);
    } else {
        gl_FragColor = vec4(t.r, t.g, t.b, result);
    }

}

などの辞書アクセスのようなことを行う方法はありますt[uChannelId]か?

それとも、すべての if ステートメントを回避できるように、同じシェーダーの 4 つの異なるバージョンが必要で、それぞれが異なるチャネルを処理する必要がありますか?

これを行う最善の方法は何ですか?

EDIT:より具体的には、WebGL(Three.js)を使用しています

4

2 に答える 2

5

そういう方法もあるし、実際に質問に書いてある通り簡単です。を使用するだけt[channelId]です。GLSL 仕様を引用するには(これはバージョン 3.30、セクション 5.5 のものですが、他のバージョンにも適用されます):

配列添字構文をベクトルに適用して、数値インデックスを提供することもできます。だから

vec4 pos;

pos[2]pos の 3 番目の要素を参照し、pos.z と同等です。これにより、ベクトルへの変数のインデックス付けと、コンポーネントにアクセスする一般的な方法が可能になります。任意の整数式を添字として使用できます。最初のコンポーネントはインデックス 0 にあります。負の値またはベクトルのサイズ以上の値を持つ定数整数式を使用して、ベクトルからの読み取りまたはベクトルへの書き込みは不正です。非定数式でインデックス付けする場合、インデックスが負の場合、またはベクトルのサイズ以上の場合、動作は未定義です。

コードの最初の部分では、これを使用してテクスチャの特定のチャネルにアクセスすることに注意してください。ARB_texture_swizzle機能を使用することもできます。その場合、たとえばr、シェーダーでアクセスするために固定チャネルを使用し、実際のテクスチャ チャネルをスウィズルして、アクセスしたいチャネルが になるようにしますr

更新: ターゲット プラットフォームが webgl であることが判明したため、これらの提案は利用できません。ただし、単純な解決策は、選択したコンポーネントに 1.0 を、その他すべてに 0.0 をvec4代わりに使用することです。uChannelIDこの変数が と呼ばれているとしuChannelSelます。data=dot(t, uChannelSel)最初の部分と2 番目の部分で使用できますgl_FragColor=(vec4(1.0)-uChannelSel) * t + uChannelSel*result

于 2013-09-19T20:27:45.960 に答える
1

ご存じのとおり、分岐はシェーダーではコストがかかる可能性があります。ただし、パスでは常に同じチャネルになるように思われるので (はい?)、良好なパフォーマンスを確認するのに十分な結束を維持することができます。

GLSL を使用してからかなり時間が経ちましたが、新しいバージョンを使用している場合は、ビット単位のシフト (<< または >>) マジックを実行できますか? テクスチャを vec4 ではなく int に読み込み、読みたいチャンネルに応じてビット数シフトします。

于 2013-09-19T20:29:47.617 に答える