color trace(ray * primary) { if (primary->depth > 0) { VNorm(&primary->d); reset_intersection(primary->intstruct); intersect_objects(primary); return shader(primary); } /* if ray is truncated, return the background as its color */ return primary->scene->background; }
color shader(ray * incident) { color col, diffuse, phongcol; vector N, L, hit; ray shadowray; flt inten, t, Llen; object * obj; int numints, i; point_light * li; numints=closest_intersection(&t, &obj, incident->intstruct); /* find the number of intersections */ /* and return the closest one. */ if (numints < 1) { /* if there weren't any object intersections then return the */ /* background color for the pixel color. */ return incident->scene->background; } if (obj->tex->islight) { /* if the current object is a light, then we */ return obj->tex->col; /* will only use the objects ambient color */ } RAYPNT(hit, (*incident), t) /* find the point of intersection from t */ obj->methods->normal(obj, &hit, incident, &N); /* find the surface normal */ /* execute the object's texture function */ col = obj->tex->texfunc(&hit, obj->tex, incident); diffuse.r = 0.0; diffuse.g = 0.0; diffuse.b = 0.0; phongcol = diffuse; if ((obj->tex->diffuse > 0.0) || (obj->tex->phong > 0.0)) { for (i=0; i<numlights; i++) { /* loop for light contributions */ li=lightlist[i]; /* set li=to the current light */ VSUB(li->ctr, hit, L) /* find the light vector */ /* calculate the distance to the light from the hit point */ Llen = sqrt(L.x*L.x + L.y*L.y + L.z*L.z) + EPSILON; L.x /= Llen; /* normalize the light direction vector */ L.y /= Llen; L.z /= Llen; VDOT(inten, N, L) /* light intensity */ /* add in diffuse lighting for this light if we're facing it */ if (inten > 0.0) { /* test for a shadow */ shadowray.intstruct = incident->intstruct; shadowray.flags = RT_RAY_SHADOW | RT_RAY_BOUNDED; incident->serial++; shadowray.serial = incident->serial; shadowray.mbox = incident->mbox; shadowray.o = hit; shadowray.d = L; shadowray.maxdist = Llen; shadowray.s = hit; shadowray.e = li->ctr; shadowray.scene = incident->scene; reset_intersection(incident->intstruct); intersect_objects(&shadowray); if (!shadow_intersection(incident->intstruct, Llen)) { /* XXX now that opacity is in the code, have to be more careful */ ColorAddS(&diffuse, &li->tex->col, inten); /* phong type specular highlights */ if (obj->tex->phong > 0.0) { flt phongval; phongval = shade_phong(incident, &hit, &N, &L, obj->tex->phongexp); if (obj->tex->phongtype) ColorAddS(&phongcol, &col, phongval); else ColorAddS(&phongcol, &(li->tex->col), phongval); } } } } } ColorScale(&diffuse, obj->tex->diffuse); col.r *= (diffuse.r + obj->tex->ambient); /* do a product of the */ col.g *= (diffuse.g + obj->tex->ambient); /* diffuse intensity with */ col.b *= (diffuse.b + obj->tex->ambient); /* object color + ambient */ if (obj->tex->phong > 0.0) { ColorAccum(&col, &phongcol); } /* spawn reflection rays if necessary */ /* note: this will overwrite the old intersection list */ if (obj->tex->specular > 0.0) { color specol; specol = shade_reflection(incident, &hit, &N, obj->tex->specular); ColorAccum(&col, &specol); } /* spawn transmission rays / refraction */ /* note: this will overwrite the old intersection list */ if (obj->tex->opacity < 1.0) { color transcol; transcol = shade_transmission(incident, &hit, 1.0 - obj->tex->opacity); ColorAccum(&col, &transcol); } return col; /* return the color of the shaded pixel... */ }