2

地形を着色するためにデータ配列をフラグメント シェーダーに渡す方法について以前にこの質問をしたところ、テクスチャの RGBA 値を使用できることが示唆されました。

私は今、yzw値をどのように使用するかを考え出そうとしています。これは私のフラグメントシェーダーコードです:

vec4 data = texture2D(texture, vec2(verpos.x / 32.0, verpos.z / 32.0));
float blockID = data.x;
vec4 color;

if (blockID == 1.0) {
    color = vec4(0.28, 0.52, 0.05, 1.0);
}
else if (blockID == 2.0) {
    color = vec4(0.25, 0.46, 0.05, 1.0);
}
else if (blockID == 3.0) {
    color = vec4(0.27, 0.49, 0.05, 1.0);
}

gl_FragColor = color;

これは問題なく動作しますが、ご覧のとおり、x-coordinate の float のみを使用しています。座標も使用している場合yzw、テクスチャ サイズは 32x32 ではなく 16x16 (4 分の 1) に縮小できます。

これの目的は、各「ブロック」が空間座標で 1x1 であり、blockID に基づいて色付けされる、ボクセル タイプの地形を作成することです。次のようになります。 ここに画像の説明を入力

GLSL 以外ではこれは簡単ですが、どのブロックが計算されたかを保存する機能がないため、これは難しいと感じています。間違いなく、私は物事を考えすぎており、簡単な数学で行うことができます.


編集:
ワグナー・パトリオタの答えに基づくコード:

vec2 pixel_of_target = vec2( verpos.xz * 32.0 - 0.5 ); // Assuming verpos.xz == uv_of_target ?

// For some reason mod() doesn't support integers so I have to convert it using int()
int X = int(mod(pixel_of_target.y, 2.0) * 2.0 + mod(pixel_of_target.x, 2.0));

// Gives the error "Index expression must be constant"
float blockID = data[ X ];

エラーについては、以前にそれについて質問したことが、実際にこれを質問することにつながりました。:P
何かアイデアはありますか? ありがとう!:)

4

1 に答える 1

2

アイデアは次のものを置き換えることです:

float blockID = data.x;

float blockID = data[ X ];

は、 16x16Xデータ イメージから R、G、B、または A を選択できる整数です。

X問題は、UV の関数で計算する方法です。

わかりました。ターゲット イメージ (32x32) とデータ イメージ (16x16) があります。それでは、やってみましょう:

ivec pixel_of_target = ivec( uv_of_target * 32.0 - vec2( 0.5 ) ); // a trick!

UV にテクスチャの寸法 (この場合は 32) を掛けると、正確なピクセルがわかります。「テクスチャからピクセルを見つけようとしている」ため、-0.5 が必要です。そしてもちろん、テクスチャには「ピクセルの中心」の間で補間された値があります。ピクセルの正確な中心が必要です...

あなたpixel_of_targetivec(整数) であり、描画している場所を正確に特定できます! そこで、16x16 テクスチャからどのチャネルを取得する必要があるかを (描画しているピクセルに基づいて) 特定する必要があります。

int X = ( pixel_of_target.y % 2 ) * 2 + pixel_of_target.x % 2;
float blockID = data[ X ]; // party on!

上記の式を使用するとX、ターゲット ピクセルに基づいて正しいインデックスを取得できます。「データ テクスチャ」 16x16 で、(R、G、B、A) をターゲットの 4 ピクセルのすべてのグループの (左上、右上、左下、右下) にマップします (または逆さまにすることもできます)。必要に応じて...あなたはそれを理解することができます)

アップデート:

WebGL を使用しているため、いくつかの詳細を変更する必要があります。私はこれをしました、そしてそれはうまくいきました。

vec2 pixel_of_target = vTextureCoord * 32.0 + vec2( 0.5 ); // the signal changed!
int _x = int( pixel_of_target.x );
int _y = int( pixel_of_target.y );
int X = mod( _y, 2 ) * 2 + mod( _x, 2 );

私はこれをテストに使用しました:

if ( X == 0 )
    gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );
else if ( X == 1 )
    gl_FragColor = vec4( 0.0, 1.0, 0.0, 1.0 );
else if ( X == 2 )
    gl_FragColor = vec4( 0.0, 0.0, 1.0, 1.0 );
else if ( X == 3 )
    gl_FragColor = vec4( 1.0, 0.0, 1.0, 1.0 );

私の画像は完全にうまくいきました:

ズーム

ここでは、Photoshop でズームして、ピクセルの詳細を確認します。

PS1: 私は WebGL に詳しくないので、Chrome で WebGL を実行できませんでした。Firefox で試しましたが、mod() 関数も見つかりませんでした。

int mod( int a, int b )
{
    return a - int( floor( float( a ) / float( b ) ) * float( b ) );
}

PS2: vec2( 0.5 ) を減算する代わりに合計しなければならなかった理由がわかりません。WebGL は少し異なります。おそらくこのシフトがあります。わかりません... ただうまくいきます。

于 2013-10-30T03:01:40.840 に答える