|
シェーディングとは、3次元で光を表現する技術のことで、物体の「陰」の処理を行います。 要するに、面に光があたると面の色が明るくなって、逆に光があたらないと暗くなる処理のことです。 つまり物体からの反射光の演出を行います。 空を見上げて、「今日も太陽がまぶしいぜ」ってことではありません。 どうすれば良いか? まず、面の法線ベクトルを求めます。 法線ベクトルは面に垂直なベクトルのことです。 んで、この法線ベクトルを正規化します。(長さを1にする) 次に光線ベクトルを設定します。 今回は視点の位置と同じにしました。 ちなみに光の減衰処理は行っていません。 んで、この光線ベクトルもまた正規化します。(長さを1にする) 正規化の式はこんな感じ。 a=sqrt(nx*nx+ny*ny+nz*nz); nx/=a; ny/=a; nz/=a; 求めた法線ベクトルと光線ベクトルの内積を求めます。 ちなみにどちらも正規化しているので、その内積の値がそのままcosθの値になります。 あとは内積の値を元に、面の色を設定すれば出来あがりです。 ![]() 「面に当たる光の強さは、正規化された光線ベクトルと法線ベクトルの内積」 ということを覚えましょう。 θが0のとき、内積(=cosθ)が1で光の強さは最大。 θが90のとき、内積(=cosθ)が0で光はまったく当たらないということになります。 ----------------------------------------------------------------
//-----------------------------------------------------------------------------
// フラットシェーディング
//-----------------------------------------------------------------------------
void flatshadeing(struct shape_type p,struct men_type *men,struct vector eye)
{
vertex_type *v0,*v1,*v2;
v0=&p.vertex[men->index[0]];
v1=&p.vertex[men->index[1]];
v2=&p.vertex[men->index[2]];
//面の法線を計算
men->vector.x= (v1->wy - v0->wy)*(v2->wz - v0->wz)-
(v1->wz - v0->wz)*(v2->wy - v0->wy);
men->vector.y= (v1->wz - v0->wz)*(v2->wx - v0->wx)-
(v1->wx - v0->wx)*(v2->wz - v0->wz);
men->vector.z= (v1->wx - v0->wx)*(v2->wy - v0->wy)-
(v1->wy - v0->wy)*(v2->wx - v0->wx);
//視線ベクトルを単位行列化
Normalize(eye);
//面の法線を単位行列化
Normalize(men->vector);
//内積を求める
float naiseki = men->vector.x * eye.x+
men->vector.y * eye.y+
men->vector.z * eye.z;
//内積イコォルcosθ
float cosSITA = naiseki;
//面の色を設定
men->R = (unsigned int)( (men->tempR+1)*(cosSITA));
if(men->R >31)men->R=31;
if(men->R < 0)men->R=0;
men->G = (unsigned int)( (men->tempG+1)*(cosSITA));
if(men->G >31)men->G=31;
if(men->G < 0)men->G=0;
men->B = (unsigned int)( (men->tempB+1)*(cosSITA));
if(men->B >31)men->B=31;
if(men->B < 0)men->B=0;
}
----------------------------------------------------------------------↑マウスでドラッグしてみてください。 面が正面を向くと明るくなります。 flat_cube.zip[33kb] |