床井研究室

切り抜き

アルファ値には、画像の合成の他にも使い道があります。前回、Photshop Elements の選択範囲を保存してアルファチャンネルを持った画像(RGBA 形式の画像)を作成しましたが、選択範囲を使って画像を切り抜けるのと同様に、アルファ値を使ってポリゴンを切り抜くことができます。

その前に

雛形のプログラムは、前回のままではとんでもない色使いになってしまっているので、一旦元に戻します。まず、GL_TEXTURE_ENV_MODEGL_MODULATE に設定します。また、GL_MODULATE では GL_TEXTURE_ENV_COLOR で指定した色は参照されません。したがって次の変数 blend の宣言と、それを GL_TEXTURE_ENV_COLOR に設定している glTexEnvf() 関数を、#if 0 〜 #endif ではさんで1無効にしておきます。

/*
** 初期化
*/
static void init()
{
  ...

  /* テクスチャ環境 */
  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

#if 0
  /* 混合する色の設定 */
  static const GLfloat blend[] = { 0.0, 1.0, 0.0, 1.0 };
  glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, blend);
#endif
  
  ...
}

次に、下地のポリゴンの材質も、もとの白色に戻しておきましょう。

/*
** シーンの描画
*/
static void scene()
{
  static const GLfloat color[] = { 1.0f, 1.0f, 1.0f, 1.0f };  /* 材質 (色) */

  /* 材質の設定 */
  glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color);

アルファ値の比較関数

アルファテストは、画素のアルファ値をある値と比較し、その結果をもとにその画素を表示するか否かを決定します。アルファ値は 0〜1 の間の値を持ち、0 で透明、1 で不透明を表しますから、ここでは glAlphaFunc() を使って、アルファ値が 0.5 を超えていればその画素を表示し、超えていなければ非表示にすることにします。

/*
** 初期化
*/
static void init()
{
  ...

  /* テクスチャ環境 */
  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

#if 0
  /* 混合する色の設定 */
  static const GLfloat blend[] = { 0.0, 1.0, 0.0, 1.0 };
  glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, blend);
#endif

  /* アルファテストの比較関数 */
  glAlphaFunc(GL_GREATER, 0.5);
void glAlphaFunc(GLenum func, GLclampf ref)
アルファ値の比較関数を設定します。引数 func には比較関数を示す定数値、ref には比較の対象となる値(閾値)を 0〜1 の値で設定します。func に指定できる値には GL_NEVER, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_NOTEQUAL, GL_GREATER, EQUAL, GL_GREATER, および GL_ALWAYS があります。

これは 2004 年の記事です。OpenGL (3.1以降 Core Profile) および OpenGL ES 2.0/3.0 以降では、glAlphaFunc() 関数は廃止されています。

複雑な外形のポリゴンが描ける

そして、図形を描画する前に、アルファテストを有効にしておきます。

/*
** シーンの描画
*/
static void scene()
{
  static const GLfloat color[] = { 1.0f, 1.0f, 1.0f, 1.0f };  /* 材質 (色) */

  /* 材質の設定 */
  glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color);

  /* アルファテスト開始 */
  glEnable(GL_ALPHA_TEST);

  /* テクスチャマッピング開始 */
  glEnable(GL_TEXTURE_2D);

  /* 1枚の4角形を描く */
  glNormal3d(0.0, 0.0, 1.0);
  glBegin(GL_QUADS);
  glTexCoord2d(0.0, 1.0);
  glVertex3d(-1.0, -1.0,  0.0);
  glTexCoord2d(1.0, 1.0);
  glVertex3d( 1.0, -1.0,  0.0);
  glTexCoord2d(1.0, 0.0);
  glVertex3d( 1.0,  1.0,  0.0);
  glTexCoord2d(0.0, 0.0);
  glVertex3d(-1.0,  1.0,  0.0);
  glEnd();

  /* テクスチャマッピング終了 */
  glDisable(GL_TEXTURE_2D);

  /* アルファテスト終了 */
  glDisable(GL_ALPHA_TEST);
}

すると、こんな具合にポリゴンが抜けます。

アルファテスト

ということで、複数のポリゴンを組み合わせなくても、1枚のポリゴンで円盤を描くことができます。もちろん、円盤に限らず複雑な形状を描くことができるので、ポリゴン数を減らしたいゲームなどでは多用されています。ただし、これにはテクスチャマッピングやアルファテストが十分高速なハードウェアを使用するという条件が付きますが。

  1. こういう方法は良くないと言われます。ちゃんとコメントにしましょう。