home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * (c) 1988 by George Kyriazis
- */
-
- /*
- * here is the shading function
- */
-
- #include "ray.h"
- #include "vector.h"
- #include <math.h>
-
- struct color trace();
- struct intersect intersect();
- struct ray sample_ray();
-
- /*
- * Shadow check. Check if the ray from the intersection point to the
- * light, intersection any objects inbetween. If it does, we have a
- * shadow.
- * One improvement that can be made is to check the transparencies of all
- * the intersecting objects and make the shadow have a different intensity
- * depending on the transparency of the objects
- */
- int shadow(r)
- struct ray r;
- {
- struct intersect i;
- struct ray r2;
- /* to have a shadow, the light ray must intersect an object */
- /* first sample the ray around the shadow ray */
- r2 = sample_ray(r, r.theta);
- i = intersect(r2);
-
- if( i.obj == NULL )
- return FALSE;
- else
- return (r.obj != i.obj);
- }
-
- /*
- * calculate the reflection vector.
- * D. Rogers: "Procedural elements for computer graphics". 5-12. p. 367
- */
- struct vector reflect(n,v1)
- struct vector n, v1;
- {
- struct vector v2;
-
- v2 = vsub( v1, svproduct( 2 * vdot(n, v1), n) );
-
-
- return v2;
- }
-
- /*
- * calculate the refracted vector.
- * D. Rogers: "Procedural elements for computer graphics". 5-12. p. 367
- */
- struct vector refract(n, v1, index)
- struct vector n, v1;
- double index;
- {
- double p, t;
- struct vector v2;
-
- v2.x = 0.; v2.y = 0.; v2.z = 0.;
-
- p = vdot(n, v1);
- if(p < 0) {
- t = 1 - ( 1 - p*p ) / ( index*index );
- if( t <= 0 )
- return v2;
- t = -p/index - sqrt(t);
- } else {
- index = 1 / index;
- t = 1 - ( 1 - p*p ) / ( index*index );
- if( t <= 0 )
- return v2;
- t = -p/index + sqrt(t);
- }
-
- v2 = vadd( svproduct(1/index, v1), svproduct(t, n) );
-
- return v2;
- }
-
- /*
- * the actual shading function. Recursively calls trace()
- */
- struct color shade(i, r, n)
- struct intersect i;
- struct ray r;
- int n; /* recursion level */
- {
- struct color col;
- struct vector pt;
- struct ray shadow_ray;
- struct vector ldir;
- int shad;
- double ldot;
- double spec;
- struct vector rr; /* reflected light direction */
- struct ray reflected, refracted; /* refl, refr directions */
- struct color c;
-
- /* if the recursion level has been exceeded, return peacefully*/
- if(n > MAXLEVEL) {
- col.r = col.g = col.b = 0.;
- return col;
- }
-
- /* initially get the ambient color */
- col = i.obj->ambient;
-
- /* first calculate the intersection point */
- pt = vadd( r.pos, svproduct(i.t, r.dir) );
-
- /* for the light source first get the vector from it to the intersection */
- ldir = norm( vsub(light.org, pt) );
- /* then calc the dot product between the light direction and the normal */
- /* negative because the light direction is reverse (comes from the light) */
- ldot = vdot(i.n, ldir);
- /* and find if that shadow ray is stopped by an object */
- shadow_ray.pos = pt;
- shadow_ray.dir = ldir;
- shadow_ray.obj = i.obj;
- /* the following is the spreading angle of the ray */
- shadow_ray.theta = light.angle;
- shad = shadow(shadow_ray);
- if( (ldot>0) && !shad ) {
- /* statistics */
- shadowline++;
- /* add some diffuse color. */
- col.r += ldot * i.obj->diffuse.r;
- col.g += ldot * i.obj->diffuse.g;
- col.b += ldot * i.obj->diffuse.b;
- /* now calc the specular color */
- /* first calculate the reflected light vector */
- rr = reflect(i.n, ldir);
- /* then take the dot of the reflected ray with the viewing direction */
- /* that is the specular component. The minus is there for obvious reasons */
- spec = vdot(rr, r.dir);
- spec = (spec < 0) ? 0 : spec;
- /* remember the specular width factor? We use it here! */
- spec = pow(spec, i.obj->width);
- col.r += spec * i.obj->specular.r;
- col.g += spec * i.obj->specular.g;
- col.b += spec * i.obj->specular.b;
- }
-
- /* setup the reflected ray */
- reflected.pos = pt;
- reflected.dir = reflect(i.n, r.dir);
- reflected.obj = i.obj;
- reflected.theta = i.obj->refl_diffuse;
- /* calculate the reflection */
- reflectline++;
- c = trace(reflected, n+1);
- col.r += c.r * i.obj->refl_color.r * i.obj->reflection;
- col.g += c.g * i.obj->refl_color.g * i.obj->reflection;
- col.b += c.b * i.obj->refl_color.b * i.obj->reflection;
- /* now setup the refracted ray */
- refracted.pos = pt;
- refracted.dir = refract(i.n, r.dir, i.obj->index);
- refracted.obj = i.obj;
- refracted.theta = i.obj->refr_diffuse;
- if( (refracted.dir.x == 0.) &&
- (refracted.dir.y == 0.) &&
- (refracted.dir.z == 0.) )
- return col;
- /* and calculate the reflection */
- refractline++;
- c = trace(refracted, n+1);
- col.r += c.r * i.obj->refr_color.r * i.obj->refraction;
- col.g += c.g * i.obj->refr_color.g * i.obj->refraction;
- col.b += c.b * i.obj->refr_color.b * i.obj->refraction;
-
- return col;
- }
-