課題03で作成したプログラムを, 以下の方法で陰影付けを行うよう変更します.
環境光に対する反射係数 Ka, 物体表面の拡散反射係数 Kd, 物体表面の法線ベクトル N, 光線ベクトル L, 光源の強度 Il, 環境光の強度 Ia から,完全拡散反射面における反射光強度 I を求める関数 shade() を作成し,render() の前に置いてください.
void shade(const float *l, const float *n,
const struct Material *k, float *i)
{
/*
** 光線ベクトル L,物体表面の法線ベクトル N,
** 環境光に対する反射係数 Ka,
** 物体表面の拡散反射係数 Kd,
** 光源の強度 Il,環境光の強度 Ia から,
** 完全拡散反射面における反射光強度 I を求める
*/
}
Ka および Kd は,それぞれ Material
という構造体の変数 red の a と d
という要素に格納するものとします.
したがって関数 shade() は,Material
という構造体のポインタを引数として受け取り,
それを介して Ka および Kd
を取り出すようにします.
struct Material {
float a[3]; /* 環境光に対する反射係数 Ka */
float d[3]; /* 物体表面の拡散反射係数 Kd */
};
struct Material red = {
{ 0.5, 0.1, 0.1 },
{ 0.5, 0.1, 0.1 },
};
また,これらの材質パラメータを物体のデータと結びつけるために, 構造体 Sphere の要素に構造体 Material を指すポインタの要素 k を追加し,それを red のポインタで初期化しておきます.
struct Sphere {
float p[3]; /* 球の中心位置 Pc */
float r; /* 球の半径 r */
struct Material *k;
};
struct Sphere sphere = {
{ 0.0, 0.0, 4.0 },
2.0,
&red,
};
L および Il は,それぞれ Light という構造体の変数 light の p と i という要素に格納するものとします.また Ia は ia という配列変数に格納するものとします.
struct Light {
float p[3]; /* 光線ベクトル L */
float i[3]; /* 光源の強度 Il */
};
struct Light light = {
{ 0.424, 0.566, -0.707 },
{ 1.0, 1.0, 1.0 },
};
float ia[] = { 0.2, 0.2, 0.2 }; /* 環境光の強度 Ia */
この関数 shade() を用いて, 以下の条件で反射光強度 I を求め, これをその画素における色 c に用いて画像を生成してください.
ちなみに (0.424, 0.566, -0.707) ≒ (3, 4, -5) / |(3, 4, -5)|
関数 shade() に視線ベクトル V, 物体表面の鏡面反射係数 Ks およびハイライトの広がり(輝き係数)Ke を与えて, 鏡面反射成分を含んだ反射光強度 I を求めるよう修正してください.
void shade(const float *l, const float *n, const float *v,
const struct Material *k, float *i)
{
/*
** 光線ベクトル L,物体表面の法線ベクトル N,
** 視線ベクトル V,
** 環境光に対する反射係数 Ka,
** 物体表面の拡散反射係数 Kd,
** 物体表面の鏡面反射係数 Ks,
** ハイライトの広がり(輝き係数)Ke,
** 光源の強度 Il,環境光の強度 Ia から,
** 完全拡散反射面における反射光強度 I を求める
*/
}
Ks および Ke は,構造体 Material の要素に s と e を追加し,この構造体の変数 red のそれぞれの要素に格納するものとします.
struct Material {
float a[3]; /* 環境光に対する反射係数 Ka */
float d[3]; /* 物体表面の拡散反射係数 Kd */
float s[3]; /* 物体表面の鏡面反射係数 Ks */
float e; /* ハイライトの広がり */
};
struct Material red = {
{ 0.5, 0.1, 0.1 },
{ 0.5, 0.1, 0.1 },
{ 0.4, 0.4, 0.4 },
40.0,
};
修正した関数 shade() を用いて, 以下の条件で反射光強度 I を求め, これをその画素における色 c に用いて画像を生成してください.
光線ベクトル L を光源の位置 Pl と交点の位置 P から求めて, 点光源による陰影付けを行ってください.
Pl は構造体 Light の変数 light の要素 p に格納するものとします.
struct Light {
float p[3]; /* 光線の位置 Pl */
float i[3]; /* 光源の強度 Il */
};
struct Light light = {
{ 3.0, 4.0, -5.0 },
{ 1.0, 1.0, 1.0 },
};
修正した関数 shade() を用いて, 以下の条件で反射光強度 I を求め, これをその画素における色 c に用いて画像を生成してください.
点光源の場合, 照射点に届く入射光の密度は光源と照射点の間の距離の2乗に反比例します. 画像が暗すぎる場合は光源の強度を調整するか, あるいは(邪道ですが,OpenGL なんかでもやっている) 入射光の密度を光源と照射点の間の距離(の1乗)に反比例するようにしたり, 距離に依存しないようにしてみてください.