ある地点における光の強さは、光源までの距離を 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 件のコメント:
コメントを投稿