ある地点における光の強さは、光源までの距離を d 、一定減衰率を kc 、1時減衰率を k1 、2時減衰率を k2 とすると以下の式で表すことができます。
減衰率kc, k1, k2はそれぞれGL側(ホストプログラム)からシェーダ側に送ることができる。
以下はホスト側のプログラム
//距離減衰 //kc: 一定減衰率 = 0 //k1: 1次減衰率 = 0 //k2: 2次減衰率 = 1.0 / (lightPos.y * lightPos.y) glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, kc); glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, k1); glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, k2);んで、フラグメントシェーダ側の記述は以下のとおり
varying vec3 P;
varying vec3 N;
void main()
{
//法線やライティング情報を受け取る
vec3 L = gl_LightSource[0].position.xyz - P;
//ライトまでの距離
float d = length(L);
//ライトへの向きベクトルを正規化する
L = normalize(L);
//減衰係数
float attenuation = 1.0 / (gl_LightSource[0].constantAttenuation
+ gl_LightSource[0].linearAttenuation * d
+ gl_LightSource[0].quadraticAttenuation * d * d);
vec3 N = normalize(N);
//アンビエント確定
vec4 ambient = gl_FrontLightProduct[0].ambient;
float dotNL = dot(N, L);
//ディフューズ確定
vec4 diffuse = gl_FrontLightProduct[0].diffuse * max(0.0, dotNL);
vec3 V = normalize(-P);
vec3 H = normalize(L + V);
float powNH = pow(max(dot(N, H), 0.0), gl_FrontMaterial.shininess);
if(dotNL <= 0.0)
{
powNH = 0.0;
}
//スペキュラ確定
vec4 specular = gl_FrontLightProduct[0].specular * powNH;
//カラー値統合
gl_FragColor = ambient + diffuse + specular;
//減衰係数を乗じる
gl_FragColor *= attenuation;
}
まあほとんど教本のまんまなんですが・・・。gl_LightSource[0].constantAttenuationがそれぞれホスト側で設定した減衰係数です。
gl_LightSource[0].linearAttenuation
gl_LightSource[0].quadraticAttenuation
画像の式に当たるのがコメントで減衰係数と書いてあるところ。んで、最後にカラー値を統合したgl_FragColorに減衰係数をかけて明るさを確定してるわけですね。このあたりはレイトレースでやったことがかなり活きてるかんじ。

0 件のコメント:
コメントを投稿