GLSLによるフォンシェーディング
をテンプレートにして作成
[
トップ
|
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
]
開始行:
GLSLを用いてフォンシェーディングを実装する.ここではまず...
----
#contents
----
*反射モデル [#l2106d45]
反射モデルは光の物体表面における反射をモデル化したもので...
ここでは,反射を環境光,拡散反射,鏡面反射に分けて考えるP...
#ref(eq_Is.gif)
k_e,k_a,k_dはそれぞれ物体表面の放射,環境,拡散反射色であ...
I_s は鏡面反射項であり,以下で説明する鏡面反射モデルによ...
#ref(reflection.gif)
***Phong 鏡面反射モデル((B. Phong, "Illumination for comp...
#ref(eq_Phong.gif)
k_s は物体の鏡面反射色,m は鏡面反射指数でハイライトの強...
また,''R'' は以下で計算される.
#ref(eq_R.gif)
***Blinn-Phong 鏡面反射モデル [#q72b7deb]
Blinn により,''R'' をハーフベクトル''H'' に置き換えるモ...
#ref(eq_BlinnPhong.gif)
#ref(eq_H.gif)
***Blinn 鏡面反射モデル((J. Blinn, "Models of light refle...
Torrance-Sparrow モデルを基にして,反射面を微少面(micro f...
#ref(eq_Blinn.gif)
D,G,Fそれぞれの項は,
-D : 微少面分布関数であり,法線がH であるmicro facet の割...
--Phongモデル : &ref(eq_D1.gif);
--Torrance-Sparrowモデル : &ref(eq_D2.gif);
--TrowbridgeとReitzのモデル : &ref(eq_D3.gif);
が用いられる.α は''N''と''H''のなす角(&ref(eq_alpha.gif)...
c_2 は分布の標準偏差,c_3 は楕円の偏心度で0ならハイライト...
-G : 微少面に入射する光,もしくは,微少面から反射する光は...
これにより,鏡面反射が暗くなる現象を表すための項である.
#ref(eq_G.gif)
1 は光が遮断されない場合,G1 は反射項の一部が遮断される場...
-F : フレネル項であり,θ1 を入射角,θ2 は透過角とすると,
#ref(eq_F1.gif)
鏡面反射に関わる微少面の法線ベクトルは''H''となっているこ...
これにより,上式を整理していくと以下のようになる.
#ref(eq_F2.gif)
ここで,&ref(eq_n.gif);は屈折率である.
***Cook-Torrance 鏡面反射モデル((R. Cook and K. Torrance,...
Blinn モデルを改良して,微少面分布関数D にBeckmann 分布関...
#ref(eq_CookTorrance.gif)
*グーローとフォンシェーディング [#kda00770]
反射モデルに基づき,画面にCGモデルを描画する際にどのよう...
CG分野ではグーローシェーディングとフォンシェーディングの2...
グーローシェーディングはまず,頂点ごとに上記の反射モデル...
その後,ピクセルごとの処理において頂点色を線形補間するこ...
一方,フォンシェーディングはピクセルごとに色を計算する方...
OpenGLの描画ではグーローシェーディングが採用されている.
そのため,フォンシェーディングを行いたい場合,GLSLやNVIDI...
*GLSLによるフォンシェーディング [#i6e091d0]
GLSLを用いてフォンシェーディングを行う場合は,フラグメン...
そのため,頂点シェーダは単純に透視投影変換前の視点座標系...
#code(C){{
/*!
@file phong.vs
@brief GLSLフラグメントシェーダ
- フォンシェーディング
@author Makoto Fujisawa
@date 2011
*/
#version 120
// フラグメントシェーダに値を渡すための変数
varying vec3 vPos;
varying vec3 vNrm;
void main(void)
{
// 頂点位置と法線
vPos = (gl_ModelViewMatrix*gl_Vertex).xyz;
vNrm = gl_NormalMatrix*gl_Normal;
// 描画頂点位置
gl_Position = ftransform();
}
}}
フラグメントシェーダでは,Blinn-Phongの鏡面反射モデルを用...
以下にコード例を示す.コード例では上記の式との対応関係が...
実際には,表面の色とライトの色の掛け算などは gl_FrontLigh...
#code(C){{
/*!
@file phong.fs
@brief GLSLフラグメントシェーダ
- フォンシェーディング
@author Makoto Fujisawa
@date 2011
*/
#version 120
// バーテックスシェーダから受け取る変数
varying vec3 vPos;
varying vec3 vNrm;
void main(void)
{
// 光源
vec3 La = gl_LightSource[0].ambient.xyz; // ライト環境光
vec3 Ld = gl_LightSource[0].diffuse.xyz; // ライト拡散反...
vec3 Ls = gl_LightSource[0].specular.xyz; // ライト鏡面...
vec3 Lp = gl_LightSource[0].position.xyz; // ライト位置
// 材質
vec3 Ke = gl_FrontMaterial.emission.xyz; // 放射色
vec3 Ka = gl_FrontMaterial.ambient.xyz; // 環境光
vec3 Kd = gl_FrontMaterial.diffuse.xyz; // 拡散反射
vec3 Ks = gl_FrontMaterial.specular.xyz; // 鏡面反射
float shine = gl_FrontMaterial.shininess;
vec3 V = normalize(-vPos.xyz); // 視線ベクトル
vec3 N = normalize(vNrm); // 法線ベクトル
vec3 L = normalize(Lp-vPos.xyz); // ライトベクトル
// 放射色の計算
vec3 emissive = Ke;
// 環境光の計算
vec3 ambient = Ka*La; // gl_FrontLightProduct[0].ambent...
// 拡散反射の計算
float diffuseLight = max(dot(L, N), 0.0);
vec3 diffuse = Kd*Ld*diffuseLight;
// 鏡面反射の計算
vec3 specular = vec3(0.0);
if(diffuseLight > 0.0){
// フォン反射モデル
//vec3 R = reflect(-L, N);
//vec3 R = -L+2*dot(N, L)*N; // reflect関数を用いない場合
//float specularLight = pow(max(dot(R, N), 0.0), shine);
// ハーフベクトルによる反射(Blinn-Phong)
vec3 H = normalize(L+V);
float specularLight = pow(max(dot(H, N), 0.0), shine);
specular = Ks*Ls*specularLight;
}
gl_FragColor.xyz = emissive+ambient+diffuse+specular;
gl_FragColor.w = 1.0;
}
}}
以下のコード例はCook-Torrance鏡面反射モデルに基づくフラグ...
#code(C){{
/*!
@file cook_torrance.fs
@brief GLSLフラグメントシェーダ
- Cook-Torrance鏡面反射モデル
@author Makoto Fujisawa
@date 2011
*/
#version 120
uniform float m;
uniform float refrac;
// バーテックスシェーダから受け取る変数
varying vec3 vPos;
varying vec3 vNrm;
void main(void)
{
// 光源
vec3 La = gl_LightSource[0].ambient.xyz; // ライト環境光
vec3 Ld = gl_LightSource[0].diffuse.xyz; // ライト拡散反...
vec3 Ls = gl_LightSource[0].specular.xyz; // ライト鏡面...
vec3 Lp = gl_LightSource[0].position.xyz; // ライト位置
// 材質
vec3 Ke = gl_FrontMaterial.emission.xyz; // 放射色
vec3 Ka = gl_FrontMaterial.ambient.xyz; // 環境光
vec3 Kd = gl_FrontMaterial.diffuse.xyz; // 拡散反射
vec3 Ks = gl_FrontMaterial.specular.xyz; // 鏡面反射
float shine = gl_FrontMaterial.shininess;
vec3 V = normalize(-vPos.xyz); // 視線ベクトル
vec3 N = normalize(vNrm); // 法線ベクトル
vec3 L = normalize(Lp-vPos.xyz); // ライトベクトル
vec3 H = normalize(L+V); // ハーフベクトル
// 放射色の計算
vec3 emissive = Ke;
// 環境光の計算
vec3 ambient = Ka*La; // gl_FrontLightProduct[0].ambent...
// 拡散反射の計算
float diffuseLight = max(dot(L, N), 0.0);
vec3 diffuse = Kd*Ld*diffuseLight;
// 鏡面反射の計算
vec3 specular = vec3(0.0);
if(diffuseLight > 0.0){
// Cook-Torrance反射モデルの計算
float NH = dot(N, H);
float VH = dot(V, H);
float NV = dot(N, V);
float NL = dot(N, L);
float alpha = acos(NH);
// D:ベックマン分布関数
float D = (1.0/(4*m*m*NH*NH*NH*NH))*exp((NH*NH-1)/(m*m*...
// G:幾何減衰
float G = min(1, min((2*NH*NV)/VH, (2*NH*NL)/VH));
// F:フレネル項
float c = VH;
float g = sqrt(refrac*refrac+c*c-1);
float F = ((g-c)*(g-c)/((g+c)*(g+c)))*(1+(c*(g+c)-1)*(c...
float specularLight = D*G*F/NV;
specular = Ks*Ls*specularLight;
}
gl_FragColor.xyz = emissive+ambient+diffuse+specular;
gl_FragColor.w = 1.0;
}
}}
*レンダリング結果 [#v21e4b4b]
左からグーローシェーディング,フォンシェーディング(Phong...
&ref(gouraud_shading_1.jpg); &ref(phong_shading_1.jpg); &...
*ソースコード [#n92bb63c]
Visual Studio 2010用のソースコードを以下に置く.
#ref(glsl_phong.zip)
終了行:
GLSLを用いてフォンシェーディングを実装する.ここではまず...
----
#contents
----
*反射モデル [#l2106d45]
反射モデルは光の物体表面における反射をモデル化したもので...
ここでは,反射を環境光,拡散反射,鏡面反射に分けて考えるP...
#ref(eq_Is.gif)
k_e,k_a,k_dはそれぞれ物体表面の放射,環境,拡散反射色であ...
I_s は鏡面反射項であり,以下で説明する鏡面反射モデルによ...
#ref(reflection.gif)
***Phong 鏡面反射モデル((B. Phong, "Illumination for comp...
#ref(eq_Phong.gif)
k_s は物体の鏡面反射色,m は鏡面反射指数でハイライトの強...
また,''R'' は以下で計算される.
#ref(eq_R.gif)
***Blinn-Phong 鏡面反射モデル [#q72b7deb]
Blinn により,''R'' をハーフベクトル''H'' に置き換えるモ...
#ref(eq_BlinnPhong.gif)
#ref(eq_H.gif)
***Blinn 鏡面反射モデル((J. Blinn, "Models of light refle...
Torrance-Sparrow モデルを基にして,反射面を微少面(micro f...
#ref(eq_Blinn.gif)
D,G,Fそれぞれの項は,
-D : 微少面分布関数であり,法線がH であるmicro facet の割...
--Phongモデル : &ref(eq_D1.gif);
--Torrance-Sparrowモデル : &ref(eq_D2.gif);
--TrowbridgeとReitzのモデル : &ref(eq_D3.gif);
が用いられる.α は''N''と''H''のなす角(&ref(eq_alpha.gif)...
c_2 は分布の標準偏差,c_3 は楕円の偏心度で0ならハイライト...
-G : 微少面に入射する光,もしくは,微少面から反射する光は...
これにより,鏡面反射が暗くなる現象を表すための項である.
#ref(eq_G.gif)
1 は光が遮断されない場合,G1 は反射項の一部が遮断される場...
-F : フレネル項であり,θ1 を入射角,θ2 は透過角とすると,
#ref(eq_F1.gif)
鏡面反射に関わる微少面の法線ベクトルは''H''となっているこ...
これにより,上式を整理していくと以下のようになる.
#ref(eq_F2.gif)
ここで,&ref(eq_n.gif);は屈折率である.
***Cook-Torrance 鏡面反射モデル((R. Cook and K. Torrance,...
Blinn モデルを改良して,微少面分布関数D にBeckmann 分布関...
#ref(eq_CookTorrance.gif)
*グーローとフォンシェーディング [#kda00770]
反射モデルに基づき,画面にCGモデルを描画する際にどのよう...
CG分野ではグーローシェーディングとフォンシェーディングの2...
グーローシェーディングはまず,頂点ごとに上記の反射モデル...
その後,ピクセルごとの処理において頂点色を線形補間するこ...
一方,フォンシェーディングはピクセルごとに色を計算する方...
OpenGLの描画ではグーローシェーディングが採用されている.
そのため,フォンシェーディングを行いたい場合,GLSLやNVIDI...
*GLSLによるフォンシェーディング [#i6e091d0]
GLSLを用いてフォンシェーディングを行う場合は,フラグメン...
そのため,頂点シェーダは単純に透視投影変換前の視点座標系...
#code(C){{
/*!
@file phong.vs
@brief GLSLフラグメントシェーダ
- フォンシェーディング
@author Makoto Fujisawa
@date 2011
*/
#version 120
// フラグメントシェーダに値を渡すための変数
varying vec3 vPos;
varying vec3 vNrm;
void main(void)
{
// 頂点位置と法線
vPos = (gl_ModelViewMatrix*gl_Vertex).xyz;
vNrm = gl_NormalMatrix*gl_Normal;
// 描画頂点位置
gl_Position = ftransform();
}
}}
フラグメントシェーダでは,Blinn-Phongの鏡面反射モデルを用...
以下にコード例を示す.コード例では上記の式との対応関係が...
実際には,表面の色とライトの色の掛け算などは gl_FrontLigh...
#code(C){{
/*!
@file phong.fs
@brief GLSLフラグメントシェーダ
- フォンシェーディング
@author Makoto Fujisawa
@date 2011
*/
#version 120
// バーテックスシェーダから受け取る変数
varying vec3 vPos;
varying vec3 vNrm;
void main(void)
{
// 光源
vec3 La = gl_LightSource[0].ambient.xyz; // ライト環境光
vec3 Ld = gl_LightSource[0].diffuse.xyz; // ライト拡散反...
vec3 Ls = gl_LightSource[0].specular.xyz; // ライト鏡面...
vec3 Lp = gl_LightSource[0].position.xyz; // ライト位置
// 材質
vec3 Ke = gl_FrontMaterial.emission.xyz; // 放射色
vec3 Ka = gl_FrontMaterial.ambient.xyz; // 環境光
vec3 Kd = gl_FrontMaterial.diffuse.xyz; // 拡散反射
vec3 Ks = gl_FrontMaterial.specular.xyz; // 鏡面反射
float shine = gl_FrontMaterial.shininess;
vec3 V = normalize(-vPos.xyz); // 視線ベクトル
vec3 N = normalize(vNrm); // 法線ベクトル
vec3 L = normalize(Lp-vPos.xyz); // ライトベクトル
// 放射色の計算
vec3 emissive = Ke;
// 環境光の計算
vec3 ambient = Ka*La; // gl_FrontLightProduct[0].ambent...
// 拡散反射の計算
float diffuseLight = max(dot(L, N), 0.0);
vec3 diffuse = Kd*Ld*diffuseLight;
// 鏡面反射の計算
vec3 specular = vec3(0.0);
if(diffuseLight > 0.0){
// フォン反射モデル
//vec3 R = reflect(-L, N);
//vec3 R = -L+2*dot(N, L)*N; // reflect関数を用いない場合
//float specularLight = pow(max(dot(R, N), 0.0), shine);
// ハーフベクトルによる反射(Blinn-Phong)
vec3 H = normalize(L+V);
float specularLight = pow(max(dot(H, N), 0.0), shine);
specular = Ks*Ls*specularLight;
}
gl_FragColor.xyz = emissive+ambient+diffuse+specular;
gl_FragColor.w = 1.0;
}
}}
以下のコード例はCook-Torrance鏡面反射モデルに基づくフラグ...
#code(C){{
/*!
@file cook_torrance.fs
@brief GLSLフラグメントシェーダ
- Cook-Torrance鏡面反射モデル
@author Makoto Fujisawa
@date 2011
*/
#version 120
uniform float m;
uniform float refrac;
// バーテックスシェーダから受け取る変数
varying vec3 vPos;
varying vec3 vNrm;
void main(void)
{
// 光源
vec3 La = gl_LightSource[0].ambient.xyz; // ライト環境光
vec3 Ld = gl_LightSource[0].diffuse.xyz; // ライト拡散反...
vec3 Ls = gl_LightSource[0].specular.xyz; // ライト鏡面...
vec3 Lp = gl_LightSource[0].position.xyz; // ライト位置
// 材質
vec3 Ke = gl_FrontMaterial.emission.xyz; // 放射色
vec3 Ka = gl_FrontMaterial.ambient.xyz; // 環境光
vec3 Kd = gl_FrontMaterial.diffuse.xyz; // 拡散反射
vec3 Ks = gl_FrontMaterial.specular.xyz; // 鏡面反射
float shine = gl_FrontMaterial.shininess;
vec3 V = normalize(-vPos.xyz); // 視線ベクトル
vec3 N = normalize(vNrm); // 法線ベクトル
vec3 L = normalize(Lp-vPos.xyz); // ライトベクトル
vec3 H = normalize(L+V); // ハーフベクトル
// 放射色の計算
vec3 emissive = Ke;
// 環境光の計算
vec3 ambient = Ka*La; // gl_FrontLightProduct[0].ambent...
// 拡散反射の計算
float diffuseLight = max(dot(L, N), 0.0);
vec3 diffuse = Kd*Ld*diffuseLight;
// 鏡面反射の計算
vec3 specular = vec3(0.0);
if(diffuseLight > 0.0){
// Cook-Torrance反射モデルの計算
float NH = dot(N, H);
float VH = dot(V, H);
float NV = dot(N, V);
float NL = dot(N, L);
float alpha = acos(NH);
// D:ベックマン分布関数
float D = (1.0/(4*m*m*NH*NH*NH*NH))*exp((NH*NH-1)/(m*m*...
// G:幾何減衰
float G = min(1, min((2*NH*NV)/VH, (2*NH*NL)/VH));
// F:フレネル項
float c = VH;
float g = sqrt(refrac*refrac+c*c-1);
float F = ((g-c)*(g-c)/((g+c)*(g+c)))*(1+(c*(g+c)-1)*(c...
float specularLight = D*G*F/NV;
specular = Ks*Ls*specularLight;
}
gl_FragColor.xyz = emissive+ambient+diffuse+specular;
gl_FragColor.w = 1.0;
}
}}
*レンダリング結果 [#v21e4b4b]
左からグーローシェーディング,フォンシェーディング(Phong...
&ref(gouraud_shading_1.jpg); &ref(phong_shading_1.jpg); &...
*ソースコード [#n92bb63c]
Visual Studio 2010用のソースコードを以下に置く.
#ref(glsl_phong.zip)
ページ名: