// For Shading Purposes void RT_shade(Ray* ray, int depth) { if (depth <= MAX_DEPTH){ // Color Coefficients Vector4* diffuseCoeff = new Vector4(); Vector4* specularCoeff = new Vector4(); double shininess; // Diffuse and Specular Terms double diffuseTerm[3] = {0.0, 0.0, 0.0}; double specularTerm[3] = {0.0, 0.0, 0.0}; if (ray->intersectedObject == SPHERE) { diffuseCoeff->ReInitialize(spheres[ray->intersectID].color_diffuse); specularCoeff->ReInitialize(spheres[ray->intersectID].color_specular); shininess = spheres[ray->intersectID].shininess; } else if (ray->intersectedObject == TRIANGLE) { // Interpolate diffuse and specular coefficients double alpha, beta; ObtainIntermediateTriangleIntersection(ray->intersectID, ray->intersectPoint, &alpha, &beta); diffuseCoeff->ReInitialize(); InterpolateTriangleProperty(triangles[ray->intersectID].v[0].color_diffuse, triangles[ray->intersectID].v[1].color_diffuse, triangles[ray->intersectID].v[2].color_diffuse, alpha, beta, diffuseCoeff, false); specularCoeff->ReInitialize(); InterpolateTriangleProperty(triangles[ray->intersectID].v[0].color_specular, triangles[ray->intersectID].v[1].color_specular, triangles[ray->intersectID].v[2].color_specular, alpha, beta, specularCoeff, false); // Interpolate shininess if (alpha > 0) { double intermediateShininess = beta * triangles[ray->intersectID].v[2].shininess + (1 - beta) * triangles[ray->intersectID].v[1].shininess; shininess = ((alpha - 1) * triangles[ray->intersectID].v[0].shininess + intermediateShininess) / alpha; } else { shininess = triangles[ray->intersectID].v[0].shininess; } } // Boundary Checking assert(diffuseCoeff->HasNonNegativeEntries()); assert(!diffuseCoeff->HasGreaterThanOneEntries()); assert(specularCoeff->HasNonNegativeEntries()); assert(!specularCoeff->HasGreaterThanOneEntries()); assert(shininess >= 0); // Normal Vector: N Vector4* N = new Vector4(ray->normal); N->ConvertToUnitVector(); // Viewer Direction: V = ray->intersectedPoint - ray->source = -ray->dir Vector4* V = new Vector4(ray->dir); V->Scale(-1); V->ConvertToUnitVector(); int dontCheckObject = NONE; int dontCheckObjectID = NONE; if (ray->intersectedObject == TRIANGLE) { dontCheckObject = ray->intersectedObject; dontCheckObjectID = ray->intersectID; } unsigned int i; for (i = 0; i < num_lights; i++) { // Shoot a ray in the direction of the light Vector4* lightPos = new Vector4(lights[i].position); Ray* checkShadow = new Ray(ray->intersectPoint, lightPos); bool shadow = false; double nearestTIntersect = FindNearestTIntersection(checkShadow,dontCheckObject,dontCheckObjectID); double point2LightDistance = FindDistanceOfIntersectedPointWithLight(ray,i); if (nearestTIntersect != INFINITY && nearestTIntersect< point2LightDistance) { shadow = true; } // Point to Light Vector: L = light_pos - intersectedPoint Vector4* L = new Vector4(lights[i].position); L->Subtraction(ray->intersectPoint); L->ConvertToUnitVector(); // Reflected Ray: R = 2(N.L)N - L Vector4* R = new Vector4(ray->normal); R->Scale(2 * N->DotProduct(L)); R->Subtraction(L); R->ConvertToUnitVector(); // Dot Product of N and L: NL double NL = N->DotProduct(L); if (NL < 0) { NL = 0; } // Dot Product of R and V: RV double RV = R->DotProduct(V); if (RV < 0) { RV = 0; } assert(NL <= 1 && RV <= 1); double attenuationTerm = depth==1?1:1; if (!shadow) { unsigned int j; for (j = 0; j < 3; j++) { diffuseTerm[j] += attenuationTerm * lights[i].color[j] * diffuseCoeff->vector[j] * NL; specularTerm[j] += attenuationTerm * lights[i].color[j] * specularCoeff->vector[j] * pow(RV, shininess); } } delete(L); delete(R); delete(lightPos); delete(checkShadow); } // Adding diffused light Vector4* diffusedColor = new Vector4(diffuseTerm); // //For Debugging Purposes // if(ray->intersectedObject == SPHERE){ // ray->color->Display(); // diffusedColor->Display(); // cout<<"................................................."<<endl; // } ray->color->Addition(diffusedColor); delete(diffusedColor); // Adding specular light Vector4* specularColor = new Vector4(specularTerm); ray->color->Addition(specularColor); delete(specularColor); //R = 2*(NI)N - I ; N = N; I = V = ray->source - ray->IntersectPoint Vector4* R_ = new Vector4(ray->normal); Vector4* I = new Vector4(ray->dir); I->Scale(-1); R_->Scale(2*N->DotProduct(I)); R_->Subtraction(I); Vector4* end = new Vector4(ray->intersectPoint); end->Addition(R_); Ray* reflectedRay = new Ray(ray->intersectPoint, end); delete(R_); delete(I); delete(end); assert(dontCheckObject!=SPHERE); RT_trace(reflectedRay, depth+1, dontCheckObject, dontCheckObjectID); //For Debugging // if(ray->intersectedObject==TRIANGLE/* && ray->intersectPoint->vector[1]<-2*screenX/4 // && ray->intersectPoint->vector[1]>-3*screenX/4*/){ // cout<<ray->intersectID; // cout<<"---->"; // ray->normal->Display(); // cout<<"------>"; // I->Display(); // cout<<I->DotProduct(ray->normal)<<"\t"; // cout<<reflectedRay->dir->DotProduct(ray->normal); // reflectedRay->dir->Display(); // cout<<": "<<reflectedRay->tIntersect<<"\t"; // reflectedRay->color->Display(); // cout<<endl; // } if(reflectedRay->tIntersect!=INFINITY){ reflectedRay->color->Scale(specularCoeff->vector[0], specularCoeff->vector[1], specularCoeff->vector[2]); ray->color->Addition(reflectedRay->color); } delete(reflectedRay); delete(N); delete(V); delete(specularCoeff); delete(diffuseCoeff); } }
double FindNearestTIntersection(Ray* ray, int noCheckObject = NONE, int noCheckID = NONE){ assert((noCheckObject==NONE && noCheckID==NONE) || (noCheckObject==SPHERE && noCheckID>=0 && noCheckID<num_spheres) || (noCheckObject==TRIANGLE && noCheckID>=0 && noCheckID<num_triangles)); int dontCheckSphereID = NONE; int dontCheckTriangleID = NONE; if(noCheckObject==SPHERE){ dontCheckSphereID = noCheckID; } if(noCheckObject==TRIANGLE){ dontCheckTriangleID = noCheckID; } int index1 = NONE; double nearestSphereIntersect = FindNearestTIntersectionWithSphere(ray,&index1, dontCheckSphereID); int index2 = NONE; double nearestTriangleIntersect = FindNearestTIntersectionWithTriangle(ray,&index2, dontCheckTriangleID); // // For Debugging Purposes // printf("[%f,%f]\t",nearestSphereIntersect,nearestTriangleIntersect); int index = NONE; double nearestTIntersect = INFINITY; if (nearestSphereIntersect < nearestTriangleIntersect){ nearestTIntersect = nearestSphereIntersect; index = index1; } else{ nearestTIntersect = nearestTriangleIntersect; index = index2; // // For Debugging Purposes // intersectTriangle[index] = 1; } if (index != NONE) { ray->intersectID = index; ray->tIntersect = nearestTIntersect; // Obtaining Intersection Point = P0 + t*dir ray->intersectPoint->ReInitialize(ray->dir->vector); ray->intersectPoint->Scale(nearestTIntersect); ray->intersectPoint->Addition(ray->source); ray->color->ReInitialize(ambient_light); if (index == index1){ ray->intersectedObject = SPHERE; // Obtaining normal at Intersection Point = intersectPoint - center ray->normal->ReInitialize(spheres[index].position); ray->normal->Scale(-1); ray->normal->Addition(ray->intersectPoint); ray->normal->ConvertToUnitVector(); // Assuming ambient coefficient = diffused coefficient, add ambient light ray->color->Scale(spheres[index].color_diffuse[0], spheres[index].color_diffuse[1], spheres[index].color_diffuse[2]); } else { ray->intersectedObject = TRIANGLE; // Obtaining normal at Intersection Point double alpha = 0.0, beta = 0.0; ObtainIntermediateTriangleIntersection(index, ray->intersectPoint, &alpha, &beta); //printf("\n(%f,%f):%f\n",alpha,beta,ray->tIntersect); InterpolateTriangleProperty(triangles[index].v[0].normal, triangles[index].v[1].normal, triangles[index].v[2].normal, alpha, beta, ray->normal, true); // Assuming ambient coefficient = diffused coefficient, add ambient light Vector4* diffusedCoeff = new Vector4(); InterpolateTriangleProperty(triangles[index].v[0].color_diffuse, triangles[index].v[1].color_diffuse, triangles[index].v[2].color_diffuse, alpha, beta, diffusedCoeff); assert(diffusedCoeff->HasNonNegativeEntries()); ray->color->Scale(diffusedCoeff->vector[0], diffusedCoeff->vector[1], diffusedCoeff->vector[2]); delete(diffusedCoeff); } } return nearestTIntersect; }