1

カラーテクスチャをグレーでレンダリングしたいのですが。シェーダーを使用してES2.0でそれを行うのは簡単ですが、ES 1.xで行うことは可能ですか?

アップデート

@datenwolfのおかげで、私はそのようにやっています:

GLfloat weights_vector[4] = {0.2126, 0.7152, 0.0722, 1.0};
GLfloat additions_vector[4] = {0.5, 0.5, 0.5, 0.0};

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);

/* First part */
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, weights_vector);

/* Second part */
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, additions_vector);

最初の部分はそのままにしておくとうまくレンダリングされますが、2番目の部分を追加すると、前の色として「黒」が使用されるため、灰色のピクセルしか得られません。私はここでそれを間違っていますか?

2回目の更新

GL_TEXTURE0代わりに使用しようとするとGL_PREVIOUS、実際にと同じ結果が得られGL_TEXTUREます。ただし、使用した場合、GL_TEXTURE1灰色のピクセルではなく、黒になります。ここで迷子になっています...

3番目の更新

2番目の部分は現在機能しています。@datenwolfが提案したように、前のテクスチャの名前を使用する必要があります。

ただし、出力が反転されたため、出力はまだ正しくありませんでした。私はそれを追加することで修正しました:

glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_ONE_MINUS_SRC_COLOR);

今、それは暗すぎます。そして、私はそれを正しく理解することができません。試したが機能しなかった:

  • 重みを2倍する
  • 0.5を追加
  • 画像全体を2で変調する
  • 重みに2を掛けてから、0.5を引く

4回目の更新(申し訳ありませんがたくさんあります)

のバイアスと乗算のために、それは不可能だと私は思い始めますDOT3_RGB。コンバイナでそれを行う正しい方法は次のとおりです。

  1. 入力テクスチャに0.5を追加します
  2. 重み係数に計算します。weight_new=(weight_real + 2.0)/(4.0);
  3. 行うGL_DOT3_RGB

たとえば、次を使用する代わりに:

GLfloat weights_vector[4] = {0.30, 0.59, 0.11, 0.0};

使用する:

GLfloat weights_vector[4] = {0.575, 0.6475, 0.5275, 0.0};

これは確かにほぼ正しい結果を得ていますが、最初のステップと数値が[-1.0、1.0]の範囲に固定されているため、コントラストの一部が失われています。

なぜ計算するのですか?さて、APIによると:

ドット計算

ですから、精度の制限のために、私が示したものと他の方法は見当たりません。もちろん、最初に入力を2.0で除算し、次に0.5を加算し、dot3を実行し、次に2を乗算することで、すべての値を[-1.0、0.0]の範囲に効果的に含めることができます。でも、分割のせいでまだ精度が落ちてしまうのではないかと思います。

DOTはこの目的を意図したものではなく、バンプマッピングなどを目的としたものである可能性が高いと思います。残念な。私が間違っているといいのですが、どうすればいいのかわかりません。

4

3 に答える 3

5

これには、ドット(スカラー)製品テクスチャ環境を使用できます。ベクトルの内積は次のとおりです。

dot(v1, v2) = v1[0]*v2[0] + v1[1]*v2[1] + ... + v1[n]*v2[n]

彩度の低下は、チャネルをそれぞれの重み係数で合計することによって実現されます。

L{r,g,b} = w_r * R + w_g * G + w_b * B

しかし、これは重みベクトルを使用した色の内積に他なりません。OpenGL-1.5には、コンバイナーと呼ばれるテクスチャ環境があり、このコンバイナー環境には、ドット積モードがあります。

GLfloat weighting_vector[4];
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, weighting_vector);

コメントによる編集

アルファコンバイナー、トークンGL_COMBINE_ALPHAでアルファチャネルの操作を指定できます。あなたの場合、あなたは単にソースアルファを使いたいだけです。これらの構成の追加:

glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE);

私が忘れていたのは、内積モードでは0.5バイアスが導入されるということでした。ただし、これは問題ありません。少なくとも3つのコンバイナステージが提供されているため、GL_SUBSTRACTステージで各チャネルの0.5を減算し、これを補うために重み付けに2.0を掛けて終了します。

glTexEnvマンページhttp://www.opengl.org/sdk/docs/man/xhtml/glTexEnv.xmlと元の拡張仕様http://www.opengl.org/registry/specs/ARB/texture_env_combineをご覧ください。 txt(これが拡張機能だったときの)。テクスチャコンバイナを初めて使用する場合は、少し気が狂うことを認めます。歴史的に、それらはフラグメントシェーダーの前身です。NVidiaは、後に「レジスターコンバイナー」と呼ばれるものからすべてを開始しました。これは後にテクスチャコンバイナーになりました。

質問への補遺によるEDIT2

独自のコンバイナーステージ(=テクスチャユニット)で2番目の部分を実行する必要があります。テクスチャユニットは。で切り替えglActiveTextureます。次のようにコードを変更します。

GLfloat weights_vector[4] = {0.2126, 0.7152, 0.0722, 1.0};
GLfloat additions_vector[4] = {0.5, 0.5, 0.5, 0.0};

glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texID);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);

/* First part */
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, weights_vector);

glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texID); // we need some dummy texture active
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);

/* Second part */
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_SUBTRACT);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, additions_vector);

また、0.5を加算するのではなく、0.5のバイアスを補正するために、減算するつもりだと思います。FTFY。

于 2011-08-03T12:06:14.683 に答える
5

これは、2つまたは3つのテクスチャコンバイナを使用して可能です。ほとんどの場合、2つのテクスチャコンバイナのみをサポートする古いデバイス(iPhone 3Gなど)をサポートしようとしています。次のコードを使用して、デバイスがサポートするテクスチャコンバイナの数を決定できます。

int maxTextureUnits;
glGetIntegerv(GL_MAX_TEXTURE_UNITS, &maxTextureUnits);

シェーダーなしでグレースケールテクスチャをレンダリングするための基本的な手順は次のとおりです。

  1. すべてのピクセルRGB値を2で割ります
  2. すべてのピクセルRGB値から.5を引きます
  3. カスタム加重値を使用して、各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);
于 2012-03-13T18:47:13.033 に答える
1

テクスチャをOpenGLにアップロードする前に、ColorMatrixを使用してテクスチャの彩度を下げます

Paint paint = new Paint();
ColorMatrix matrix = new ColorMatrix();
matrix.setSaturation(0);
paint.setColorFilter(new ColorMatrixColorFilter(matrix));

Bitmap bmp = Bitmap.createBitmap(resource.getWidth(), resource.getHeight(), resource.getConfig());
Canvas canvas = new Canvas(bmp);
canvas.drawBitmap(resource, null, paint);
于 2011-08-03T10:55:17.503 に答える