Color refraction_shader::Shade( const Scene &scene, const HitInfo &hit ) const{ if(gen >= max_depth) return scene.envmap->Shade(hit.ray); if( mat->emission != black ) if (_ray.type == indirect_ray) //turnign off the light return black; else return mat->emission; //this si direct sample, so return illum of the light if(mat->reflectivity != black && _ray.type == indirect_ray) return black; Vec3 O = _ray.origin; Vec3 P = hit.point; Vec3 N = hit.normal; Vec3 E = Unit( O - P ); Vec3 R = Unit( ( 2.0 * ( E * N ) ) * N - E ); if( E * N < 0.0 ) N = -N; //flip the normal to make it point into the space of the ray origin if(mat->translucency != black ){ Ray rr = obj->getRefracetedRay(_ray,P,N); if(rr.direction!=Vec3(0,0,0)) return scene.Trace(rr)*mat->translucency + scene.Trace(obj->getReflectedRay(_ray,P,N))*(white-mat->translucency); else return black;//this is TIR even after 4 level of internal reflections } unsigned k = 1,n = 1; if(gen == 1 ){ // rays of tree depth = 1 n = numDirectRays; k = numIndirectRays; } Color color = mat->diffuse * mat->ambient; Sample *dSamples = new Sample[n*n]; unsigned numSamples; HitInfo dHit; Ray dRay,iRay; unsigned Y = scene.NumLights() ; for( unsigned i = 0; i < Y; i++ ){ const Object *light = scene.GetLight(i); numSamples = light->GetSamples (hit.point, hit.normal, dSamples, n); //#pragma omp parallel for for(unsigned j=0;j<numSamples ;j++){ dRay.origin = hit.point + Unit(N)*10E-4; dRay.direction = Unit( dSamples[j].P - hit.point ); dRay.generation = gen + 1; //next level in tree dHit.ray = dRay; dHit.distance = Infinity; dRay.type = _ray.type; if(scene.Cast(dRay,dHit)) if( dHit.object == light){ color += max( 0, dRay.direction*Unit(N) )* mat->diffuse* light->material->emission*dSamples[j].w/Pi; if( mat->Phong_exp !=0 && mat->specular != black) //this si handling specularity color += (white-mat->reflectivity)* pow( max( dRay.direction*R,0), mat->Phong_exp) * mat->specular*light->material->emission*dSamples[j].w; } else if(dHit.object->material->translucency != black){ //hit a tranclusive surface, so cast the transmitted ray Ray rr = dHit.object->getRefracetedRay(dRay,dHit.point, dHit.normal); HitInfo rrHit; rrHit.distance = Infinity; rrHit.ray = rr; if(scene.Cast(rr,rrHit)) if(rrHit.object == light) color += max( 0, dRay.direction*Unit(N) )* mat->diffuse* light->material->emission*dSamples[j].w/Pi; if( mat->Phong_exp !=0 && mat->specular != black) color += (white-mat->reflectivity)* pow( max( dRay.direction*R,0), mat->Phong_exp) * mat->specular*light->material->emission*dSamples[j].w; } } } if(mat->reflectivity == black){ //sample hmisphere (stratified) if(max_depth > 2){ Sample* iSamples = new Sample[k*k]; numSamples = SampleProjectedHemisphere (hit.point, hit.normal, iSamples, k); //#pragma omp parallel for for(unsigned j = 0; j < numSamples ;j++){ iRay.origin = hit.point + Unit(N)*10E-4; iRay.from = obj; iRay.direction = Unit( hit.point - iSamples[j].P ); iRay.generation = gen+ 1; iRay.type = indirect_ray; color += (mat->diffuse*iSamples[j].w*scene.Trace(iRay))/TwoPi; } delete [] iSamples; iSamples = NULL; } } else{ Ray rr; rr.origin = P+ N*10E-4; rr.direction = R; rr.from = obj; rr.ignore = NULL; rr.generation = gen+1; color = color*(white - mat->reflectivity); color += mat->reflectivity*scene.Trace(rr); } delete [] dSamples; dSamples = NULL; return color; }
// Shade assigns a color to a point on a surface, as it is seen // from another point. The coordinates of these points, the normal // of the surface, and the surface material are all recorded in the // HitInfo structure. The shader will typically make calls to Trace // to handle shadows and reflections. Color Raytracer::Shade(const HitInfo &hit, const Scene &scene, int max_tree_depth) { Color color = { 0.0f, 0.0f, 0.0f }; Vec3 point = hit.geom.point + hit.geom.normal*Epsilon; HitInfo hitObstacle = hit; Ray ray, ray2; Color diffuse = Color(0,0,0), specular = Color(0,0,0); Color direct = Color(0,0,0), indirect = Color(0,0,0); Sample lightPoint; Vec3 V; Color irradiant = Color(0,0,0); int espec = 0; Color indirect_hemisphere = Color(0, 0, 0), indirect_lobe = Color(0, 0, 0); //if (max_tree_depth >= 0) { if (hit.material.Emitter()) { return hit.material.m_Diffuse; }else{ for (Object *object = scene.first; object != NULL; object = object->next) { if (object->material.Emitter() == true) { lightPoint = object->GetSample(hit.geom.point, hit.geom.normal); ray.origin = hit.geom.point; //lightPoint.P = lightPoint.P + hit.geom.normal*Epsilon; ray.direction = Unit(lightPoint.P - hit.geom.point); hitObstacle.geom.distance = Length(lightPoint.P - point); V = Unit(hit.geom.origin - hit.geom.point); Vec3 N = (hit.geom.normal); Vec3 H = Unit(V + ray.direction); //V = Unit(hit.geom.origin - hit.geom.point); Vec3 L = (-ray.direction);// Unit(point - lightPoint.P); Vec3 R = Unit(Reflection(-L, N));//Unit((2*N*(N*L))-L); espec = hit.material.m_Phong_exp; double c = (L*H); double g = sqrt((pow(1.4 / 1, 2.0))+ pow(c,2)-1); Color f0 = hit.material.m_Specular; double F = (f0.red + (1.0 - f0.red, 1.0 - f0.green, 1.0 - f0.blue)*(pow((1 - (N*V)), 5)), f0.green + (1.0 - f0.red, 1.0 - f0.green, 1.0 - f0.blue)*(pow((1 - (N*V)), 5)), f0.blue+(1.0 - f0.red, 1.0 - f0.green, 1.0 - f0.blue)*(pow((1 - (N*V)), 5))); //double F = (1 / 2)*((pow(g - c, 2))/(pow(g + c, 2)))*(1+pow((c*(g+c)-1),2)/ (1 + pow((c*(g - c) + 1), 2))); double D = ((espec + 2) / (2 * Pi))*(pow((H*N), espec)); //double D = 1/(sqrt(2*Pi)) double G = min(min(1.0, (2 * (N*H)*(N*V)) / (V*H)), (2 * (N*H)*(N*L)) / (L*H)); if (G < 0) G = 0; if (D < 0) D = 0; if (F < 0) F = 0; if (!Cast(ray, scene, hitObstacle)) { if (N * L > 0) { diffuse = (N*L)*hit.material.m_Diffuse/Pi; } else { diffuse = Color(0.0, 0.0, 0.0); } irradiant = object->material.m_Emission*(lightPoint.w); if ((R*V) > 0 && hit.material.m_Phong_exp > 0) { specular = /*(espec + 2)/(2*Pi) * pow((R*V), espec)*/(F*D*G / (4 * (N*L)*(N*V)))*hit.material.m_Specular; } else { specular = Color(0.0, 0.0, 0.0); } direct += (diffuse + specular)*irradiant; } } } if (hit.material.m_Phong_exp > 0) { Vec3 N = (hit.geom.normal); Vec3 L = Unit(-ray.direction); V = -Unit(hit.geom.point - hit.geom.origin); Vec3 R = Unit(Reflection(-V, N)); Vec3 H = Unit(V + ray.direction); double c = (L*H); double g = sqrt((pow(1.4 / 1, 2.0)) + pow(c, 2) - 1); Color f0 = hit.material.m_Specular; double F = (f0.red + (1.0 - f0.red, 1.0 - f0.green, 1.0 - f0.blue)*(pow((1 - (N*V)), 5)), f0.green + (1.0 - f0.red, 1.0 - f0.green, 1.0 - f0.blue)*(pow((1 - (N*V)), 5)), f0.blue + (1.0 - f0.red, 1.0 - f0.green, 1.0 - f0.blue)*(pow((1 - (N*V)), 5))); //double F = (1 / 2)*((pow(g - c, 2))/(pow(g + c, 2)))*(1+pow((c*(g+c)-1),2)/ (1 + pow((c*(g - c) + 1), 2))); double D = ((espec + 2) / (2 * Pi))*(pow((H*N), espec)); double G = min(min(1.0, (2 * (N*H)*(N*V)) / (V*H)), (2 * (N*H)*(N*L)) / (L*H)); if (G < 0) G = 0; if (D < 0) D = 0; if (F < 0) F = 0; float phong_exp = hit.material.m_Phong_exp; ray2.origin = point; Sample sample_hemisphere = SampleProjectedHemisphere(N); ray2.direction = Unit(sample_hemisphere.P); //ray2.no_emitters = true; indirect_hemisphere = Trace(ray2, scene, max_tree_depth-1)* hit.material.m_Diffuse; Sample specular_sample = SampleSpecularLobe(R, phong_exp); ray2.direction = Unit(specular_sample.P); indirect_lobe = Trace(ray2, scene, max_tree_depth - 1)*F*D*G / (4 * (N*L)*(N*V));// *hit.material.m_Specular; indirect = indirect_hemisphere + indirect_lobe;// *(F*D*G / (4 * (N*L)*(N*V))); } return (direct) + indirect; } //} }