GLSLを使い環境マップ(キューブマップ)と反射・屈折効果を実装. キューブマップとフレネル効果(Fresnel reflection)について†環境マップ†鏡面反射表面上への写り込みや透過物体の表現はレンダリング結果のリアルさを向上させるのにとても重要である. しかし,これらの効果を正確にシミュレートする場合,レイトレーシングなどの時間のかかる方法が必要となる. そこで写り込みや屈折に影響するのは遠景だけであるとし, 環境に配置した遠景を表す画像を使ってこれらの効果を表現する. この方法は環境マップと呼ばれ,画像を球形状に貼り付けるスフィアマップ, 立方体形状に貼り付けるキューブマップの2つが一般的である. キューブマップに用いる画像の例を以下に示す. OpenGLにはキューブマップを取り扱うためのテクスチャタイプ GL_TEXTURE_CUBE_MAP があり,以下のように設定することでキューブマップ用のテクスチャ座標を自動生成することができる. glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); これらのテクスチャ座標は法線ベクトルに基づいて計算された反射ベクトルから生成される. 屈折の効果を入れたいので以下ではGLSLを使って反射,屈折ベクトルを計算, キューブマップテクスチャを参照することで反射・屈折効果を再現する方法を述べる. ただし,一次反射,屈折のみで複数回の反射などは考慮しない. 反射方向ベクトルの算出†GLSLによるフォンシェーディングで説明したように,反射ベクトルは以下のように求められる. ![]() 反射ベクトルを計算するシェーダコードを以下に示す.
また,GLSLには反射ベクトルを計算するビルトイン関数 reflect() があるのでこれを使って, vec3 R = reflect(I, N); としても良い. 透過屈折方向ベクトルの算出†スネルの法則(snell's law)より,入射角 ![]() の関係がある.
ここで 上の図において,入射ベクトル ![]() よって, ![]() ![]() ここで ![]() よって, ![]() また,スネルの法則より, ![]() この式の両辺に ![]()
![]() ここで, ![]()
屈折ベクトルを計算するシェーダコードを以下に示す.
ここで,引数eには屈折率比を指定する. また,GLSLには屈折ベクトルを計算するビルトイン関数 refract() があるのでこれを使って, vec3 T = refract(I, N, e); としても良い. フレネル効果†フレネル効果とは,透明な物体表面においてみる角度によって反射や屈折が起こる現象のことである.
入射光強度 視点に届く光に関して考えると,
表面上の点に反射方向から届く光の強度を ![]() 計算を簡単にするためとユーザによる制御を容易にするために (1)で提案されている近似式を用いる. ![]() ここでbiasは値が小さいと反射成分が弱くなりほとんど屈折し,1に近いとほぼ反射するようになる. 上記の反射・屈折ベクトルの算出方法とフレネル効果の近似式をGLSLで行うコードを以下に示す. まず,頂点シェーダは,
フラグメントシェーダにおける視点位置eyePositionがローカル座標で与えられることを想定して, vPosにはローカル座標の値をそのまま用いている. 頂点シェーダはGLSLによるフォンシェーディングのものとおなじである. 次にフラグメントシェーダを以下に示す.
OpenGL側から各パラメータと視点位置, GL_TEXTURE_CUBE_MAPとして生成したキューブマップテクスチャを指定する. 実行結果†実行結果のスクリーンショットを以下に示す(クリックで拡大). ソースコード†Visual Studio 2010用のソースコードを以下に置く(要GLUT,GLEW,libpng,libjpeg,zlib).
|