/* in is the direction of the incoming ray and d is the recusive depth */ void shade(point* p, vector* n, material* m, vector* in, color* c, lightNode* lightList, int d) { double distToIntersect, distToLight; vector toLightVector; vector nDummy;material* mDummy; point offsetP; ray toLightRay; point intersectPoint; GLfloat nDotHi, liDotN; /* ambient component of color */ c->r = m->amb * m->r; c->g = m->amb * m->g; c->b = m->amb * m->b; vector nIn; nIn.x = -in->x; nIn.y = -in->y; nIn.z = -in->z; nIn.w = in->w; color reflectLight; reflectLight.r = 0.0; reflectLight.g = 0.0; reflectLight.b = 0.0; /* Diffuse Lighting */ lightNode* aLight; aLight = lightList->next; while(aLight != NULL){ calculateDirection(p, aLight->theLight->p, &toLightVector); normalize(&toLightVector); offsetP.x = p->x + toLightVector.x*0.0001; offsetP.y = p->y + toLightVector.y*0.0001; offsetP.z = p->z + toLightVector.z*0.0001; toLightRay.dir = &toLightVector; toLightRay.start = &offsetP; distToLight = sqrt(pow((offsetP.x-aLight->theLight->p->x),2)+pow((offsetP.y-aLight->theLight->p->y),2)+pow((offsetP.z-aLight->theLight->p->z),2)); firstHit(&toLightRay,&intersectPoint,&nDummy,&mDummy,&distToIntersect); if((intersectPoint.w == 0.0) || (intersectPoint.w == 1.0 && distToIntersect > distToLight)){ liDotN = dot(&toLightVector,n); if(liDotN > 0.0){ // Diffuse Lighting c->r += m->kd * aLight->theLight->c->r * liDotN * m->r; c->g += m->kd * aLight->theLight->c->g * liDotN * m->g; c->b += m->kd * aLight->theLight->c->b * liDotN * m->b; // For Specular Highlights vector Hi; Hi.x = toLightVector.x + nIn.x; Hi.y = toLightVector.y + nIn.y; Hi.z = toLightVector.z + nIn.z; normalize(&Hi); nDotHi = dot(n,&Hi); if(nDotHi > 0.0){ reflectLight.r += pow(nDotHi,m->ns) * aLight->theLight->c->r; reflectLight.g += pow(nDotHi,m->ns) * aLight->theLight->c->g; reflectLight.b += pow(nDotHi,m->ns) * aLight->theLight->c->b; } } } aLight = aLight->next; } /* Specular */ c->r += m->kss * reflectLight.r; c->g += m->kss * reflectLight.g; c->b += m->kss * reflectLight.b; /* Reflections */ vector rv; normalize(n); normalize(&nIn); GLfloat nDotV = 2.0*dot(n,&nIn); rv.x = (nDotV*n->x); rv.y = (nDotV*n->y); rv.z = (nDotV*n->z); rv.x -= nIn.x; rv.y -= nIn.y; rv.z -= nIn.z; rv.w = 0.0; normalize(&rv); offsetP.x = p->x + rv.x*0.0001; offsetP.y = p->y + rv.y*0.0001; offsetP.z = p->z + rv.z*0.0001; offsetP.w = 1.0; ray newRay; newRay.dir = &rv; newRay.start = &offsetP; color traceColor; if(m->ksr > 0.0){ traceColor = traceRay(&newRay,d-1); c->r += m->ksr*traceColor.r; c->g += m->ksr*traceColor.g; c->b += m->ksr*traceColor.b; } /* Refractions */ offsetP.x = p->x + in->x*0.0001; offsetP.y = p->y + in->y*0.0001; offsetP.z = p->z + in->z*0.0001; newRay.dir = in; newRay.start = &offsetP; if(m->kr > 0.0){ traceColor = traceRay(&newRay,--d); c->r += m->kr*traceColor.r; c->g += m->kr*traceColor.g; c->b += m->kr*traceColor.b; } /* clamp color values to 1.0 */ if (c->r > 1.0) c->r = 1.0; if (c->g > 1.0) c->g = 1.0; if (c->b > 1.0) c->b = 1.0; }
/* returns the color seen by ray r in parameter c */ void traceRay(ray* r, color* c, int depth) { GLdouble product_nv; point p; /* first intersection point */ point direction; /* direction */ vector v; /* unit vector in the direction of viewpoint */ vector n; /* normal vector at point of intersection */ ray flec; /* reflected ray */ ray frac; /* refracted ray */ color cflec; color cfrac; material* m; /* material of object intersected */ if ( depth == 0) { return; } else { p.w = 0.0; /* initialize to "no intersection" */ firstHit(r,&p,&n,&m); if (p.w != 0.0) { /* p is finite intersection point */ /* compute v in the direction of incoming ray */ calculateDirection(&p,r->start,&direction); v.x = direction.x / length(&direction); v.y = direction.y / length(&direction); v.z = direction.z / length(&direction); /* do the lighting for current intersection point */ shade(&p,&n,&v,m,c,lights,lnum); /* COMPUTE REFLECTION RAY AND ITS INTENSITY */ cflec.r = 0.0; cflec.g = 0.0; cflec.b = 0.0; if ( m->Krefl > 0.0 ) { flec.start = &p; product_nv = dotproduct(&n,&v); if (product_nv > 0.01) { flec.end = makePoint( 2.0 * product_nv * n.x - v.x, 2.0 * product_nv * n.y - v.y, 2.0 * product_nv * n.z - v.z ); traceRay(&flec, &cflec, depth-1); } } /* COMPUTE REFRACTION RAY AND ITS INTENSITY */ cfrac.r = 0.0; cfrac.g = 0.0; cfrac.b = 0.0; if ( m->a > 0.0 ) { frac.start = &p; frac.end = r->end; traceRay(&frac, &cfrac, depth-1); } c->r = (1 - m->Krefl - m->a) * c->r + m->Krefl * cflec.r + m->a * cfrac.r; c->g = (1 - m->Krefl - m->a) * c->g + m->Krefl * cflec.g + m->a * cfrac.b; c->b = (1 - m->Krefl - m->a) * c->b + m->Krefl * cflec.b + m->a * cfrac.g; /* clamp color values to 1.0 */ if (c->r > 1.0) c->r = 1.0; if (c->g > 1.0) c->g = 1.0; if (c->b > 1.0) c->b = 1.0; } } }
/* in is the direction of the incoming ray and d is the recusive depth */ void shade(point* p, vector* n, material* m, vector* in, color* c, int d) { /* so far, just finds ambient component of color */ c->r = m->amb * m->r * (1-m->a); c->g = m->amb * m->g * (1-m->a); c->b = m->amb * m->b * (1-m->a); for(unsigned i = 0; i < lights.size(); i++) { lighting* light = lights[i]; vector* li = (vector*)makePoint(light->p->x - p->x, light->p->y - p->y, light->p->z - p->z); normalize(li); GLfloat dot = dotProduct(li,n); vector* rm = (vector*)makePoint(2*dot*n->x - li->x, 2*dot*n->y - li->y, 2*dot*n->z - li->z); vector* v = (vector*)makePoint(-p->x, -p->y, -p->z); normalize(v); GLfloat specDot = dotProduct(rm, v); point n_p; /* next intersection point */ vector n_n; material* n_m; ray r; r.start = p; r.dir = li; n_p.w = 0.0; /* inialize to "no intersection" */ firstHit(&r,&n_p,&n_n,&n_m); if(n_p.w == 0.0) { if(dot > 0) { c->r += m->diff * light->c->r * dot; c->g += m->diff * light->c->g * dot; c->b += m->diff * light->c->b * dot; } if(specDot > 0) { specDot = pow(specDot, 16); c->r += m->spec * light->c->r * specDot; c->g += m->spec * light->c->g * specDot; c->b += m->spec * light->c->b * specDot; } } freePoint(li); freePoint(rm); freePoint(v); } if(d > 0) { color n_c; vector* in_r = (vector*)makePoint(-in->x, -in->y, -in->z); normalize(in_r); GLfloat dot = dotProduct(n,in_r); vector* ref = (vector*)makePoint(2*dot*n->x - in_r->x, 2*dot*n->y - in_r->y, 2*dot*n->z - in_r->z); point n_p; /* next intersection point */ vector n_n; material* n_m; ray r; r.start = p; r.dir = ref; n_p.w = 0.0; /* inialize to "no intersection" */ firstHit(&r,&n_p,&n_n,&n_m); //reflection if (n_p.w != 0.0) { shade(&n_p,&n_n,n_m,ref,&n_c,d-1); c->r += (d/(double)RAYDEPTH) * m->spec * n_c.r; c->g += (d/(double)RAYDEPTH) * m->spec * n_c.g; c->b += (d/(double)RAYDEPTH) * m->spec * n_c.b; } //refraction n_p.w = 0.0; r.dir = in; firstHit(&r, &n_p, &n_n, &n_m); if (n_p.w != 0.0) { shade(&n_p,&n_n,n_m,in,&n_c,d-1); c->r += (d/(double)RAYDEPTH) * m->a * n_c.r; c->g += (d/(double)RAYDEPTH) * m->a * n_c.g; c->b += (d/(double)RAYDEPTH) * m->a * n_c.b; } freePoint(in_r); freePoint(ref); } /* clamp color values to 1.0 */ if (c->r > 1.0) c->r = 1.0; if (c->g > 1.0) c->g = 1.0; if (c->b > 1.0) c->b = 1.0; }