GLSLで環境マップ&フレネル効果
をテンプレートにして作成
[
トップ
|
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
]
開始行:
GLSLを使い環境マップ(キューブマップ)と反射・屈折効果を実...
----
#contents
----
**キューブマップとフレネル効果(Fresnel reflection)につい...
***環境マップ [#f39cba66]
鏡面反射表面上への写り込みや透過物体の表現はレンダリング...
しかし,これらの効果を正確にシミュレートする場合,レイト...
そこで写り込みや屈折に影響するのは遠景だけであるとし,
環境に配置した遠景を表す画像を使ってこれらの効果を表現す...
この方法は環境マップと呼ばれ,画像を球形状に貼り付けるス...
立方体形状に貼り付けるキューブマップの2つが一般的である.
キューブマップに用いる画像の例を以下に示す.
#ref(cube_map.jpg,,100%);
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を使って反射,屈折ベ...
キューブマップテクスチャを参照することで反射・屈折効果を...
ただし,一次反射,屈折のみで複数回の反射などは考慮しない.
***反射方向ベクトルの算出 [#e2fe62d6]
GLSLによるフォンシェーディングで説明したように,反射ベク...
#ref(fresnel.eq1.gif,nolink,70%)
反射ベクトルを計算するシェーダコードを以下に示す.
#code(C){{
vec3 Reflection(vec3 I, vec3 N)
{
float cos_theta = dot(-I, N);
vec3 R = 2*N*cos_theta+I;
return (cos_theta > 0 ? normalize(R) : vec3(0.0));
}
}}
また,GLSLには反射ベクトルを計算するビルトイン関数 reflec...
vec3 R = reflect(I, N);
としても良い.
***透過屈折方向ベクトルの算出 [#k2a4a378]
スネルの法則(snell's law)より,入射角&ref(fresnel.eq2.gif...
#ref(fresnel.eq4.gif,nolink,70%)
の関係がある.
ここで&ref(fresnel.eq5.gif,nolink,70%);は境界面をはさむ両...
#ref(refraction_model.jpg,,70%)
上の図において,入射ベクトル&ref(fresnel.eq6.gif,nolink,7...
は単位ベクトルとする.
&ref(fresnel.eq10.gif,nolink,70%);, &ref(fresnel.eq11.gif...
#ref(fresnel.eq14.gif,nolink,70%)
よって,
#ref(fresnel.eq15.gif,nolink,70%)
#ref(fresnel.eq16.gif,nolink,70%)
ここで&ref(fresnel.eq12.gif,nolink,70%);と&ref(fresnel.eq...
#ref(fresnel.eq17.gif,nolink,70%)
よって,
#ref(fresnel.eq18.gif,nolink,70%)
また,スネルの法則より,
#ref(fresnel.eq19.gif,nolink,70%)
この式の両辺に&ref(fresnel.eq12.gif,nolink,70%);をかけて...
#ref(fresnel.eq20.gif,nolink,70%)
&ref(fresnel.eq8.gif,nolink,70%);について解くと,
#ref(fresnel.eq21.gif,nolink,70%)
ここで,
#ref(fresnel.eq22.gif,nolink,70%)
&ref(fresnel.eq23.gif,nolink,70%);は&ref(fresnel.eq24.gif...
屈折ベクトルを計算するシェーダコードを以下に示す.
#code(C){{
vec3 Refraction(vec3 I, vec3 N, float e)
{
float cos_theta = dot(-I, N);
float cos_phi2 = 1.0-e*e*(1.0-cos_theta*cos_theta);
vec3 T = e*(I+N*cos_theta)-N*sqrt(abs(cos_phi2));
return (cos_phi2 > 0 ? normalize(T) : vec3(0.0));
}
}}
ここで,引数eには屈折率比を指定する.
また,GLSLには屈折ベクトルを計算するビルトイン関数 refrac...
vec3 T = refract(I, N, e);
としても良い.
***フレネル効果 [#a26f5e9a]
フレネル効果とは,透明な物体表面においてみる角度によって...
入射光強度&ref(fresnel.eq6.gif,nolink,70%);のうち,&ref(f...
ここで,&ref(fresnel.eq27.gif,nolink,70%);,&ref(fresnel.e...
表面での損失がなければ&ref(fresnel.eq29.gif,nolink,70%);...
視点に届く光に関して考えると,
表面上の点に反射方向から届く光の強度を&ref(fresnel.eq30.g...
屈折方向からの強度を&ref(fresnel.eq31.gif,nolink,70%);と...
視点に届く色は&ref(fresnel.eq32.gif,nolink,70%);となる.
このときの鏡面反射係数はフレネルの公式より,
#ref(fresnel.eq33.gif,nolink,70%)
計算を簡単にするためとユーザによる制御を容易にするために
¬e{Fernando2003:R. Fernando and M. J. Kilgard, The Cg ...
#ref(fresnel.eq34.gif,nolink,70%)
ここでbiasは値が小さいと反射成分が弱くなりほとんど屈折し...
上記の反射・屈折ベクトルの算出方法とフレネル効果の近似式...
まず,頂点シェーダは,
#code(C){{
// フラグメントシェーダに値を渡すための変数
varying vec4 vPos;
varying vec3 vNrm;
void main(void)
{
// フラグメントシェーダでの計算用(モデルビュー変換のみ)
vPos = gl_Vertex; // 頂点位置
vNrm = normalize(gl_NormalMatrix*gl_Normal); // 頂点法線
// 描画頂点位置
gl_Position = ftransform();
}
}}
フラグメントシェーダにおける視点位置eyePositionがローカル...
vPosにはローカル座標の値をそのまま用いている.
頂点シェーダは[[GLSLによるフォンシェーディング]]のものと...
次にフラグメントシェーダを以下に示す.
#code(C){{
// バーテックスシェーダから受け取る変数
varying vec4 vPos;
varying vec3 vNrm;
// GLから設定される定数(uniform)
uniform float fresnelBias;
uniform float fresnelScale;
uniform float fresnelPower;
uniform float etaRatio;
uniform vec3 eyePosition;
uniform samplerCube envmap;
vec4 lerp(vec4 a, vec4 b, float s)
{
return vec4(a+(b-a)*s);
}
/*!
* Fresnel反射モデルによるシェーディング
* @return 表面反射色
*/
vec4 FresnelShading(void)
{
// 入射,反射,屈折ベクトルの計算
vec3 N = normalize(vNrm); // 法線ベクトル
vec3 I = normalize(vPos.xyz-eyePosition); // 入射ベクトル
//vec3 R = reflect(I, N); // 反射ベクトル
vec3 R = Reflection(I, N); // 反射ベクトル
//vec3 T = refract(I, N, etaRatio); // 屈折ベクトル
vec3 T = Refraction(I, N, etaRatio); // 屈折ベクトル
// 反射因数の計算
float fresnel = fresnelBias+fresnelScale*pow(min(0.0, 1....
// 反射環境色の取得
vec4 reflecColor = textureCube(envmap, R);
reflecColor.a = 1.0;
// 屈折環境色の計算
vec4 refracColor;
refracColor.rgb = textureCube(envmap, T).rgb;
refracColor.a = 1.0;
// 色を統合
vec4 cout = lerp(refracColor, reflecColor, fresnel);
cout.a = fresnel*0.5+0.5;
return cout;
}
}}
OpenGL側から各パラメータと視点位置,
GL_TEXTURE_CUBE_MAPとして生成したキューブマップテクスチャ...
**実行結果 [#r7574160]
実行結果のスクリーンショットを以下に示す(クリックで拡大).
|&ref(fresnel_result1.jpg,,50%);|&ref(fresnel_result2.jpg...
|etaRatio=0.8,bias=0.3|etaRatio=0.8,bias=1.0|
**ソースコード [#l7b6aa51]
Visual Studio 2010用のソースコードを以下に置く(要GLUT,GLE...
#ref(glsl_fresnel_v1.1.zip)
-version1.1 : 視点位置と頂点位置の整合性がとれていなかっ...
終了行:
GLSLを使い環境マップ(キューブマップ)と反射・屈折効果を実...
----
#contents
----
**キューブマップとフレネル効果(Fresnel reflection)につい...
***環境マップ [#f39cba66]
鏡面反射表面上への写り込みや透過物体の表現はレンダリング...
しかし,これらの効果を正確にシミュレートする場合,レイト...
そこで写り込みや屈折に影響するのは遠景だけであるとし,
環境に配置した遠景を表す画像を使ってこれらの効果を表現す...
この方法は環境マップと呼ばれ,画像を球形状に貼り付けるス...
立方体形状に貼り付けるキューブマップの2つが一般的である.
キューブマップに用いる画像の例を以下に示す.
#ref(cube_map.jpg,,100%);
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を使って反射,屈折ベ...
キューブマップテクスチャを参照することで反射・屈折効果を...
ただし,一次反射,屈折のみで複数回の反射などは考慮しない.
***反射方向ベクトルの算出 [#e2fe62d6]
GLSLによるフォンシェーディングで説明したように,反射ベク...
#ref(fresnel.eq1.gif,nolink,70%)
反射ベクトルを計算するシェーダコードを以下に示す.
#code(C){{
vec3 Reflection(vec3 I, vec3 N)
{
float cos_theta = dot(-I, N);
vec3 R = 2*N*cos_theta+I;
return (cos_theta > 0 ? normalize(R) : vec3(0.0));
}
}}
また,GLSLには反射ベクトルを計算するビルトイン関数 reflec...
vec3 R = reflect(I, N);
としても良い.
***透過屈折方向ベクトルの算出 [#k2a4a378]
スネルの法則(snell's law)より,入射角&ref(fresnel.eq2.gif...
#ref(fresnel.eq4.gif,nolink,70%)
の関係がある.
ここで&ref(fresnel.eq5.gif,nolink,70%);は境界面をはさむ両...
#ref(refraction_model.jpg,,70%)
上の図において,入射ベクトル&ref(fresnel.eq6.gif,nolink,7...
は単位ベクトルとする.
&ref(fresnel.eq10.gif,nolink,70%);, &ref(fresnel.eq11.gif...
#ref(fresnel.eq14.gif,nolink,70%)
よって,
#ref(fresnel.eq15.gif,nolink,70%)
#ref(fresnel.eq16.gif,nolink,70%)
ここで&ref(fresnel.eq12.gif,nolink,70%);と&ref(fresnel.eq...
#ref(fresnel.eq17.gif,nolink,70%)
よって,
#ref(fresnel.eq18.gif,nolink,70%)
また,スネルの法則より,
#ref(fresnel.eq19.gif,nolink,70%)
この式の両辺に&ref(fresnel.eq12.gif,nolink,70%);をかけて...
#ref(fresnel.eq20.gif,nolink,70%)
&ref(fresnel.eq8.gif,nolink,70%);について解くと,
#ref(fresnel.eq21.gif,nolink,70%)
ここで,
#ref(fresnel.eq22.gif,nolink,70%)
&ref(fresnel.eq23.gif,nolink,70%);は&ref(fresnel.eq24.gif...
屈折ベクトルを計算するシェーダコードを以下に示す.
#code(C){{
vec3 Refraction(vec3 I, vec3 N, float e)
{
float cos_theta = dot(-I, N);
float cos_phi2 = 1.0-e*e*(1.0-cos_theta*cos_theta);
vec3 T = e*(I+N*cos_theta)-N*sqrt(abs(cos_phi2));
return (cos_phi2 > 0 ? normalize(T) : vec3(0.0));
}
}}
ここで,引数eには屈折率比を指定する.
また,GLSLには屈折ベクトルを計算するビルトイン関数 refrac...
vec3 T = refract(I, N, e);
としても良い.
***フレネル効果 [#a26f5e9a]
フレネル効果とは,透明な物体表面においてみる角度によって...
入射光強度&ref(fresnel.eq6.gif,nolink,70%);のうち,&ref(f...
ここで,&ref(fresnel.eq27.gif,nolink,70%);,&ref(fresnel.e...
表面での損失がなければ&ref(fresnel.eq29.gif,nolink,70%);...
視点に届く光に関して考えると,
表面上の点に反射方向から届く光の強度を&ref(fresnel.eq30.g...
屈折方向からの強度を&ref(fresnel.eq31.gif,nolink,70%);と...
視点に届く色は&ref(fresnel.eq32.gif,nolink,70%);となる.
このときの鏡面反射係数はフレネルの公式より,
#ref(fresnel.eq33.gif,nolink,70%)
計算を簡単にするためとユーザによる制御を容易にするために
¬e{Fernando2003:R. Fernando and M. J. Kilgard, The Cg ...
#ref(fresnel.eq34.gif,nolink,70%)
ここでbiasは値が小さいと反射成分が弱くなりほとんど屈折し...
上記の反射・屈折ベクトルの算出方法とフレネル効果の近似式...
まず,頂点シェーダは,
#code(C){{
// フラグメントシェーダに値を渡すための変数
varying vec4 vPos;
varying vec3 vNrm;
void main(void)
{
// フラグメントシェーダでの計算用(モデルビュー変換のみ)
vPos = gl_Vertex; // 頂点位置
vNrm = normalize(gl_NormalMatrix*gl_Normal); // 頂点法線
// 描画頂点位置
gl_Position = ftransform();
}
}}
フラグメントシェーダにおける視点位置eyePositionがローカル...
vPosにはローカル座標の値をそのまま用いている.
頂点シェーダは[[GLSLによるフォンシェーディング]]のものと...
次にフラグメントシェーダを以下に示す.
#code(C){{
// バーテックスシェーダから受け取る変数
varying vec4 vPos;
varying vec3 vNrm;
// GLから設定される定数(uniform)
uniform float fresnelBias;
uniform float fresnelScale;
uniform float fresnelPower;
uniform float etaRatio;
uniform vec3 eyePosition;
uniform samplerCube envmap;
vec4 lerp(vec4 a, vec4 b, float s)
{
return vec4(a+(b-a)*s);
}
/*!
* Fresnel反射モデルによるシェーディング
* @return 表面反射色
*/
vec4 FresnelShading(void)
{
// 入射,反射,屈折ベクトルの計算
vec3 N = normalize(vNrm); // 法線ベクトル
vec3 I = normalize(vPos.xyz-eyePosition); // 入射ベクトル
//vec3 R = reflect(I, N); // 反射ベクトル
vec3 R = Reflection(I, N); // 反射ベクトル
//vec3 T = refract(I, N, etaRatio); // 屈折ベクトル
vec3 T = Refraction(I, N, etaRatio); // 屈折ベクトル
// 反射因数の計算
float fresnel = fresnelBias+fresnelScale*pow(min(0.0, 1....
// 反射環境色の取得
vec4 reflecColor = textureCube(envmap, R);
reflecColor.a = 1.0;
// 屈折環境色の計算
vec4 refracColor;
refracColor.rgb = textureCube(envmap, T).rgb;
refracColor.a = 1.0;
// 色を統合
vec4 cout = lerp(refracColor, reflecColor, fresnel);
cout.a = fresnel*0.5+0.5;
return cout;
}
}}
OpenGL側から各パラメータと視点位置,
GL_TEXTURE_CUBE_MAPとして生成したキューブマップテクスチャ...
**実行結果 [#r7574160]
実行結果のスクリーンショットを以下に示す(クリックで拡大).
|&ref(fresnel_result1.jpg,,50%);|&ref(fresnel_result2.jpg...
|etaRatio=0.8,bias=0.3|etaRatio=0.8,bias=1.0|
**ソースコード [#l7b6aa51]
Visual Studio 2010用のソースコードを以下に置く(要GLUT,GLE...
#ref(glsl_fresnel_v1.1.zip)
-version1.1 : 視点位置と頂点位置の整合性がとれていなかっ...
ページ名: