OpenGL での光源と質感 (ライティングとマテリアル) の設定

図形が表示されてもなかなか 3D っぽく見えないのですが、それがなぜかというとちゃんと光を当てたりして、影とか光沢(あるいはつや消し) 、 色みがないからです。

ここでは OpenGL におけるライト (光源) の設定とマテリアル (質感) の設定をします。

それによって前回の記事 「OpenGL で図形を回転させてみよう」 で描いたキューブをいよいよ、それっぽく (3D っぽく) 見えるようにしてみましょう。

細かい説明は後回しにして、まずはコードを書いて立体的なキューブがレンダリングされることをみてみましょう。

前回の記事の結果できあがったキューブは次のようなものでした。

OpenGL 物体の回転

これに対してライティングを有効化してみましょう。

ライティングを有効化するには、次のように gl.glEnable(GL10.GL_LIGHTING)とします。また、光源は GL_LIGHT0 から GL_LIGHT7 番までの 8 つの光源が有効化できますが、 ここでは GL_LIGHT0 を有効化しています。

  @Override
  public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    ...    
    gl.glEnable(GL10.GL_LIGHTING);
    gl.glEnable(GL10.GL_LIGHT0);
    ...

これだけで、次のようになりました。

OpenGL ライティングとマテリアル

確かに影がついていて、以前とはうって変わって立体的に見えますね。

ライティングはどうなっているのか?

これはいったいどういうことだったのか、ざっと説明しましょう。(詳しくは長くなりすぎるので、また別の機会にしたいと思います)

さて、ライティングを有効にした場合、光源としては次の値がデフォルトで設定されます。 環境光 (ambient) は (0,0,0,1)、 拡散光 (diffuse) は (1,1,1,1)、 鏡面光 (specular) は (1,1,1,1) です。 一方マテリアルの設定のデフォルトはそれぞれ順に (0.2, 0.2, 0.2, 1.0)、 (0.8, 0.8, 0.8, 1.0)、 (0, 0, 0, 1) です。

環境光はもともと 0、 鏡面光はマテリアルで 0 なので、どちらも効いてきません。 この状態では有効な設定は拡散光のみになります。

光源の位置はデフォルトで (0,0,1) で、 directional です。すなわち z 軸沿いに、太陽光のようにまっすぐ照らされているということです。

拡散光は物体の表面に当たって、全方向に反射します。見る位置によって明るさは変わらないのですが、光の方向と反射面の法線ベクトルによって計算され、 面にまっすぐ当たった方が明るくなります。このため、前面が明るく見えています。

・・・と、駆け足で書きましたが、、、ここで言いたいことは、 ライティングを有効にしたとき、特に何かの値を設定しなくとも、光源と物体の材質についてそれなりのデフォルトの設定がされているために、 上の図のようにみえた、ということです。

逆に言えば、たとえライティングを有効にしても、光源の設定と材質の設定によってはまったく影がみえなかったりして、 3D っぽく見えるとは限らないということです。 (例えば環境光だけでは、全体が同様に照らされるので影は出来ません)

そのため、ライティングについてはきめ細かく設定を行う必要があるのです。

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Android 開発入門