5

マルチテクスチャリングを使用してオブジェクトをレンダリングする必要がありますが、同じオブジェクトに対して両方のテクスチャの UV 座標が異なります。1 つはノーマル マップで、もう 1 つはライト マップです。

これに関する有用な資料を提供してください。

4

1 に答える 1

6

とにかく、OpenGL ES 2 ではシェーダーを使用します。そのため、好きなテクスチャ座標を自由に使用できます。通常どおり、2 番目のテクスチャ座標ペアに追加の属性を導入し、これをフラグメント シェーダーに委譲するだけです。

...
attribute vec2 texCoord0;
attribute vec2 texCoord1;

varying vec2 vTexCoord0;
varying vec2 vTexCoord1;

void main()
{
    ...
    vTexCoord0 = texCoord0;
    vTexCoord1 = texCoord1;
}

フラグメント シェーダーでは、それぞれの座標を使用してテクスチャにアクセスします。

...
uniform sampler2D tex0;
uniform sampler2D tex1;
...
varying vec2 vTexCoord0;
varying vec2 vTexCoord1;

void main()
{
    ... = texture2D(tex0, vTexCoord0);
    ... = texture2D(tex1, vTexCoord1);
}

もちろん、この新しい属性にデータを提供する必要があります ( を使用glVertexAttribPointer)。しかし、これらすべてが非常に異質に聞こえる場合は、GLSL シェーダーをもう少し詳しく調べるか、実際に OpenGL ES 1 を使用する必要があります。この場合、質問にタグを付け直してください。回答を更新します。

編集: OpenGL ES 1 の更新によると、状況は少し異なります。単一のテクスチャを使用し、これにテクスチャ座標を指定する方法を既に知っていると仮定します。

これによりglActiveTexture(GL_TEXTUREi)、i 番目のテクスチャ ユニットをアクティブにすることができます。テクスチャ状態に関連する以下のすべての操作は、i 番目のテクスチャ ユニットのみを参照します ( と同様ですが、およびglBindTextureも同様です)。glTexEnvgl(En/Dis)able(GL_TEXTURE_2D)

テクスチャ座標を指定するにはglTexCoordPointer、単一のテクスチャリングと同様に関数を使用しますが、次の呼び出しと参照glCientActiveTexture(GL_TEXTUREi)を行うテクスチャ ユニットを選択できます。glTexCoordPointerglEnableClientAttrib(GL_TEXTURE_COORD_ARRAY)

したがって、次のようになります。

//bind and enable textures
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, <second texture>);
glTexEnv(<texture environment for second texture>);   //maybe, if needed
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, <first texture>);
glTexEnv(<texture environment for first texture>);   //maybe, if needed
glEnable(GL_TEXTURE_2D);

//set texture coordinates
glClientActiveTexture(GL_TEXTURE1);
glTexCoordPointer(<texCoords for second texture>);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0);
glTexCoordPointer(<texCoords for first texture>);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

//other arrays, like glVertexPointer, ...

glDrawArrays(...)/glDrawElements(...);

//disable arrays
glClientActiveTexture(GL_TEXTURE1);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

//disable textures
glActiveTexture(GL_TEXTURE1);
glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glDisable(GL_TEXTURE_2D);

最初のテクスチャの前に 2 番目のテクスチャのパラメータを設定した理由は、設定後にテクスチャ ユニット 0 がアクティブになるためです。ユニット 0 以外の別のユニットがアクティブであるときに、ドライバーが描画時に問題を起こすのを既に見たことがあると思います。そして、最後に多かれ少なかれきれいな状態を残すことは常に良い考えです。これは、デフォルトのテクスチャ ユニット ( GL_TEXTURE0) がアクティブであることを意味します。

編集:頂点配列の代わりに即時モード ( glBegin/glEnd) を使用する場合は、もちろん使用しませんglTexCoordPointer。この場合glClientAttribTexture、もちろん も必要ありません。glMultiTexCoord(GL_TEXTUREi, ...)の代わりに適切なテクスチャ ユニット ( GL_TEXTURE0GL_TEXTURE1、...)を使用する必要がありglTexCoord(...)ます。しかし、私の知る限り、OpenGL ES には即時モードはありません。

于 2011-10-13T13:29:18.463 に答える