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; }
Color basic_shader::Shade( const Scene &scene, const HitInfo &hit ) const { Ray ray; Ray reflectionRay; Ray refractedRay; Ray secondaryRefractedRay; HitInfo otherhit; HitInfo refractionHit; static const double epsilon = 1.0E-6; if( Emitter( hit.object ) ) return hit.object->material->emission; Material *mat = hit.object->material; Color diffuse = mat->diffuse; Color specular = mat->specular; Color color = mat->ambient * diffuse; Vec3 O = hit.ray.origin; Vec3 P = hit.point; Vec3 N = hit.normal; Vec3 E = Unit( O - P ); Vec3 R = Unit( ( 2.0 * ( E * N ) ) * N - E ); Color r = mat->reflectivity; double e = mat->Phong_exp; double k = mat->ref_index; Color t = mat->translucency; if(hit.object->Inside(P)){ P = P + epsilon*N; } if( E * N < 0.0 ) N = -N; // Flip the normal if necessary. //get the attentuation double attenuation; double lightDistance; Vec3 lightVector; double diffuseFactor; double specularFactor; Color diffuseColor = Color(); Color specularColor = Color(); Color finalColor; Color colorWithLighting; Color reflectedColor; Color refractedColor; Vec3 currentR; double shadowFactor = 0; bool objectWasHit = false; int numGridVals = 30; float numSamples = 5; int totalNumGridVals = numGridVals*numGridVals*numSamples; int totalArrayValues = totalNumGridVals*2; float totalGridVals = numGridVals; float currentXvalue; float currentYvalue; float interval = 2.0f/totalGridVals; float currentDist; bool posZinHemisphere,negZinHemisphere; int currentInd1,currentInd2; float randomX,randomY; float currentPosZvalue,currentNegZvalue; //Vec3 currentNormal = Vec3(0.0f,0.0f,1.0f); Vec3 currentNormal = N; float dotProdPosZ,dotProdNegZ,dotProdXYpart; Vec3 positiveZvector; Vec3 negativeZvector; int numLightsHit = 0; /* Surface Area of sphere from each patch P is approximately area(P)*(1/z') where z' is taken at the center This comes from the fact that the surface area is integral_P (1/z) */ float minZvalue=sqrt(interval)*sqrt(2-interval);; //used to calculate surface area float centerXvalue,centerYvalue,centerZvalue,approxSurfaceArea; //temp variable. default emission of the light blocks Color defaultEmission = Color(1.0,1.0,1.0); double emissionFactor = 30.0; Color posZpatchValue = Color(); Color negZpatchValue = Color(); Color posZpatchSpecValue = Color(); Color negZpatchSpecValue = Color(); double radius,patchFormFactor; Vec3 otherNormal; float currentEnergy = 0; for(int xInd = 0; xInd < numGridVals; xInd++){ for(int yInd = 0; yInd < numGridVals; yInd++){ centerXvalue = -1 + interval*xInd + interval*0.5; centerYvalue = -1 + interval*yInd + interval*0.5; currentDist = centerXvalue*centerXvalue + centerYvalue*centerYvalue; centerZvalue = sqrt(1-currentDist); if(centerZvalue < minZvalue){ centerZvalue = minZvalue; } approxSurfaceArea = interval*interval*(1.0f/centerZvalue); posZpatchValue = Color(); negZpatchValue = Color(); for(int sampleInd = 0; sampleInd < numSamples; sampleInd++){ randomX = (double)rand() / RAND_MAX; randomY = (double)rand() / RAND_MAX; currentXvalue = -1+interval*xInd + interval*randomX; currentYvalue = -1+interval*yInd + interval*randomY; currentDist = currentXvalue*currentXvalue + currentYvalue*currentYvalue; posZinHemisphere = false; negZinHemisphere = false; currentInd1 = (xInd*numGridVals + yInd)*numSamples + sampleInd; currentInd2 = currentInd1 + totalNumGridVals; //makes sure it is inside the unit disk if(currentDist <= 1){ currentPosZvalue = sqrt(1-currentDist); currentNegZvalue = -currentPosZvalue; dotProdXYpart = currentNormal.x*currentXvalue + currentNormal.y*currentYvalue; dotProdPosZ = currentNormal.z*currentPosZvalue + dotProdXYpart; dotProdNegZ = currentNormal.z*currentNegZvalue + dotProdXYpart; posZinHemisphere = (dotProdPosZ >=0); negZinHemisphere = (dotProdNegZ >=0); } if(posZinHemisphere){ positiveZvector = Vec3(currentXvalue,currentYvalue,currentPosZvalue); //light ray to case to determine occulsion ray.origin = P; ray.direction = positiveZvector; HitInfo objectHit; objectHit.distance = Infinity; shadowFactor = 1; if(scene.Cast(ray,objectHit) ){ if(objectHit.object != NULL){ Vec3 LightPos = objectHit.point; if(LightPos.z > 12.0){ lightVector = LightPos - P; numLightsHit = numLightsHit + 1; radius = Length(lightVector); otherNormal = Unit(objectHit.normal); lightVector = Unit(lightVector); //this is the current patches approximation of F_ij //patchFormFactor = ((abs(lightVector*currentNormal))*(abs(-1*lightVector*otherNormal)))/(Pi*radius*radius); patchFormFactor = ((lightVector*currentNormal)*(-1*lightVector*otherNormal))/(Pi*radius*radius); patchFormFactor = max(0,patchFormFactor); //printf("radius: %f\n",radius); currentEnergy = currentEnergy + emissionFactor*patchFormFactor; diffuseColor = diffuseColor + GetDiffuseColor(lightVector,N,defaultEmission,diffuse); } } } } if(negZinHemisphere){ negativeZvector = Vec3(currentXvalue,currentYvalue,currentNegZvalue); //printf("(x,y,z)=(%f,%f,%f)\n",gridXvalues[currentInd2],gridYvalues[currentInd2],gridZvalues[currentInd2]); //light ray to case to determine occulsion ray.origin = P; ray.direction = negativeZvector; HitInfo objectHit; objectHit.distance = Infinity; shadowFactor = 1; if(scene.Cast(ray,objectHit) ){ if(objectHit.object != NULL){ Vec3 LightPos = objectHit.point; if(LightPos.z > 12.0){ lightVector = LightPos - P; numLightsHit = numLightsHit + 1; radius = Length(lightVector); otherNormal = Unit(objectHit.normal); lightVector = Unit(lightVector); //this is the current patches approximation of F_ij //patchFormFactor = ((abs(lightVector*currentNormal))*(abs(-1*lightVector*otherNormal)))/(Pi*radius*radius); patchFormFactor = ((lightVector*currentNormal)*(-1*lightVector*otherNormal))/(Pi*radius*radius); patchFormFactor = max(0,patchFormFactor); currentEnergy = currentEnergy + emissionFactor*patchFormFactor; diffuseColor = diffuseColor + GetDiffuseColor(lightVector,N,defaultEmission,diffuse); //negZpatchValue = negZpatchValue + GetDiffuseColor(lightVector,N,defaultEmission,diffuse); } } } } } //diffuseColor = diffuseColor + (posZpatchValue/numSamples)*approxSurfaceArea; //diffuseColor = diffuseColor + (negZpatchValue/numSamples)*approxSurfaceArea; //printf("Approx Surface Area:%f\n",approxSurfaceArea); //diffuseColor = diffuseColor + posZpatchValue; //diffuseColor = diffuseColor + negZpatchValue; if(diffuseColor.blue > 0.5 || diffuseColor.green > 0.5 || diffuseColor.red > 0.5){ //printf("Current Diffuse Color: (%f,%f,%f)\n",diffuseColor.blue,diffuseColor.green,diffuseColor.red); } } } //makes sure to include the light vectors in the calculations for( unsigned i = 0; i < scene.NumLights(); i++ ) { const Object *light = scene.GetLight(i); Color emission = light->material->emission; AABB box = GetBox( *light ); Vec3 LightPos( Center( box ) ); //gets the light Vector lightVector = LightPos - P; lightDistance = Length(lightVector); Vec3 unitLightVector = Unit(lightVector); //gets the attenuation factor attenuation = 1/(attenuation_a + attenuation_b*lightDistance + attenuation_c*lightDistance*lightDistance); float dotProd = currentNormal.x*unitLightVector.x + currentNormal.y*unitLightVector.y + currentNormal.z*unitLightVector.z; //light vector in unit hemipshere if(dotProd >= 0){ //light ray to case to determine occulsion ray.origin = P; ray.direction = unitLightVector; HitInfo objectHit; objectHit.distance = Infinity; if(scene.Cast(ray,objectHit) ){ if(objectHit.object != NULL){ Vec3 LightPos = objectHit.point; if(LightPos.z > 12.0){ numLightsHit = numLightsHit + 1; lightVector = LightPos - P; //diffuseColor = diffuseColor + GetDiffuseColor(lightVector,N,defaultEmission,diffuse); radius = Length(lightVector); otherNormal = Unit(objectHit.normal); lightVector = Unit(lightVector); //this is the current patches approximation of F_ij //patchFormFactor = ((abs(lightVector*currentNormal))*(abs(-1*lightVector*otherNormal)))/(Pi*radius*radius); patchFormFactor = ((lightVector*currentNormal)*(-1*lightVector*otherNormal))/(Pi*radius*radius); patchFormFactor = max(0,patchFormFactor); currentEnergy = currentEnergy + emissionFactor*patchFormFactor; diffuseColor = diffuseColor + GetDiffuseColor(lightVector,N,defaultEmission,diffuse); } } } } } diffuseColor = currentEnergy*defaultEmission; //diffuseColor = diffuseColor/12.0; float numLights = numLightsHit; //diffuseColor = diffuseColor/(numLights*Pi); if(numLightsHit > 1){ //printf("Number of Lights Hit:%d\n",numLightsHit); //printf("Original Color: (%f,%f,%f)\n",diffuse.blue,diffuse.green,diffuse.red); //printf("Diffuse Color: (%f,%f,%f)\n\n",diffuseColor.blue,diffuseColor.green,diffuseColor.red); } //colorWithLighting = color + diffuseColor*diffuse + specularColor*specular; //colorWithLighting = diffuseColor*diffuse; colorWithLighting = diffuseColor*diffuse + diffuse*0.4; //set variables for reflection reflectionRay.origin = P; reflectionRay.direction = R; reflectionRay.generation = hit.ray.generation + 1; reflectedColor = Color(); //set variables for refraction refractedRay.origin = P-epsilon*N; Vec3 refractionDir = RefractionDirection(1.0,k,E,N); refractedRay.direction = refractionDir; //for refraction refractedRay.generation = hit.ray.generation + 1; refractedColor = Color(); refractionHit.distance = Infinity; //only do refraction if the transluency is greater than zero // this is an optimization so unnecessary refractions are not calculated if( (t.red + t.green + t.blue) > epsilon){ if(scene.Cast(refractedRay,refractionHit)){ bool insideMaterial = false; Vec3 currentNormal; Vec3 previousRefractedDirection; do{ currentNormal = Unit(refractionHit.normal); previousRefractedDirection = refractedRay.direction; refractedRay.direction = RefractionDirection(k,1.0,-1*refractedRay.direction,-1*currentNormal); if(Length(refractedRay.direction) < epsilon){ insideMaterial = true; refractionHit.distance = Infinity; refractedRay.origin = refractionHit.point - epsilon*currentNormal; refractedRay.direction = Unit( ( 2.0 * ( previousRefractedDirection * currentNormal ) ) * (-1*currentNormal) + previousRefractedDirection ); if(!scene.Cast(refractedRay,refractionHit)){ insideMaterial = false; } }else{ refractedRay.origin = refractionHit.point + epsilon*currentNormal; insideMaterial = false; } }while(insideMaterial); refractedRay.generation = hit.ray.generation + 1; //now do refraction refractedColor = scene.Trace(refractedRay); } } //do the reflection //only do reflection if the reflectance is greater than zero // this is an optimization so unnecessary reflections are not calculated if( (r.red + r.green + r.blue) > epsilon){ reflectedColor = scene.Trace(reflectionRay); } //printf("diffuseColor: (%f,%f,%f)\n",colorWithLighting.red,colorWithLighting.green,colorWithLighting.blue); //now combine calculated color with reflected color //finalColor = (-1*t + Color(1.0,1.0,1.0))*(colorWithLighting + r*reflectedColor) + t*refractedColor; return colorWithLighting; //return finalColor; }