トップ
ソフトウェア
陶芸
陶芸
OpenGL
大戦略1208攻略
リンク
7 ポリゴンの深さ(デプス。重なりの計算)
OpenGLでは、ポリゴンの深さ(デプス)設定を有効にすることで、自動的にポリゴンを描く順番を決定し、遠いものほど隠れるようになる(実際は、重なる部分はポリゴンを分解し、遠くにあるものは描画しないようにしている)。深さ設定を無効にすると、コマンドを実行した順で描画する。
ポリゴンの深さ(重なり)
深さ計算で基準になるのは、常に視点からの距離である。あたりまえのことではあるが、決してzの値に依存するわけではない。サンプルの多くは視線の遠近方向とz軸が重なる、もしくはほぼ一緒になるため、z軸の値で遠近を変化させているだけである。
サンプルコード
以下のコードを追記する。分かりやすくするため、透視法射影で描画している。三つの三角形は同じ大きさだが、視点からの距離が異なり、遠いものほど小さく描画される。ここでは遠いほうから赤、青、緑となっている。描画の順番は逆に緑、青、赤としている。深さ設定の流れは後で述べる。
初期設定部

Protected Overrides Sub InitGLContext()
  GL.glClearColor(1.0, 1.0, 0, 1.0) '背景色

  'カメラの設定 **********
  GL.glMatrixMode(Convert.ToUInt32(GLFlags.GL_PROJECTION)) 'カメラ用行列を指定

  GL.glLoadIdentity() '行列を初期化
  GL.glFrustum(-1, 1, -1, 1, 0.5, 1.5)
  GL.gluLookAt(0, 0, 1, 0, 0, 0, 0, 1, 0) 'eye 0,0,1 center 0,0,0 up 0,1,0

  GL.glMatrixMode(Convert.ToUInt32(GLFlags.GL_MODELVIEW)) '物体用行列を指定 

  '深さ設定 **********
  'GL.glEnable(Convert.ToUInt32(GLFlags.GL_DEPTH_TEST))


End Sub
描画部分
Public Overrides Sub glDraw()
  GL.glClear(Convert.ToUInt32(GLFlags.GL_COLOR_BUFFER_BIT))'
  GL.glClear(Convert.ToUInt32(GLFlags.GL_DEPTH_BUFFER_BIT))
  
   '手前
  GL.glBegin(Convert.ToUInt32(GLFlags.GL_TRIANGLES))
  GL.glColor3d(0, 1.0, 0)
  GL.glVertex3f(-0.2, 0.5, 0.3)
  GL.glVertex3f(-0.6, 0, 0.3)
  GL.glVertex3f(0.2, 0, 0.3)
  GL.glEnd()

  '中
  GL.glBegin(Convert.ToUInt32(GLFlags.GL_TRIANGLES))
  GL.glColor3d(0, 0, 1.0)
  GL.glVertex3f(0.0, 0.5, 0)
  GL.glVertex3f(-0.4, 0, 0)
  GL.glVertex3f(0.4, 0, 0)
  GL.glEnd()

  '奥
  GL.glBegin(Convert.ToUInt32(GLFlags.GL_TRIANGLES))
  GL.glColor3d(1.0, 0, 0)
  GL.glVertex3f(0.2, 0.5, -0.1)
  GL.glVertex3f(-0.2, 0, -0.1)
  GL.glVertex3f(0.6, 0, -0.1)
  GL.glEnd()
  GL.glFlush()

End Sub
実行すると、上から赤青緑の順で三角形が表示される。
続いて、「深さ設定」に続くコマンドの「’」をはずし、有効にして実行してみる。すると、緑の三角形が上に表示されるはずである。
見たとおり、
このサンプルコードは、すでに使っているコマンドだけで構成されているが、指定する定数が異なっている
GL.glEnable(Convert.ToUInt32(GLFlags.GL_DEPTH_TEST))
 ※GL.glDisable(Convert.ToUInt32(GLFlags.GL_DEPTH_TEST))
深さ設定を有効/無効にする。有効の場合、条件にもよるが処理速度が結構遅くなる。
 
GL.glClear(Convert.ToUInt32(GLFlags.GL_DEPTH_BUFFER_BIT))
深さバッファをクリアする。バッファクリアのタイミングが描画の途中にあると、重なり順が狂ってしまうので(クリア前後で逆転する)、必ず描画全体の最初でクリアすること。また、描画ルーチンを呼び出すたびにクリアしないとやはり描画がおかしくなる(表示されなくなる)。
なお、ここでは分かりやすくするために「COLOR_BUFFER」と別で記述しているが、他HPのサンプルのように
GL.glClear(Convert.ToUInt32(GLFlags.GL_COLOR_BUFFER_BIT Or GLFlags.GL_DEPTH_BUFFER_BIT))
二つの定数をOr演算して実行しても問題ない。
ただし、他のコマンドでも同様にうまくいくわけではないので(EnableでCullとDEPTHを同時に有効にはできない)、注意が必要である
深さ無効 深さ有効
失敗例
なお、深さ設定はEnableとDisableの間の描画のみが適用されるので、高速化のために部分的に深さ設定を適用することもできなくはないが、以下のコードのように、有効に無効がはさまれるとおかしな画像になる(上の失敗例)ので、できれば
初期設定で有効に設定 → 描画ルーチン呼び出しの先頭でバッファクリア
とすることが望ましい。以下に失敗例のサンプルコードを記す。
描画部分(上のコードに追加)
   '手前
  'GL.glEnable(Convert.ToUInt32(GLFlags.GL_DEPTH_TEST))
  ...
  '中

  'GL.glDisable(Convert.ToUInt32(GLFlags.GL_DEPTH_TEST))
  ...
  '奥

  'GL.glEnable(Convert.ToUInt32(GLFlags.GL_DEPTH_TEST))
  ...
実行すると、失敗例のように、赤の三角がおかしくなってしまう。このコードの流れを追ってみると
バッファクリア → 有効 → 緑描画 → 無効 → 青描画 → 有効 → 赤描画
という感じである。つまり、緑と赤は有効、青は無効である。このとき
1. 緑よりも遠くの青は無効なので、緑より上に描画される。
2. 赤よりも近くの青は無効なので、赤より下に描画される。この時点で 上から赤、青、緑になる。
3. 緑と赤は有効なので、緑が上に描画される。2.の順番に矛盾する。
つまり、この3つはまともに描画されないことが分かる。実際の結果では、描画順は上から赤、青、緑で2.の時点での順番が適用されているが、赤の形は緑と重なった部分が削除されている。このことから推測すると
1. 有効なポリゴンの重なりを計算し、重なり部分は一番近いポリゴンのみ残し、他のポリゴンは重なり部分を削除した形のポリゴンに変換。
2. 全てのポリゴンを描画順にそのまま描画。
という処理がなされていると思われる(あくまで推測)。どちらにせよ、できるだけ有効と無効は混在させない。もし有効、無効を混在させる場合は有効にするのは、1回の描画で1回だけ(2回以上だと、有効にはさまれる無効がでることになる)にすべきであろう。
参考までに、失敗サンプルの有効、無効を入れ替えて描画した場合、「深さ無効」画像と同じ結果になる。
前へ
  
Copyright Lichu since 2008 all rights reserved