
ОСНОВЫ МЕТОДА ТРАССИРОВКИ ЛУЧЕЙ
152
Vector Shade ( Medium& CurMed, double Weight, Vector& p, Vector& View, GObject * Obj
)
{
SurfaceData txt;
Ray ray;
Vector Color;
Vector l; // light vector
double Sh; // light shadow coeff.
Vector h; // vector between View and light vector
double ln, vn;
int Entering = 1; // flag whether we're entering or
leaving object
Obj > FindTexture ( p, txt );
if ( ( vn = View & txt.n ) > 0 ) // force ( View, n ) > 0
{
txt.n = txt.n;
vn = vn;
Entering = 0;
}
ray.Org = p; // since all rays will be cast from here
Color = Ambient * txt.Color * txt.Ka; // get ambient light
for ( int i = 0; i < Scene > LightsCount; i++ )
if ( ( Sh = Scene > Light [i] > Shadow ( p, l ) ) > Threshold )
if ( ( ln = l & txt.n ) > Threshold ) // if light is visible
{
if ( txt.Kd > Threshold ) // compute direct diffuse light
Color += Scene > Light [i] > Color * txt.Color * ( txt.Kd
* Sh * ln );
if ( txt.Ks > Threshold ) // compute direct specular light,
via Phong shading
{ // compute halfvector between View and l
h = Normalize ( l View );
Color += Scene > Light [i] > Color * ( txt.Ks *
Sh * pow ( txt.n & h, txt.p));
}
}
doublerWeight = Weight * txt.Kr; // weight of reflected ray
doubletWeight = Weight * txt.Kt; // weight of transmitted ray
// check for reflected ray
if ( rWeight > Threshold && Level < MaxLevel )
{
ray.Dir = View txt.n * ( 2 * vn ); // get reflected ray direction
Color += txt.Kr * Trace ( CurMed, rWeight, ray );
}
// check for transmitted ray
if ( tWeight > Threshold && Level < MaxLevel )
{ // relative index of refraction
doubleEta = CurMed.nRefr / ( Entering ? txt.Med.nRefr : Air.nRefr );
doubleci = vn; // cosine of incident angle
doublectSq = 1 + Eta*Eta*( ci*ci 1 ); // squared cosine of transm. angle
if ( ctSq > Threshold ) // not a Total Internal Reflection
{
ray.Dir = View * Eta + txt.n * ( Eta*ci sqrt ( ctSq ) );
if ( Entering ) // ray enters object ( txt.Med )
Color += txt.Kr * Trace ( txt.Med, tWeight, ray );
else // ray leaves object ( Air )
Color += txt.Kr * Trace ( Air, tWeight, ray );
}