CAVE Programming


6. シェーディング

描画モデルに対する陰影付けを行うシェーディングの方法について学習します。
シェーディングの処理を行うことで、物体の色や濃淡、質感を表現することができ、リアリティの高い映像表現を行うことが可能になります。ここでは、シェーディングの原理と設定方法について学びます。


6.1 シェーディングの原理

シェーディングとは、物体の表面で反射して視点に届く光の強度を計算することで、物体表面の陰影や質感を表現する手法です。物体表面における光の反射は、拡散反射、鏡面反射、環境光反射の3つの成分で表すことができ、これらの計算結果を重畳することで物体表面の輝度を決定します。
・拡散反射(diffuse):拡散反射とは光沢の無い物体表面で起こる反射で、すべての方向に一様に散乱する成分です。
・鏡面反射(specular):鏡面反射は鏡の面の反射のように、法線に対して入射光の反対方向に強く反射する成分です。
・環境光反射(ambient):環境光反射とは光源からの直接光の他に2次反射、3次反射により全ての方向から照らされる光の成分です。


        図6.1:光の反射の成分

シェーディングの処理を有効にするには以下の関数が使われます。

・glEnable(GL_LIGHT0);
光源を有効にします。初期状態の光源はz軸のマイナス方向を照らす白色の平行光源です。

・void glNormal3f(GLfloat nx , GLfloat ny , GLfloat nz);
ポリゴンの頂点に対して法線ベクトルを設定します。nx, ny, nz は長さ1の単位ベクトルとします。
シェーディングを行う場合は、glColor3f() による色の指定の代わりに glNormal3f() による法線ベクトルの指定を行います。

・glEnable(GL_LIGHTING);
シェーディング処理を有効にします。

・glDisable(GL_LIGHTING);
シェーディング処理を無効にします。


 
6.2 材質の設定

シェーディングにおける光の反射特性は、物体の材質によって決められ、これにより物体の色や質感が表現されます。材質の設定には、以下の関数が使われます。

・void glMaterialfv(GLenum face, GLenum pname, const GLfloat *params);
材質パラメータの設定を行います。最初の引数 face は GL_FRONT、GL_BACK、GL_FRONT_AND_BACK によってそれぞれ面の表、裏、両面の指定を行います。次の引数 pname は、GL_DIFFUSE、GL_SPECULAR、GL_AMBIENT等によって、拡散反射係数、鏡面反射係数、環境光反射係数の指定を行い、最後の引数 params は各パラメータの値をRGBAの強度 0.0〜1.0 で設定します。
物体に対する材質パラメータを設定することで物体に色が付けられます。拡散反射係数は主に物体の色、鏡面反射係数はハイライトの強さ、環境光反射係数は光の当たらない部分の明るさに相当します。

以下は、sample2のプログラム内で使われている材料パラメータの設定方法を示したものです。ここでは、床面を青色、テーブルを茶色、ティーポットを緑色で表現しています。

  GLfloat matDiff1[] = { 0.0, 0.0, 0.3, 1.0 };
  GLfloat matSpec1[] = { 0.0, 0.0, 0.2, 1.0 };
  GLfloat matAmbi1[] = { 0.0, 0.0, 0.0, 1.0 };
  GLfloat matDiff2[] = { 0.6, 0.3, 0.0, 1.0 };
  GLfloat matSpec2[] = { 0.0, 0.0, 0.0, 1.0 };
  GLfloat matAmbi2[] = { 0.0, 0.0, 0.0, 1.0 };
  GLfloat matDiff3[] = { 0.0, 1.0, 0.0, 1.0 };
  GLfloat matSpec3[] = { 0.0, 0.0, 0.0, 1.0 };
  GLfloat matAmbi3[] = { 0.0, 0.0, 0.0, 1.0 };

  /* floor */
  glMaterialfv(GL_FRONT, GL_DIFFUSE, matDiff1);
  glMaterialfv(GL_FRONT, GL_SPECULAR, matSpec1);
  glMaterialfv(GL_FRONT, GL_AMBIENT, matAmbi1);
  glBegin(GL_POLYGON);
  ..........
  glEnd();

  /* table */
  ..........
  glMaterialfv(GL_FRONT, GL_DIFFUSE, matDiff2);
  glMaterialfv(GL_FRONT, GL_SPECULAR, matSpec2);
  glMaterialfv(GL_FRONT, GL_AMBIENT, matAmbi2);
  ..........
  Cylinder(0.02, 0.30, 30);

  /* teapot */
  ..........
  glMaterialfv(GL_FRONT, GL_DIFFUSE, matDiff3);
  glMaterialfv(GL_FRONT, GL_SPECULAR, matSpec3);
  glMaterialfv(GL_FRONT, GL_AMBIENT, matAmbi3);
  ..........
  glutSolidTeapot(0.2);


6.3 光源の設定

光の反射特性を表現するためには、材質の次に光源の属性を設定する必要があります。光源の設定には、以下の関数で使われます。初期状態では白色光が設定されていますが、光に色を与えることで物体の見かけの色を変えることもできます。

・void glLightfv(GLenum light, GLenum pname, const GLfloat *params);
光源のパラメータを設定します。引数 light は光源番号(GL_LIGHT0〜GL_LIGHTn)、引数 pname はパラメータの種類で、GL_POSITIONは光源の位置、GL_DIFFUSEは拡散反射成分の色、GL_SPECULARは鏡面反射成分の色、GL_AMBIENTは環境光成分の色をそれぞれ設定します。引数 params はパラメータの設定値を表します。

  void myinit(void)
  {
  GLfloat lightPos[] = { 0.0, 2.0, 2.0, 1.0 };
  GLfloat lightDiff[] = { 1.0, 1.0, 1.0, 1.0 };
  GLfloat lightSpec[] = { 1.0, 1.0, 1.0, 1.0 };
  GLfloat lightAmb[] = { 0.0, 0.0, 0.0, 1.0 };

  glLightfv(GL_LIGHT0, GL_POSITION, lightPosi);
  glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiff);
  glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpec);
  glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbi);

  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glEnable(GL_DEPTH_TEST);
  }


 
6.4 スムーズシェーディング

基本的なフラットシェーディングでは、ポリゴン内部は同じ色に塗られるためポリゴンの境界がはっきりと分かってしまいます。そこで、陰影を平滑化して見た目をなめらかな曲面に見せる方法がスムーズシェーディングです。OpenGLでは特に、グーローシェーディングと呼ばれるスムーズシェーディングの方法が用いられています。
この方法は、頂点の法線ベクトルをそれを共有するる隣接した多角形の法線ベクトルの平均値として求め、更に多角形内部の各点の色を各頂点の色から線形補間によって決めています。


   図6.1:グーローシェーディング

シェーディングは以下の関数で実行されます。

・void glShadeModel(GLenum mode);
シェーディングの方法を設定します。mode は、GL_FLAT が頂点の色をポリゴン全体に適用するフラットシェーディング、GL_SMOOTH はポリゴンの各頂点の色を距離比に従って混合するスムーズシェーディングの設定を行います。


※練習:

光源や材質の設定における拡散反射、鏡面反射、環境光反射等の各パラメータの値を変えてプログラムを実行し、見かけの色がどのように変化するか試してみましょう。