これは、2つまたは3つのテクスチャコンバイナを使用して可能です。ほとんどの場合、2つのテクスチャコンバイナのみをサポートする古いデバイス(iPhone 3Gなど)をサポートしようとしています。次のコードを使用して、デバイスがサポートするテクスチャコンバイナの数を決定できます。
int maxTextureUnits;
glGetIntegerv(GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
シェーダーなしでグレースケールテクスチャをレンダリングするための基本的な手順は次のとおりです。
- すべてのピクセルRGB値を2で割ります
- すべてのピクセルRGB値から.5を引きます
- カスタム加重値を使用して、各RGB値のGL_DOT3_RGB値を計算します
これで、これらの各ステップをTextureCombinerで実行できます。または、手順1を、テクスチャを読み込むときにピクセル値を調整するカスタムコードに置き換えることで、2つのテクスチャコンバイナのみを使用することもできます。調整したテクスチャをカラーでレンダリングできるテクスチャコンバイナを2つだけ使用する場合は、レンダリングする前にRGB値を2倍にする単一のテクスチャコンバイナが必要です。
すべてのピクセル値に.5を追加する理由は、輝度の計算に使用しているGL_DOT3_RGBの式が、各ピクセル値から.5を減算するためです。
すべてのピクセル値を2で割る理由は、ステップ2からステップ3に移動するときに値がクランプされないようにするためです。RGB値が(.5、.6、.7)で、.5をに追加した場合各RGB値、ステップ3に入る結果のRGB値は(1.0、1.0、1.0)になります。DOT3の式は、各値から.5を引いた後、(。5、.5、.5)に基づいて輝度を計算します。
3つのテクスチャユニットを使用してテクスチャグレースケールをレンダリングするサンプルコードを次に示します。
//Enable texture unit 0 to divide RGB values in our texture by 2
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_textureId);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glClientActiveTexture(GL_TEXTURE0);
//GL_MODULATE is Arg0 * Arg1
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
//Configure Arg0
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
//Configure Arg1
float multipliers[4] = {.5, .5, .5, 0.0};
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (GLfloat*)&multipliers);
//Remember to set your texture coordinates if you need them
//glEnableClientState(GL_TEXTURE_COORD_ARRAY);
//glTexCoordPointer...
//Enable texture unit 1 to increase RGB values by .5
glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_textureId);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glClientActiveTexture(GL_TEXTURE1);
//GL_ADD is Arg0 + Arg1
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD);
//Configure Arg0
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
//Configure Arg1
GLfloat additions[4] = {.5, .5, .5, 0.0};
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (GLfloat*)&additions);
//Set your texture coordinates if you need them
//glEnableClientState(GL_TEXTURE_COORD_ARRAY);
//glTexCoordPointer...
//Enable texture combiner 2 to get a DOT3_RGB product of your RGB values
glActiveTexture(GL_TEXTURE2);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_textureId);
glClientActiveTexture(GL_TEXTURE2);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
//GL_DOT3_RGB is 4*((Arg0r - 0.5) * (Arg1r - 0.5) + (Arg0g - 0.5) * (Arg1g - 0.5) + (Arg0b - 0.5) * (Arg1b - 0.5))
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB);
//Configure Arg0
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
//Configure Arg1
//We want this to adjust our DOT3 by R*0.3 + G*0.59 + B*0.11
//So, our actual adjustment will need to take into consideration
//the fact that OpenGL will subtract .5 from our Arg1
//and we need to also take into consideration that we have divided
//our RGB values by 2 and we are multiplying the entire
//DOT3 product by 4
//So, for Red adjustment you will get :
// .65 = (4*(0.3))/2 + 0.5 = (0.3/2) + 0.5
GLfloat weights[4] = {.65, .795, .555, 1.};
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (GLfloat*)&weights);
//Set your texture coordinates if you need them
//glEnableClientState(GL_TEXTURE_COORD_ARRAY);
//glTexCoordPointer...
//Render your objects or sprite
//Clean up by disabling your texture combiners or texture units.
glActiveTexture(GL_TEXTURE2);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE1);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glClientActiveTexture(GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);