color scalar_volume_texture(vector * hit, texture * tex, ray * ry) { color col, col2; box * bx; flt a, tx1, tx2, ty1, ty2, tz1, tz2; flt tnear, tfar; flt t, tdist, dt, sum, tt; vector pnt, bln; scalarvol * vol; flt scalar, transval; int x, y, z; unsigned char * ptr; bx=(box *) tex->obj; vol=(scalarvol *)bx->tex->img; col.r=0.0; col.g=0.0; col.b=0.0; tnear= -FHUGE; tfar= FHUGE; if (ry->d.x == 0.0) { if ((ry->o.x < bx->min.x) || (ry->o.x > bx->max.x)) return col; } else { tx1 = (bx->min.x - ry->o.x) / ry->d.x; tx2 = (bx->max.x - ry->o.x) / ry->d.x; if (tx1 > tx2) { a=tx1; tx1=tx2; tx2=a; } if (tx1 > tnear) tnear=tx1; if (tx2 < tfar) tfar=tx2; } if (tnear > tfar) return col; if (tfar < 0.0) return col; if (ry->d.y == 0.0) { if ((ry->o.y < bx->min.y) || (ry->o.y > bx->max.y)) return col; } else { ty1 = (bx->min.y - ry->o.y) / ry->d.y; ty2 = (bx->max.y - ry->o.y) / ry->d.y; if (ty1 > ty2) { a=ty1; ty1=ty2; ty2=a; } if (ty1 > tnear) tnear=ty1; if (ty2 < tfar) tfar=ty2; } if (tnear > tfar) return col; if (tfar < 0.0) return col; if (ry->d.z == 0.0) { if ((ry->o.z < bx->min.z) || (ry->o.z > bx->max.z)) return col; } else { tz1 = (bx->min.z - ry->o.z) / ry->d.z; tz2 = (bx->max.z - ry->o.z) / ry->d.z; if (tz1 > tz2) { a=tz1; tz1=tz2; tz2=a; } if (tz1 > tnear) tnear=tz1; if (tz2 < tfar) tfar=tz2; } if (tnear > tfar) return col; if (tfar < 0.0) return col; if (tnear < 0.0) tnear=0.0; tdist=sqrt((flt) (vol->xres*vol->xres + vol->yres*vol->yres + vol->zres*vol->zres)); tt = (vol->opacity / tdist); bln.x=fabs(bx->min.x - bx->max.x); bln.y=fabs(bx->min.y - bx->max.y); bln.z=fabs(bx->min.z - bx->max.z); dt=sqrt(bln.x*bln.x + bln.y*bln.y + bln.z*bln.z) / tdist; sum=0.0; /* move the volume residency check out of loop.. */ if (!vol->loaded) { LoadVol(vol); vol->loaded=1; } for (t=tnear; t<=tfar; t+=dt) { pnt.x=((ry->o.x + (ry->d.x * t)) - bx->min.x) / bln.x; pnt.y=((ry->o.y + (ry->d.y * t)) - bx->min.y) / bln.y; pnt.z=((ry->o.z + (ry->d.z * t)) - bx->min.z) / bln.z; x=(int) ((vol->xres - 1.5) * pnt.x + 0.5); y=(int) ((vol->yres - 1.5) * pnt.y + 0.5); z=(int) ((vol->zres - 1.5) * pnt.z + 0.5); ptr = vol->data + ((vol->xres * vol->yres * z) + (vol->xres * y) + x); scalar = (flt) ((flt) 1.0 * ((int) ptr[0])) / 255.0; sum += tt * scalar; transval = tt * scalar; col2 = VoxelColor(scalar); if (sum < 1.0) { col.r += transval * col2.r; col.g += transval * col2.g; col.b += transval * col2.b; if (sum < 0.0) sum=0.0; } else { sum=1.0; } } if (sum < 1.0) { /* spawn transmission rays / refraction */ color transcol; transcol = shade_transmission(ry, hit, 1.0 - sum); col.r += transcol.r; /* add the transmitted ray */ col.g += transcol.g; /* to the diffuse and */ col.b += transcol.b; /* transmission total.. */ } return col; }
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... */ }