最終更新: mikk_ni3_92 2009年12月20日(日) 17:30:33履歴
現在地:メニュー >> Cg >> Cg編05 >> Cg編05::ライティング1
関連:GLSL編04
オブジェクト座標系ということは、物体の中心に原点がある座標系である。
ここでは、簡潔にするために
「オブジェクト座標系」と「ワールド座標系」が一致している
状態でライティングを考えてみる。
つまり、描画物に対し、平行移動や回転移動などを行わず
ワールド座標系でも原点に物体が置いてある状態で考える。
基本的には以下の図
「halfVec」は
つまり、halfVec = (EyeVec + LightVec) / 2ということ。
陰影付けにおいて計算上必要なのは、
「法線とLightVecの内積」、「法線とhalfVecの内積」
である。
【拡散反射】
拡散反射光(diffuse)にはランバート反射のモデル等がある。
【プログラム例】
【鏡面反射】
鏡面反射光には「phongのモデルやBlinのモデル」がある
■phongのモデル
■Blinのモデル
上で説明したような原理をそのまま記述してもよい。
しかし、ここでは簡潔にするために「lit関数」を使用する。
float4 lit(ndotl, ndoth, m)
「Blinのモデル」をつかってライティング係数を計算する。
【ndotl】:「法線ベクトルと光源ベクトルの内積」を指定。
【ndoth】:「法線ベクトルとhalfVecの内積」を指定。
【m】:鏡面指数
この計算で返ってきたライティング係数はそれぞれ
x:1
y:diffuseに演算する係数
z:speclarに演算する係数
w:1
である。
【例】:光源の色は(1,1,1)
このように、それぞれの光の要素の色は
そして、全ての光の要素を足したものが、ライティングした色となる。
関連:GLSL編04
オブジェクト座標系ということは、物体の中心に原点がある座標系である。
ここでは、簡潔にするために
「オブジェクト座標系」と「ワールド座標系」が一致している
状態でライティングを考えてみる。
つまり、描画物に対し、平行移動や回転移動などを行わず
ワールド座標系でも原点に物体が置いてある状態で考える。
基本的には以下の図
「halfVec」は
- 頂点から視点へのベクトル「EyeVec」(図の青いベクトル)
- 頂点から光源へのベクトル「LightVec」(図の赤いベクトル)
つまり、halfVec = (EyeVec + LightVec) / 2ということ。
陰影付けにおいて計算上必要なのは、
「法線とLightVecの内積」、「法線とhalfVecの内積」
である。
【拡散反射】
拡散反射光(diffuse)にはランバート反射のモデル等がある。
【プログラム例】
float3 L = normalize(lightPosition - P); //(光源 - 頂点位置)を正規化 → 点から見た光源への単位ベクトル float diffuseLight = max(dot(N, L), 0); //法線NとLの内積を計算。 0と比較し、大きい方を返す float3 diffuse = Kd * lightColor * diffuseLight; //拡散光 = (拡散光の係数) * (光源の色) * (diffuseLight)
【鏡面反射】
鏡面反射光には「phongのモデルやBlinのモデル」がある
■phongのモデル
float3 V = normalize(eyePos - P); float3 R = normalize(2*dot(L,N)*N - L); float specularLight = pow(max(dot(R,V), 0), shininess); if (diffuseLight <= 0) specularLight = 0; float3 specular = Ks * lightColor * specularLight;
■Blinのモデル
float3 V = normalize(eyePos - P);//Blinのモデルで計算 float3 H = normalize(L + V); float specularLight = pow(max(dot(N, H), 0), shininess); if (diffuseLight <= 0) specularLight = 0; float3 specular = Ks * lightColor * specularLight;
上で説明したような原理をそのまま記述してもよい。
しかし、ここでは簡潔にするために「lit関数」を使用する。
float4 lit(ndotl, ndoth, m)
「Blinのモデル」をつかってライティング係数を計算する。
【ndotl】:「法線ベクトルと光源ベクトルの内積」を指定。
【ndoth】:「法線ベクトルとhalfVecの内積」を指定。
【m】:鏡面指数
この計算で返ってきたライティング係数はそれぞれ
x:1
y:diffuseに演算する係数
z:speclarに演算する係数
w:1
である。
【例】:光源の色は(1,1,1)
float3 calcVertexLighting(VertexIn input, uniform float3 objEye, uniform float4 objLight) { float3 eyeVec = normalize(objEye - input.position.xyz);//視点へのベクトル float3 lightVec = normalize(objLight.xyz - input.position.xyz);//光源へのベクトル float3 halfVec = normalize(eyeVec + lightVec); float3 normalVec = normalize(input.normal.xyz); float NL = dot(normalVec,lightVec); float NH = dot(normalVec,halfVec); float3 lightColor = float3(1,1,1);//光の色は(1,1,1) float4 lightingCoff = lit(NL,NH,52); float3 ambMaterial = float3( 0.24725, 0.1995, 0.0745); float3 diffMaterial = float3(0.75164, 0.60648 , 0.22648); float3 specMaterial = float3(0.628281, 0.555802,0.366065); float3 color = lightColor * lightingCoff.x * ambMaterial + lightColor * lightingCoff.y * diffMaterial + lightColor * lightingCoff.z * specMaterial; return color; }
このように、それぞれの光の要素の色は
(光源の色)*(材質の反射係数)*(ライティング係数)で計算できる。
そして、全ての光の要素を足したものが、ライティングした色となる。