void DisplayClass::traceRay(glm::vec3* color, int depth, glm::vec3 P, glm::vec3 V, float currentRI, float oldRI, glm::vec3 lcol) { if (depth > 5) { color->x = rayAmbientCol->x; color->y = rayAmbientCol->y; color->z = rayAmbientCol->z; return; } Node* n = getIntersectionObject(P, V); if (n == NULL) { color->x = rayAmbientCol->x; color->y = rayAmbientCol->y; color->z = rayAmbientCol->z; return; } //find intersection glm::vec3 intersection = P + (((float) *n->t) * V); //get material float* mt; switch(*n->mtl) { case 1: mt = mtl1; break; case 2: mt = mtl2; break; case 3: mt = mtl3; break; case 4: mt = mtlf; break; } glm::vec3 N = glm::normalize(*n->normal); //compute normal at intersection point //if (N.x < 0.0001f && N.x > -0.0001f && N.y < 0.0001f && N.y > -0.0001f && N.z < 1.0001f && N.z > 0.9999f) { // std::cout << "Noisy!" << std::endl; //} glm::vec3 Rd = glm::normalize(glm::reflect(V, N)); //compute reflected ray direction float RI = mt[6]; glm::vec3 Rfn = N; //if reflective, make recursive call glm::vec3 spec(0.0f, 0.0f, 0.0f); if (mt[4] > 0.0f) { glm::vec3* reflectedColor = new glm::vec3(); traceRay(reflectedColor, depth + 1, intersection + 0.001f * Rd, Rd, currentRI, oldRI, glm::vec3(lcol.x * mt[0], lcol.y * mt[1], lcol.z * mt[2])); spec = *reflectedColor; delete reflectedColor; } glm::vec3 refr(0.0f, 0.0f, 0.0f); glm::vec3 Rf; glm::vec3 tcol; float insFl = -1.0f; if (mt[5] > 0.0f) { insFl = glm::dot(N, V); tcol = glm::vec3(lcol.x * mt[0], lcol.y * mt[1], lcol.z * mt[2]); if (insFl > -0.0001f) { Rfn = -1.0f * N; //tcol = lcol; //RI = 1.0f; } if (currentRI == 1.0f) { oldRI = RI; } float eta = currentRI/oldRI; Rf = glm::normalize(glm::refract(V, Rfn, eta)); glm::vec3* refractedColor = new glm::vec3(); traceRay(refractedColor, depth + 1, intersection + 0.001f * Rf, Rf, oldRI, currentRI, glm::vec3(lcol.x * mt[0], lcol.y * mt[1], lcol.z * mt[2])); refr = *refractedColor; delete refractedColor; } //ambient color color->x = rayAmbientCol->x * mt[0]; color->y = rayAmbientCol->y * mt[1]; color->z = rayAmbientCol->z * mt[2]; //*color = *color * 0.2f; *color = glm::clamp(*color, 0.0f, 1.0f); if (mt[5] > 0.0f) { *color = *color + refr; *color = ((1.0f - mt[4]) * glm::clamp(*color, 0.0f, 1.0f)) + (mt[4] * glm::clamp(spec, 0.0f, 1.0f)); /*float cosT = glm::dot(Rf, V); //2.0f * glm::dot(-1.0f * Rfn, V); float rcoef = glm::clamp(pow(1.0f - cosT, 5), 0.0f, 1.0f); *color = glm::clamp(((1.0f - rcoef) * *color) + (rcoef * tcol), 0.0f, 1.0f);*/ return; } //light ray glm::vec3 L; glm::vec3 R; glm::vec3 finalCol; glm::vec3 ambientCol = *color; glm::vec3 totalCol(0.0f, 0.0f, 0.0f); for (int lc = 0; lc < 3; lc++) { L = glm::normalize(*rayLightPos->at(lc) - intersection); R = glm::reflect(-1.0f * L, N); //cast ray for shadow glm::vec3 blockob; Node* blocker = getIntersectionObject(*rayLightPos->at(lc), -1.0f * L); if (blocker != NULL) { blockob = *rayLightPos->at(lc) - (((float) *blocker->t) * L); } float di = glm::length(blockob - intersection); //if not shadowed, add more color if (blocker == NULL || (di < 0.0001f && di > -0.0001f)) { //diffuse color glm::vec3 diffuseColor = glm::clamp(glm::vec3(mt[0] * rayLightCol->at(lc)->x, mt[1] * rayLightCol->at(lc)->y, mt[2] * rayLightCol->at(lc)->z), 0.0f, 1.0f); //specular term float specTerm = glm::clamp(pow(glm::dot(V, R), mt[3]), 0.0f, 1.0f); //diffuse term float diffuseTerm = glm::clamp(glm::dot(N, L), 0.0f, 1.0f); //final color weighted calculation //blinn-phong finalCol = ambientCol + (glm::clamp(diffuseTerm * diffuseColor, 0.0f, 1.0f) * 0.6f) + (glm::clamp(spec + specTerm * *rayLightCol->at(lc), 0.0f, 1.0f) * 0.2f); totalCol = totalCol + finalCol; *color = totalCol; } } //reflectivity-weighted *color = ((1.0f - mt[4]) * glm::clamp(*color, 0.0f, 1.0f)) + (mt[4] * glm::clamp(spec, 0.0f, 1.0f)); }
void Raytracer::render( int width, int height, Point3D eye, Vector3D view, Vector3D up, double fov, const char* fileName ) { /*****************anti-aliasing************************/ Matrix4x4 viewToWorld; _scrWidth = width; _scrHeight = height; double factor = (double(height)/2)/tan(fov*M_PI/360.0); Colour totalCol(0.0,0.0,0.0); initPixelBuffer(); viewToWorld = initInvViewMatrix(eye, view, up); scfCache(_root); // Construct a ray for each pixel. for (int i = 0; i < _scrHeight; i++) { for (int j = 0; j < _scrWidth; j++) { //anti-aliasing, each pixel can have 4 rays, the pixel color determined by the avgerage for(double a = i; a < i+1 ; a += 0.5){ for(double b = j; b < j+1;b += 0.5){ // Sets up ray origin and direction in view space, // image plane is at z = -1. Point3D origin(0, 0, 0); Point3D imagePlane; imagePlane[0] = (-double(width)/2 + 0.5 + b)/factor; imagePlane[1] = (-double(height)/2 + 0.5 + a)/factor; imagePlane[2] = -1; // TODO: Convert ray to world space and call // shadeRay(ray) to generate pixel colour. Point3D originW = viewToWorld * imagePlane; Vector3D directionW = viewToWorld * (imagePlane -origin); directionW.normalize(); Ray3D ray(originW, directionW); Colour col = shadeRay(ray,0,0); //each ray contributed 0.25 color to the final rending color for the pixel _rbuffer[i*width+j] += int(col[0]*255*0.25); _gbuffer[i*width+j] += int(col[1]*255*0.25); _bbuffer[i*width+j] += int(col[2]*255*0.25); } } } } /********************anti-aliasing**************************/ // Matrix4x4 viewToWorld; // _scrWidth = width; // _scrHeight = height; // double factor = (double(height)/2)/tan(fov*M_PI/360.0); // // initPixelBuffer(); // viewToWorld = initInvViewMatrix(eye, view, up); // scfCache(_root); // // Construct a ray for each pixel. // for (int i = 0; i < _scrHeight; i++) { // for (int j = 0; j < _scrWidth; j++) { // // Sets up ray origin and direction in view space, // // image plane is at z = -1. // Point3D origin(0, 0, 0); // Point3D imagePlane; // imagePlane[0] = (-double(width)/2 + 0.5 + j)/factor; // imagePlane[1] = (-double(height)/2 + 0.5 + i)/factor; // imagePlane[2] = -1; // // // TODO: Convert ray to world space and call // // shadeRay(ray) to generate pixel colour. // // //Vector3D dir = imagePlane-origin; // Ray3D ray(origin,imagePlane-origin); // /*my dode here*/ // ray.origin = viewToWorld*ray.origin; // ray.dir = viewToWorld*ray.dir; // ray.dir.normalize(); // Colour col = shadeRay(ray,0,0);//the original is shadeRay(ray) // // _rbuffer[i*width+j] = int(col[0]*255); // _gbuffer[i*width+j] = int(col[1]*255); // _bbuffer[i*width+j] = int(col[2]*255); // } // } flushPixelBuffer(fileName); }