Color World::runPhotonCache(vec origin, vec direction) const { HitInfo eyeInfo; objects->hit(&eyeInfo, origin, direction); if (!eyeInfo.hit) return Color(0,0,0); Color initc = eyeInfo.mat->getColor(); Color accum; for (int d = 0; d < depth; d++) { HitInfo newI; newI.follow(eyeInfo); vec newDirection = eyeInfo.mat->sample(eyeInfo.incoming, eyeInfo.normal); objects->hit(&newI, eyeInfo.location, newDirection); if (newI.hit) { Color newc = initc * eyeInfo.mat->getColor() * Color(1.0, 1.0, 1.0) * eyeInfo.mat->sampledPdf(eyeInfo.incoming, newDirection, eyeInfo.normal); accum += newc * pc->seenValue(eyeInfo.location, newI.location, &newI, sampleRadius) * (1.0 / depth); } } return accum; }
void BeginRender() { Color24 *temp; temp = renderImage.GetPixels(); float *zBuffer = renderImage.GetZBuffer(); Color materialColor; Color24 newColor; for (int i = 0; i < camera.imgWidth; i++) { for (int j = 0; j < camera.imgHeight; j++) { Ray currentRay = ComputeCameraRay(i, j); HitInfo hInfo; hInfo.Init(); bool value = TraceRay(currentRay, hInfo, &rootNode); if (value) { hInfo.node->FromNodeCoords(hInfo); const Material *m = hInfo.node->GetMaterial(); materialColor = m->Shade(currentRay, hInfo, lights); temp[camera.imgWidth*j + i].r = (materialColor.r)*255; temp[camera.imgWidth*j + i].g = (materialColor.g)*255; temp[camera.imgWidth*j + i].b = (materialColor.b)*255; } else { temp[camera.imgWidth*j + i].r = 0; temp[camera.imgWidth*j + i].g = 0; temp[camera.imgWidth*j + i].b = 0; } zBuffer[camera.imgWidth*j + i] = hInfo.z; } } renderImage.ComputeZBufferImage(); renderImage.SaveImage("Output"); }
ColorTimeCache World::runTimePhotonCache(vec origin, vec direction) const { ColorTimeCache ctc; HitInfo eyeInfo; objects->hit(&eyeInfo, origin, direction); if (!eyeInfo.hit) return ctc; Color initc = eyeInfo.mat->getColor(); for (int d = 0; d < depth; d++) { HitInfo newI; newI.follow(eyeInfo); vec newDirection = eyeInfo.mat->sample(eyeInfo.incoming, eyeInfo.normal); objects->hit(&newI, eyeInfo.location, newDirection); if (newI.hit) { Color newc = initc * eyeInfo.mat->getColor() * (1.0/depth) * eyeInfo.mat->sampledPdf(eyeInfo.incoming, newDirection, eyeInfo.normal); ctc.addWeighted(newI.distance + eyeInfo.distance, newc, pc->seenTimeValue(eyeInfo.location, newI.location, &newI, sampleRadius)); } } return ctc; }
void BeginRender() { cout<<"\nBeginning Render..."; float alpha = camera.fov; float l = 1.0; float h = l * tan(alpha/2.0 *(M_PI/180)); float aspectRatio = (float)camera.imgWidth/camera.imgHeight; float s = aspectRatio * h; float dx = (2 * s)/camera.imgWidth; float dy = -(2 * h)/camera.imgHeight; float dxx = dx/2,dyy=dy/2; Point3 K(-s,h,-l); K.x += dxx; K.y += dyy; for(int i = 0; i< camera.imgHeight; i++){ for(int j = 0; j<camera.imgWidth; j++){ K.x += dx; Matrix3 RotMat; Point3 dvec = camera.dir - camera.pos; Point3 svec = camera.up.Cross(dvec); dvec.Normalize(); svec.Normalize(); camera.up.Normalize(); RotMat.Set(svec,camera.up, dvec); Ray r(camera.pos, K); r.dir=r.dir*RotMat; r.dir.Normalize(); HitInfo hInfo; hInfo.Init(); if(rootNode.GetNumChild()>0){ // for(int k=0; k < rootNode.GetNumChild(); ++k){ // RayTrace(rootNode.GetChild(k),r,i * camera.imgWidth + j); // } if(RayTrace_2(r, hInfo)) { renderImage.PutPixel(i *camera.imgWidth+j, white, hInfo.z); } else renderImage.PutPixel(i *camera.imgWidth+j, black, BIGFLOAT); } } K.x = -s; K.x += dxx; K.y += dy; } cout<<"Render Complete"<<endl; renderImage.ComputeZBufferImage(); renderImage.SaveZImage("/Users/varunk/Desktop/RayTracerProj1/RayTracerProj1/zbuffer.ppm"); renderImage.SaveImage("/Users/varunk/Desktop/RayTracerProj1/RayTracerProj1/renderimage.ppm"); }
float GenLight::Shadow(Ray ray, float t_max) { HitInfo hInfo; hInfo.Init(); hInfo.z = t_max; if (TraceRay(&rootNode, ray, hInfo, HIT_FRONT)) return 0.0f; return 1.0f; }
void Renderer::calculatePixelColor(Node &i_rootNode, LightList &i_lightList, int offsetAlongWidth, int offsetAlongHeight) { HitInfo hitInfo; Color noHitPixelColor = { 0,0,0 }; Color finalColor = { 0,0,0 }; RandomSampler sampler = RandomSampler(MIN_SAMPLE_COUNT, MAX_SAMPLE_COUNT, MIN_VARIANCE, MAX_VARIANCE); while (sampler.needMoreSamples()) { sampler.generateSamples(offsetAlongWidth, offsetAlongHeight); for (int k = 0; k < sampler.getSampleBucketSize(); ++k) { hitInfo.Init(); Ray sampleRay = sampler.getSampleRay(k); if (TraceRay(&i_rootNode, sampleRay, hitInfo)) { finalColor = hitInfo.node->GetMaterial()->Shade(sampleRay, hitInfo, i_lightList, REFLECTION_BOUNCE_COUNT, GI_BOUNCE_COUNT); /*finalColor.r = pow(finalColor.r, 1/2.2); finalColor.g = pow(finalColor.g, 1/2.2); finalColor.b = pow(finalColor.b, 1/2.2);*/ sampler.setSampleColor(k, finalColor); sampler.setIsSampleHit(k, true); } else { sampler.setSampleColor(k, background.Sample(sampleRay.dir)); } sampler.setHitInfo(k, hitInfo); } } Color tempColor = sampler.getAveragedSampleListColor(); tempColor.r = pow(tempColor.r, 1 / 2.2); tempColor.g = pow(tempColor.g, 1 / 2.2); tempColor.b = pow(tempColor.b, 1 / 2.2); float depth = sampler.getAveragedDepth(); int sampleCount = sampler.getSampleBucketSize(); int pixel = offsetAlongHeight * imageWidth + offsetAlongWidth; TCHAR* mutexName = __T("WritingMutex"); static HANDLE mutexHandle = NULL; if( mutexHandle == NULL ) mutexHandle = OpenMutex(MUTEX_ALL_ACCESS, FALSE, mutexName); DWORD dSuccess = WaitForSingleObject(mutexHandle, INFINITE); assert(dSuccess == WAIT_OBJECT_0); renderingImage[pixel] = tempColor; operationCountImage[pixel] = Color(1.0f,0.0f,0.0f) * static_cast<float>(hitInfo.operationCount/BIGFLOAT); zBufferImage[pixel] = depth; sampleCountImage[pixel] = sampleCount; bool bSuccess = ReleaseMutex(mutexHandle); assert(bSuccess == true); sampler.resetSampler(); }
bool RayTrace(HitInfo &hitInfo, Node* curnode, Ray ray, int PixIndex) { Node* node = curnode; bool hitTest = false; const Object *obj = node->GetObject(); ray = curnode->ToNodeCoords(ray); if(obj){ // cout<<"Transforming to..."<<endl; HitInfo tempHitInfo; tempHitInfo.Init(); tempHitInfo.node = node; tempHitInfo.z = hitInfo.z; hitTest = obj->IntersectRay(ray, tempHitInfo); node->FromNodeCoords(tempHitInfo); if(hitTest && tempHitInfo.z < hitInfo.z){ hitInfo = tempHitInfo; //cout<<hitInfo.z<<endl; } //else hitTest=false; } if(node->GetNumChild()>0) { //cout<<"Children "<<node->GetNumChild()<<endl; for(int i=0;i<curnode->GetNumChild();++i) { // cout<<"Child "<<i<<endl; node = curnode->GetChild(i); HitInfo temp; temp.Init(); temp = hitInfo; if(RayTrace(hitInfo, node, ray, PixIndex)){ curnode->FromNodeCoords(hitInfo); // cout<<"Transforming from "<<curnode->GetNumChild()<<endl; if(temp.z > hitInfo.z) hitTest = true; else{ // hitInfo = temp; hitTest = false; continue; } } } } if(hitTest) return true; else return false; }
const Vector3 Lambert::shade(const unsigned int threadID, const Ray& ray, const HitInfo &hit, const Scene& scene, bool isSecondary) const { Vector3 L = Vector3(0.0f, 0.0f, 0.0f); Vector3 rayD = Vector3(ray.d[0],ray.d[1],ray.d[2]); // Ray direction Vector3 viewDir = -rayD; // View direction float u, v; Vector3 N, geoN, T, BT; Vector3 diffuseColor = m_kd; Vector3 P = ray.getPoint(hit.t); hit.getAllInfos(N, geoN, T, BT, u, v); if (m_colorMap != NULL) { Vector4 texCol = m_colorMap->getLookup(u, v); diffuseColor = Vector3(texCol.x, texCol.y, texCol.z); } const Lights *lightlist = scene.lights(); // loop over all of the lights Lights::const_iterator lightIter; for (lightIter = lightlist->begin(); lightIter != lightlist->end(); lightIter++) { float discard; Vector3 lightPower = (*lightIter)->sampleLight(threadID, P, N, ray.time, scene, 0, discard); L += lightPower * diffuseColor; // Calculate Diffuse component } // add the ambient component L += m_ka; return L; }
void doRender(void* arg){ RenderParams rarg = *((RenderParams *)arg); //cout<<"Do render...."<<endl; bool pixelHit=false; HitInfo hitInfo; hitInfo.Init(); Point2 pixLoc = rarg.pixLocation; Ray r = rarg.ray; int PixIndex = rarg.pixIndex; Color shade(255,255,255); if(rootNode.GetNumChild()>0){ if(RayTrace_2(r, hitInfo)) { pixelHit=true; // cout<<"Shading...."<<endl; shade = hitInfo.node->GetMaterial()->Shade(r, hitInfo, lights, 5); } renderImage.PutPixel(PixIndex, shade, hitInfo.z); } if(!pixelHit){ renderImage.PutPixel(PixIndex, black, BIGFLOAT); } // RenderParams renderArg = giveMeAPixelToRender(); // if(renderArg.renderComplete != 1){ // doRender(&renderArg); // } // }
Color MtlBlinn::Shade(const Ray &ray, const HitInfo &hInfo, const LightList &lights, int bounceCount) const{ float bias = BIAS_SHADING; Color shade; Color rShade = Color(0,0,0); Color tShade = Color(0,0,0); const Material *mat; mat = hInfo.node->GetMaterial(); const MtlBlinn* mb =static_cast<const MtlBlinn*>(mat); // cout<<"HInfo front: "<<hInfo.front<<endl; /* local copy */ Point3 P; P.Set(hInfo.p.x,hInfo.p.y,hInfo.p.z); Ray iRay = ray; Color ambInt = mb->diffuse; Color allOther = Color(0,0,0); Color diffuse = mb->diffuse;; Color ambComponent = Color(0,0,0); for ( unsigned int i=0; i<lights.size(); i++ ) { if(lights[i]->IsAmbient()){ // cout<<"ambient "<<endl; Color intensity = lights[i]->Illuminate(hInfo.p); ambComponent += (ambInt * intensity); continue; } else{ // cout<<"other lighting "<<endl; Point3 L = -lights[i]->Direction(P); L.Normalize(); Point3 V = ray.p - P; V.Normalize(); Point3 LplusV = L + V; Point3 H = (L+V)/LplusV.Length(); H.Normalize(); float alpha = mb->glossiness; Point3 N = hInfo.N; float S = H.Dot(N); S = pow(S,alpha); float costheta = L.Dot(N)/(L.Length() * N.Length()); Color intensity = lights[i]->Illuminate(P); // cout<<"costheta "<<endl; allOther += intensity * (costheta>0?costheta:0) * (diffuse + S * (mb->specular)) ; } /* finally add inta*cola + intall*costheta*(cold + s* colS)*/ shade = ambComponent + allOther; } /* Calculate refraction */ if(refraction.Grey()>0 && bounceCount>0){ Color reflShade = Color(0,0,0); float R0, Refl = 0.0f, Trans = 0.0f; HitInfo temp; temp.Init(); Point3 N = hInfo.N; // Point3 V = Point3(iRay.p.x - hInfo.p.x, iRay.p.y - hInfo.p.y, iRay.p.z - hInfo.p.z); Point3 V = Point3(hInfo.p.x - iRay.p.x, hInfo.p.y - iRay.p.y, hInfo.p.z - iRay.p.z); V.Normalize(); float n1 = 1, n2 = 1; if(hInfo.front){ /* Hitting from outside */ // temp.front = false; n2 = ior; // cout<<"outside "<<endl; } else if(!hInfo.front){ /* Transmission from the inside */ // temp.front = true; n1 = ior; // cout<<"intside... "<<endl; N = -hInfo.N; } float ratio_n = n1 / n2; float costheta_v = -V.Dot(N); /* refer: http://graphics.stanford.edu/courses/cs148-10-summer/docs/2006--degreve--reflection_refraction.pdf */ float sin2theta_t = ratio_n * ratio_n * (1 - costheta_v * costheta_v); Point3 T = ratio_n * V + (ratio_n * costheta_v - sqrtf(1 - sin2theta_t)) * N ; // cout<<ratio_n<<" "<<"cos_v "<<costheta_v<<" sin2theta_t "<<sin2theta_t<<endl; Ray tRay = Ray(hInfo.p,T); //tRay.dir.Normalize(); tRay.p.x = tRay.p.x + bias *tRay.dir.x; /* add bias */ tRay.p.y = tRay.p.y + bias *tRay.dir.y; tRay.p.z = tRay.p.z + bias *tRay.dir.z; // cout<<"B temp front: "<< temp.front<<endl; if(sin2theta_t <= 1){ if(RayTrace_2(tRay, temp)){ // bounceCount--; // cout<<"A temp front: "<< temp.front<<endl; tShade = temp.node->GetMaterial()->Shade(tRay,temp,lights,bounceCount); tShade.r *= exp(-absorption.r * temp.z); tShade.g *= exp(-absorption.g * temp.z); tShade.b *= exp(-absorption.b * temp.z); // shade = tShade; /* remove later */ // return shade; /* Calculate Schlick's approximation */ R0 = (n1 - n2)/(n1 + n2); R0 *= R0; double X = 0.0; // if(n1 > n2){ // X = 1.0 - sqrtf(1.0 - sin2theta_t); // } // else{ X = 1.0 - costheta_v; } X = 1.0 - costheta_v; Refl = R0 + (1.0 - R0) * X * X * X * X * X; Trans = 1.0 - Refl; } } else {/* Total internal reflection */ Refl = 1.0f; } /* Calculate reflection due to reflectance */ if(bounceCount >0){ N = hInfo.N; Point3 V = Point3(iRay.p.x - P.x, iRay.p.y - P.y, iRay.p.z - P.z); //V.Normalize(); Point3 VR = 2 * V.Dot(N) * N - V; //VR.Normalize(); Ray rRay = Ray(P, VR); //rRay.dir.Normalize(); rRay.p.x = rRay.p.x + bias *rRay.dir.x; rRay.p.y = rRay.p.y + bias *rRay.dir.y; rRay.p.z = rRay.p.z + bias *rRay.dir.z; HitInfo temp1; temp1.Init(); if(rootNode.GetNumChild()>0){ if(RayTrace_2(rRay, temp1)){ bounceCount --; reflShade = temp1.node->GetMaterial()->Shade(rRay, temp1, lights, bounceCount); } } } // cout<<"Refl: "<<Refl<<"Trans "<<Trans<<endl; tShade = refraction * (Trans * tShade + Refl * reflShade); } /* calculate reflection*/ if(reflection.Grey()>0 && bounceCount > 0){ Point3 N = hInfo.N; Point3 V = Point3(iRay.p.x - P.x, iRay.p.y - P.y, iRay.p.z - P.z); // V.Normalize(); Point3 VR = 2 * V.Dot(N) * N - V; Ray rRay = Ray(hInfo.p, VR); //rRay.dir.Normalize(); rRay.p.x = rRay.p.x + bias *rRay.dir.x; rRay.p.y = rRay.p.y + bias *rRay.dir.y; rRay.p.z = rRay.p.z + bias *rRay.dir.z; HitInfo temp; temp.Init(); if(rootNode.GetNumChild()>0){ if(RayTrace_2(rRay, temp)){ bounceCount--; rShade = reflection * temp.node->GetMaterial()->Shade(rRay, temp, lights, bounceCount); } } } /* Add shade with reflected and refracted colors */ shade += (rShade + tShade); return shade; };
Color World::runBiDi(vec origin, vec direction) const { Thing *emitter = emitters[Random::upto(emitters.size())]; std::vector<Color> cumEmtWeight; std::vector<HitInfo> emtHits; std::vector<Color> cumEyeWeight; std::vector<HitInfo> eyeHits; std::vector<int> todo; cumEmtWeight.reserve(depth); emtHits.reserve(depth); cumEyeWeight.reserve(depth); eyeHits.reserve(depth); todo.reserve(depth); HitInfo emtInfo; vec emtN; vec source; source = emitter->randomSurfacePoint(emtN); emtInfo.hit = true; emtInfo.incoming = emtN; emtInfo.normal = emtN; emtInfo.location = source; emtInfo.mat = emitter->getMaterial(); cumEmtWeight.push_back(emitter->getMaterial()->getColor()); emtHits.push_back(emtInfo); bool done = false; for (int d = 1; d < depth && !done; d++) { HitInfo newI; newI.follow(emtHits[d-1]); vec newDirection = emtHits[d-1].mat->sample(emtHits[d-1].incoming, emtHits[d-1].normal); objects->hit(&newI, emtHits[d-1].location, newDirection); cumEmtWeight.push_back(emtHits[d-1].mat->combineColor( cumEmtWeight[d-1] * emtHits[d-1].mat->sampledPdf( emtHits[d-1].incoming, newDirection, emtHits[d-1].normal))); if (newI.hit) emtHits.push_back(newI); else done = true; } HitInfo eyeInfo; objects->hit(&eyeInfo, origin, direction); done = false; if (!eyeInfo.hit) return Color(0,0,0); cumEyeWeight.push_back(eyeInfo.mat->getColor()); eyeHits.push_back(eyeInfo); /*for (int d = 1; d < depth && !done; d++) { HitInfo newI; newI.follow(eyeHits[d-1]); vec newDirection = eyeHits[d-1].mat->sample(eyeHits[d-1].incoming, eyeHits[d-1].normal); objects->hit(&newI, eyeHits[d-1].location, newDirection); cumEyeWeight.push_back(eyeHits[d-1].mat->combineColor( cumEyeWeight[d-1] * eyeHits[d-1].mat->sampledPdf( eyeHits[d-1].incoming, newDirection, eyeHits[d-1].normal))); if (newI.hit) eyeHits.push_back(newI); else done = true; }*/ for (int d = 1; d < depth && !todo.empty(); d++) { HitInfo newI; int index = todo.back(); todo.pop_back(); newI.follow(eyeHits[index]); vec newDirection = eyeHits[index].mat->sample(eyeHits[index].incoming, eyeHits[index].normal); objects->hit(&newI, eyeHits[index].location, newDirection); if (newI.hit) { Color newc = eyeHits[index].mat->combineColor( cumEyeWeight[index] * eyeHits[index].mat->sampledPdf( eyeHits[index].incoming, newDirection, eyeHits[index].normal)); int ints = 1;//newc.intensity() * 5 + 1; for (int x=0; x<ints; x++) todo.push_back(eyeHits.size()); eyeHits.push_back(newI); cumEyeWeight.push_back(newc * (1.0/ints)); } else done = true; } Color accum; for (int x=0; x<emtHits.size(); x++) for (int y=0; y<eyeHits.size(); y++) { vec dir = eyeHits[y].location - emtHits[x].location; double dist = dir.magnitude(); dir.normalize(); HitInfo inf; inf.distanceOnly = true; inf.distance = dist; objects->hit(&inf, emtHits[x].location, dir); if (inf.distance >= dist - EPSILON || !inf.hit) { //hit accum += cumEyeWeight[y] * cumEmtWeight[x] * eyeHits[y].mat->pdf(eyeHits[y].incoming, dir * -1, eyeHits[y].normal) * emtHits[x].mat->pdf(emtHits[x].incoming, dir, emtHits[x].normal); } } return accum; /*if (eyeInfo.hit) { vec newn; vec dtl = eyeInfo.location - emitter->randomSurfacePoint(newn); return emitter->getMaterial()->getColor() * eyeInfo.mat->pdf(direction*-1, dtl, eyeInfo.normal); } else return Color(0,0,0);*/ }
Colour SceneNode::get_colour(Point3D origin, Vector3D dir, const Colour& ambient, const Colour& bg, const std::list<Light*>& lights, int num_glossy_rays, int limit) { HitInfo info = intersects(origin, dir); if (!info.empty() && limit > 0) { Hit closest = info.get_closest(); Material* close_mat = closest.material; Colour c(0.0, 0.0, 0.0); for (std::list<Light*>::const_iterator it = lights.begin(); it != lights.end(); ++it) { Vector3D shadow_ray = (*it)->position - closest.intersection; HitInfo shadow_info = intersects(closest.intersection, shadow_ray); closest = close_mat->apply_material(-dir, *it, closest); if (!shadow_info.empty()) { std::vector<Hit> all_hits = shadow_info.get_all_hits(); int num_translucent = 0; Colour shadow(0.0, 0.0, 0.0); for (unsigned int i = 0; i < all_hits.size(); i++) { Hit h = all_hits.at(i); if (!h.in_shadow) { if (num_translucent == 0) { shadow = shadow + closest.diffuse; num_translucent = 1; } break; } else { if ((h.material)->get_transparency() > 0.0) { shadow = shadow + (h.material)->get_transparency() * closest.diffuse; num_translucent++; } else { num_translucent = 0; break; } } } if (num_translucent > 0) { c = c + (1.0 / num_translucent) * shadow; c = c + closest.specular; } } else { c = c + closest.diffuse; c = c + closest.specular; } } if ((closest.material)->should_reflect()) { Vector3D V = dir, N = closest.normal; V.normalize(); N.normalize(); Vector3D reflected = V - (2 * V.dot(N) * N); Colour r = get_colour(closest.intersection, reflected, ambient, bg, lights, num_glossy_rays, limit - 1); if (num_glossy_rays > 0) { Vector3D w = reflected; w.normalize(); Vector3D u = w.cross(Vector3D(1.0, 0.0, 0.0)); u.normalize(); Vector3D v = w.cross(Vector3D(0.0, 1.0, 0.0)); v.normalize(); for (int i = 0; i < num_glossy_rays; i++) { double dx = 0.0; double dy = 0.0; while (dx == 0.0 && dy == 0.0) { dx = ((double)(rand() % 100) / 100.0) * 0.125; dy = ((double)(rand() % 100) / 100.0) * 0.125; } Vector3D refi = reflected + dx * u + dy * v; if (refi.dot(closest.normal) < 0) { refi = -refi; } Colour ri = get_colour(closest.intersection, refi, ambient, bg, lights, num_glossy_rays, limit - 1); r = r + ri; } r = (double) (1.0 / (num_glossy_rays + 1)) * r; } c = 0.7 * c + 0.3 * close_mat->get_reflect(r); } Vector3D refracted; if (close_mat->should_refract() && close_mat->get_transmit_ray(refracted, dir, closest)) { Colour refr = get_colour(closest.intersection, refracted, ambient, bg, lights, num_glossy_rays, limit + 1); c = c + close_mat->get_transparency() * refr; } c = c + (1.0 - close_mat->get_transparency()) * close_mat->get_ambient(ambient); return c; } else { return bg; } }
void PhotonTracer::traceSinglePhoton(IPhotonMap& photonMap, int photonCount) const { float randomVector[RANDOM_DIMENSION]; randomSet_->nextf(randomVector); Spectrum power; ray3f ray(light_->samplePhoton( power, vec2f( Lcg::global().nextf(), Lcg::global().nextf()), vec2f( randomAt(randomVector, 0), randomAt(randomVector, 1)))); power /= static_cast<float>(photonCount); // split power HitInfo hit = HitInfo::createUninitialized(); float currentRefractiveIndex = 1; int bounceCount = 0; while( scene_->raytrace(ray, hit) ) { if(bounceCount > 0) { Photon photon( hit.position(), hit.normal(), power); photonMap.add(photon); } Material const& material = hit.material(); if(material.getType() == Material::MATERIAL_DIFFUSE) { float u = Lcg::global().nextf(); // Russian roulette. if(u <= material.getReflectance().average()) { power *= material.getReflectance() / material.getReflectance().average(); ray = ray3f( hit.position(), Hemisphere::cosineWeightedDirection( hit.normal(), randomAt(randomVector, 2+2*bounceCount), randomAt(randomVector, 3+2*bounceCount))); } else { break; } } else if(material.getType() == Material::MATERIAL_SPECULAR) { float u = Lcg::global().nextf(); // Russian roulette. if(u <= material.getReflectance().average()) { power *= material.getReflectance() / material.getReflectance().average(); ray = ray3f( hit.position(), Hemisphere::mirrorReflection( hit.normal(), ray.getDirection())); } else { break; } } else if(material.getType() == Material::MATERIAL_DIELECTRIC) { float fresnel = Hemisphere::fresnelCoefficient( hit.normal(), ray.getDirection(), currentRefractiveIndex, material.getRefractiveIndex()); float u = Lcg::global().nextf(); if(u < 1 - fresnel) { // refraction vec3f excitantDirection; if( Hemisphere::computeRefraction( hit.normal(), ray.getDirection(), currentRefractiveIndex, material.getRefractiveIndex(), excitantDirection) ) { ray = ray3f( hit.position(), excitantDirection); currentRefractiveIndex = material.getRefractiveIndex(); } else { // total internal reflection ray = ray3f( hit.position(), Hemisphere::mirrorReflection( hit.normal(), ray.getDirection())); } } else { // reflection ray = ray3f( hit.position(), Hemisphere::mirrorReflection( hit.normal(), ray.getDirection())); } } else { break; } ++bounceCount; } }
void World::createCache() { Thing *emitter; HitInfo c; int length =0; int resetcount = 1; HitInfo emtInfo; vec emtN; vec source; emitter = emitters[Random::upto(emitters.size())]; source = emitter->randomSurfacePoint(emtN); emtInfo.hit = true; emtInfo.incoming = emtN; emtInfo.normal = emtN; emtInfo.location = source; emtInfo.mat = emitter->getMaterial(); colorcache.push_back(emitter->getMaterial()->getColor()); hicache.push_back(emtInfo); bool done = false; for (int d = 1; d < cacheSize; d++) { int i = d - 1; double ints = colorcache[i].intensity(); if (ints < .01 || length > 60 || done) { emitter = emitters[Random::upto(emitters.size())]; source = emitter->randomSurfacePoint(emtN); emtInfo.distance = 0; emtInfo.previousDistances = 0; emtInfo.hit = true; emtInfo.incoming = emtN; emtInfo.normal = emtN; emtInfo.location = source; emtInfo.mat = emitter->getMaterial(); int intes = 1;//emitter->getMaterial()->getColor().intensity() + 1; for (int x=0; x<intes; x++) { colorcache.push_back(emitter->getMaterial()->getColor() * (1.0/intes)); hicache.push_back(emtInfo); } resetcount++; d += intes-1; done = false; length = 0; continue; } length++; HitInfo newI; newI.follow(hicache[d-1]); vec newDirection = hicache[d-1].mat->sample(hicache[d-1].incoming, hicache[d-1].normal); objects->hit(&newI, hicache[d-1].location, newDirection); if (newI.hit) { Color newc = hicache[d-1].mat->combineColor(colorcache[d-1] * hicache[d-1].mat->sampledPdf(hicache[d-1].incoming, newDirection, hicache[d-1].normal)); int intes = 1;//newc.intensity()*3 + 1; for (int x=0; x<intes; x++) { hicache.push_back(newI); colorcache.push_back(newc * (1.0/intes)); } d += intes-1; } else { done = true; d--; } } cacheweight = (cacheSize * 1.0 / resetcount); }
ColorTimeCache World::runCache(vec origin, vec direction) const { ColorTimeCache accum; std::vector<Color> cumEyeWeight; std::vector<HitInfo> eyeHits; std::vector<int> todo; std::vector<double> mult; todo.reserve(depth); cumEyeWeight.reserve(depth); //8s without, 8s with, but should make a difference. eyeHits.reserve(depth); mult.reserve(depth); HitInfo eyeInfo; objects->hit(&eyeInfo, origin, direction); bool done = false; if (!eyeInfo.hit) return accum; Color newc = eyeInfo.mat->getColor(); int ints = 1;//newc.intensity() * (depth/2) + 1; for (int x=0; x<ints; x++) todo.push_back(eyeHits.size()); cumEyeWeight.push_back(newc); eyeHits.push_back(eyeInfo); mult.push_back(1.0/ints); for (int d = 1; d < depth && !todo.empty(); d++) { HitInfo newI; int index = todo.back(); todo.pop_back(); newI.follow(eyeHits[index]); vec newDirection = eyeHits[index].mat->sample(eyeHits[index].incoming, eyeHits[index].normal); objects->hit(&newI, eyeHits[index].location, newDirection); if (newI.hit) { Color newc = newI.mat->combineColor( cumEyeWeight[index] * eyeHits[index].mat->sampledPdf( eyeHits[index].incoming, newDirection, eyeHits[index].normal)); // newc *= mult[index]; int ints = 1;//newc.intensity() * (depth/2) + 1; for (int x=0; x<ints; x++) todo.push_back(eyeHits.size()); eyeHits.push_back(newI); cumEyeWeight.push_back(newc); mult.push_back(1.0/ints); } else done = true; } for (int x=0; x<depth; x++) { for (int y=0; y<eyeHits.size(); y++) { int index = Random::upto(cacheSize); vec dir = eyeHits[y].location - hicache[index].location; double dist = dir.magnitude(); if (dist < EPSILON) continue; dir.normalize(); HitInfo inf; inf.distanceOnly = true; inf.distance = dist; objects->hit(&inf, hicache[index].location, dir); if (inf.distance >= dist - EPSILON || !inf.hit) { //hit Color result = cumEyeWeight[y] * colorcache[index] * cacheweight * eyeHits[y].mat->pdf(eyeHits[y].incoming, dir * -1, eyeHits[y].normal) * hicache[index].mat->pdf(hicache[index].incoming, dir, hicache[index].normal) * (1/BOUNCE_MULT); accum.addSample(hicache[index].distance + hicache[index].previousDistances + eyeHits[y].distance + eyeHits[y].previousDistances + inf.distance, result); } } } return accum; }
Color MtlBlinn::Shade(const Ray &ray, const HitInfo &hInfo, const LightList &lights, int reflection_bounceCount, int gi_bounceCount) const { Color ambientComp, diffuseComp, specularComp, reflectiveComp, refractiveComp, reflectionTotal, refractionTotal, noColor, diffuseReflection; diffuseReflection = ambientComp = diffuseComp = specularComp = reflectiveComp = refractiveComp = noColor = reflectionTotal = refractionTotal = Color(0.0f, 0.0f, 0.0f); Color fromReflection = Color(0.0f, 0.0f, 0.0f); Color fromRefraction = Color(0.0f, 0.0f, 0.0f); Point3 viewDirection = -ray.dir; float schlicksConstant, ratioOfRefraction; Color kd = diffuse.Sample(hInfo.uvw); int hitside = HIT_FRONT; float n1 = 1; float n2 = ior; for (int i = 0; i < lights.size(); i++) { Color lightColor = lights[i]->Illuminate(hInfo.p, hInfo.N); /*if (lightColor != noColor) {*/ if (lights[i]->IsAmbient()) { ambientComp = ambientComponent(lights[i], lightColor, hInfo, diffuse.Sample(hInfo.uvw)); } else { //lightColor.ClampMinMax(); Point3 rayDir = ray.dir; globalPhotonMap.EstimateIrradiance<50>(lightColor, rayDir, 2.0f, hInfo.p, &hInfo.N); diffuseComp = diffuseComponent(lights[i], lightColor, hInfo, diffuse.Sample(hInfo.uvw)); specularComp = specularComponent(lights[i], lightColor, viewDirection, hInfo, specular.Sample(hInfo.uvw), glossiness); } //} } /************************Refraction************************************************************/ if(refraction.Sample(hInfo.uvw) != noColor && reflection_bounceCount > 0) { Ray refractionRay; HitInfo refractionRayHit; refractionRayHit.Init(); refractionRay.p = hInfo.p; if (hInfo.front == HIT_FRONT) { refractionRay.dir = getRefractionVector(viewDirection, getPerturbedNormal(hInfo.N, hInfo.p, refractionGlossiness), n1, n2); } else { refractionRay.dir = getRefractionVector(viewDirection, getPerturbedNormal( -hInfo.N, hInfo.p, refractionGlossiness), n2, n1); } if(TraceRay(&rootNode, refractionRay, refractionRayHit, hitside)) { Point3 refractionDir = refractionRay.dir; refractiveComp += refractionRayHit.node->GetMaterial()->Shade(refractionRay, refractionRayHit, lights, --reflection_bounceCount); refractiveComp *= refraction.Sample(hInfo.uvw); } else { refractiveComp = environment.SampleEnvironment(refractionRay.dir); } } /********************Schlick's Approximation - Fresnel Reflection***************************/ schlicksConstant = pow(((n1 - n2) / (n1 + n2)), 2); ratioOfRefraction = schlicksConstant + (1 - schlicksConstant) * pow((1 - viewDirection.Dot(hInfo.N)), 5); reflectionTotal = ratioOfRefraction*refraction.Sample(hInfo.uvw); refractionTotal = (1 - ratioOfRefraction)*refraction.Sample(hInfo.uvw); ///*******************************************************************************************/ //refractiv eComp *= refractionTotal; //It = (1-R) * KT' reflectionTotal += reflection.Sample(hInfo.uvw); //Doing outside in case refraction didn't occured at all /*********************************************************************************************/ /**********************Reflection*************************************************************/ if(reflectionTotal != noColor && reflection_bounceCount > 0) { Ray reflectionViewVector; reflectionViewVector.dir = getReflectionVector(viewDirection, getPerturbedNormal(hInfo.N, hInfo.p, reflectionGlossiness)); reflectionViewVector.p = hInfo.p; HitInfo reflectionRayHit; reflectionRayHit.Init(); //--reflection_bounceCount; if (TraceRay(&rootNode, reflectionViewVector, reflectionRayHit, HIT_FRONT)) { fromReflection += reflectionRayHit.node->GetMaterial()->Shade(reflectionViewVector, reflectionRayHit, lights, --reflection_bounceCount); reflectiveComp = reflectionTotal * fromReflection; } else { reflectiveComp = environment.SampleEnvironment(reflectionViewVector.dir); } } /****************************************************************************************************/ if(GI_ALGO) { if (kd != noColor && gi_bounceCount > 0) { HemiSphereSampler giHemiSampler = HemiSphereSampler(__gi_sampleCount, __gi_sampleCount, 1); giHemiSampler.generateSamples(); Point3 randomDirectionAtHitPoint = Point3(0.0f, 0.0f, 0.0f); HitInfo diffuseReflectionHitInfo; Ray diffuseReflectionRay; for (int i = 0; i < giHemiSampler.getCurrentSampleCount(); ++i) { randomDirectionAtHitPoint = giHemiSampler.getSample(getRandomNumber(0, giHemiSampler.getCurrentSampleCount())).getOffset(); diffuseReflectionRay.p = hInfo.p; Point3 u = Point3(0.0f, 0.0f, 0.0f); Point3 v = Point3(0.0f, 0.0f, 0.0f); Point3 w = Point3(0.0f, 0.0f, 0.0f); w = hInfo.N; getOrthoNormalBasisVector(w, u, v); diffuseReflectionRay.dir = randomDirectionAtHitPoint.x * u + randomDirectionAtHitPoint.y * v + randomDirectionAtHitPoint.z *w; diffuseReflectionHitInfo.Init(); if (TraceRay(&rootNode, diffuseReflectionRay, diffuseReflectionHitInfo, HIT_FRONT)) { diffuseReflection = diffuseReflectionHitInfo.node->GetMaterial()->Shade(diffuseReflectionRay, diffuseReflectionHitInfo, lights, 0, gi_bounceCount - 1); } else { diffuseReflection = environment.SampleEnvironment(diffuseReflectionRay.dir); } giHemiSampler.setSampleColor(i, diffuseReflection); giHemiSampler.setIsSampleHit(i, true); } diffuseReflection = giHemiSampler.getAveragedSampleListColor() * diffuseReflection * kd * M_PI; } } else { if (kd != noColor && gi_bounceCount > 0) { HemiSphereSampler giHemiSampler = HemiSphereSampler(__gi_sampleCount, __gi_sampleCount, 1); giHemiSampler.generateSamples(); Point3 randomDirectionAtHitPoint = Point3(0.0f, 0.0f, 0.0f); HitInfo diffuseReflectionHitInfo; Ray diffuseReflectionRay; randomDirectionAtHitPoint = giHemiSampler.getSample(getRandomNumber(0, giHemiSampler.getCurrentSampleCount())).getOffset(); diffuseReflectionRay.p = hInfo.p; Point3 u = Point3(0.0f, 0.0f, 0.0f); Point3 v = Point3(0.0f, 0.0f, 0.0f); Point3 w = Point3(0.0f, 0.0f, 0.0f); w = hInfo.N; getOrthoNormalBasisVector(w, u, v); diffuseReflectionRay.dir = randomDirectionAtHitPoint.x * u + randomDirectionAtHitPoint.y * v + randomDirectionAtHitPoint.z *w; diffuseReflectionHitInfo.Init(); if (TraceRay(&rootNode, diffuseReflectionRay, diffuseReflectionHitInfo, HIT_FRONT)) { diffuseReflection += diffuseReflectionHitInfo.node->GetMaterial()->Shade(diffuseReflectionRay, diffuseReflectionHitInfo, lights, 0, gi_bounceCount - 1); diffuseReflection = diffuseReflection * kd; } else { diffuseReflection = environment.SampleEnvironment(diffuseReflectionRay.dir); } } } return (ambientComp + diffuseComp + specularComp+ reflectiveComp + refractiveComp + diffuseReflection); }
Color MtlBlinn::Shade(const Cone &ray, const HitInfo &hInfo, const LightList &lights, int bounceCount) const{ float bias = BIAS_SHADING; Color shade; Color rShade = Color(0,0,0); Color tShade = Color(0,0,0); const Material *mat; mat = hInfo.node->GetMaterial(); const MtlBlinn* mb =static_cast<const MtlBlinn*>(mat); // cout<<"HInfo front: "<<hInfo.front<<endl; /* local copy */ Point3 P; P.Set(hInfo.p.x,hInfo.p.y,hInfo.p.z); Cone iRay = ray; Color ambInt = mb->diffuse.Sample(hInfo.uvw, hInfo.duvw); Color allOther = Color(0,0,0); Color diffuse = mb->diffuse.Sample(hInfo.uvw, hInfo.duvw); Color ambComponent = Color(0,0,0); Point3 newN = hInfo.N; for ( unsigned int i=0; i<lights.size(); i++ ) { if(lights[i]->IsAmbient()){ // cout<<"ambient "<<endl; Color intensity = lights[i]->Illuminate(hInfo.p); ambComponent += (ambInt * intensity); continue; } else{ // cout<<"other lighting "<<endl; Point3 L = -lights[i]->Direction(P); L.Normalize(); Point3 V = ray.p - P; V.Normalize(); Point3 LplusV = L + V; Point3 H = (L+V)/LplusV.Length(); H.Normalize(); float alpha = mb->glossiness; // Point3 N = hInfo.N; Point3 N = newN; float S = H.Dot(N); S = pow(S,alpha); float costheta = L.Dot(N)/(L.Length() * N.Length()); Color intensity = lights[i]->Illuminate(P); // cout<<"costheta "<<endl; allOther += intensity * (costheta>0?costheta:0) * (diffuse + S * (mb->specular.Sample(hInfo.uvw, hInfo.duvw))) ; } /* finally add inta*cola + intall*costheta*(cold + s* colS)*/ shade = ambComponent + allOther; } /* Calculate refraction */ if(refraction.GetColor().r>0 && bounceCount>0){ //compute new jittered normal float gloss = refractionGlossiness; if(gloss){ float random = rand()/(float)RAND_MAX; float rRadius = sqrtf(random) * gloss; random = rand()/(float)RAND_MAX; float rAngle = random * 2.0 * M_PI; float x = rRadius * cos(rAngle); float y = rRadius * sin(rAngle); Point3 xAxis(1,0,0), yAxis(0,1,0), v1, v2, normalDir; normalDir = hInfo.N; // normalDir.Normalize(); if(normalDir.Dot(xAxis) > 0.7) v1 = normalDir.Cross(yAxis); else v1 = normalDir.Cross(xAxis); v2 = v1.Cross(normalDir); v1.Normalize(); v2.Normalize(); v1 *= x; v2 *= y; newN = hInfo.N + v1.Length() + v2.Length(); newN.Normalize(); } else{ newN = hInfo.N; } //------------------------------------- Color reflShade = Color(0,0,0); float R0, Refl = 0.0f, Trans = 0.0f; HitInfo temp; temp.Init(); // Point3 N = hInfo.N; Point3 N = newN; // Point3 V = Point3(iRay.p.x - hInfo.p.x, iRay.p.y - hInfo.p.y, iRay.p.z - hInfo.p.z); Point3 V = Point3(hInfo.p.x - iRay.p.x, hInfo.p.y - iRay.p.y, hInfo.p.z - iRay.p.z); V.Normalize(); float n1 = 1, n2 = 1; if(hInfo.front){ /* Hitting from outside */ // temp.front = false; n2 = ior; // cout<<"outside "<<endl; } else if(!hInfo.front){ /* Transmission from the inside */ // temp.front = true; n1 = ior; // cout<<"intside... "<<endl; // N = -hInfo.N; N *= -1; } float ratio_n = n1 / n2; float costheta_v = -V.Dot(N); /* refer: http://graphics.stanford.edu/courses/cs148-10-summer/docs/2006--degreve--reflection_refraction.pdf */ float sin2theta_t = ratio_n * ratio_n * (1 - costheta_v * costheta_v); Point3 T = ratio_n * V + (ratio_n * costheta_v - sqrtf(1 - sin2theta_t)) * N ; // cout<<ratio_n<<" "<<"cos_v "<<costheta_v<<" sin2theta_t "<<sin2theta_t<<endl; Cone tRay = Cone(hInfo.p,T); //tRay.dir.Normalize(); tRay.p.x = tRay.p.x + bias *tRay.dir.x; /* add bias */ tRay.p.y = tRay.p.y + bias *tRay.dir.y; tRay.p.z = tRay.p.z + bias *tRay.dir.z; // cout<<"B temp front: "<< temp.front<<endl; temp.timeInstance = hInfo.timeInstance; if(sin2theta_t <= 1){ if(RayTrace_2(tRay, temp)){ /* ray tracing after refraction */ // bounceCount--; tShade = temp.node->GetMaterial()->Shade(tRay,temp,lights,bounceCount); } else{ /* no hit after refraction */ tShade = environment.SampleEnvironment(tRay.dir); } /* Calculate Schlick's approximation */ R0 = (n1 - n2)/(n1 + n2); R0 *= R0; double X = 0.0; // if(n1 > n2){ // X = 1.0 - sqrtf(1.0 - sin2theta_t); // } // else{ X = 1.0 - costheta_v; } X = 1.0 - costheta_v; Refl = R0 + (1.0 - R0) * X * X * X * X * X; Trans = 1.0 - Refl; tShade.r *= exp(-absorption.r * temp.z); tShade.g *= exp(-absorption.g * temp.z); tShade.b *= exp(-absorption.b * temp.z); } else {/* Total internal reflection */ Refl = 1.0f; } /* Calculate reflection due to reflectance */ if(bounceCount >0){ // N = hInfo.N; N = newN; Point3 V = Point3(iRay.p.x - P.x, iRay.p.y - P.y, iRay.p.z - P.z); //V.Normalize(); Point3 VR = 2 * V.Dot(N) * N - V; //VR.Normalize(); Cone rRay = Cone(P + BIAS_SHADING * VR, VR); rRay.dir.Normalize(); HitInfo temp1; temp1.Init(); temp.timeInstance = hInfo.timeInstance; if(rootNode.GetNumChild()>0){ if(RayTrace_2(rRay, temp1)){ bounceCount --; reflShade = temp1.node->GetMaterial()->Shade(rRay, temp1, lights, bounceCount); } else{ reflShade = environment.SampleEnvironment(rRay.dir); // reflShade = Color(1,100,1); } } } // cout<<"Refl: "<<Refl<<"Trans "<<Trans<<endl; tShade = refraction.GetColor().r * (Trans * tShade + Refl * reflShade); } /* calculate reflection*/ if(reflection.GetColor().r>0 && bounceCount > 0){ //compute new jittered normal float gloss = reflectionGlossiness; if(gloss){ float random = rand()/(float)RAND_MAX; float rRadius = sqrtf(random) * gloss; random = rand()/(float)RAND_MAX; float rAngle = random * 2.0 * M_PI; float x = rRadius * cos(rAngle); float y = rRadius * sin(rAngle); Point3 xAxis(1,0,0), yAxis(0,1,0), v1, v2, normalDir; normalDir = hInfo.N; // normalDir.Normalize(); if(normalDir.Dot(xAxis) > 0.7) v1 = normalDir.Cross(yAxis); else v1 = normalDir.Cross(xAxis); v2 = v1.Cross(normalDir); v1.Normalize(); v2.Normalize(); v1 *= x; v2 *= y; newN = hInfo.N + v1+ v2; newN.Normalize(); } else{ newN = hInfo.N; } //------------------------------------- Point3 N = newN;//hInfo.N; Point3 V = Point3(iRay.p.x - P.x, iRay.p.y - P.y, iRay.p.z - P.z); // V.Normalize(); Point3 VR = 2 * V.Dot(N) * N - V; Cone rRay = Cone(P + BIAS_SHADING * VR, VR); rRay.dir.Normalize(); HitInfo temp; temp.Init(); temp.timeInstance=hInfo.timeInstance; if(rootNode.GetNumChild()>0){ if(RayTrace_2(rRay, temp)){ bounceCount--; rShade = reflection.GetColor().r * temp.node->GetMaterial()->Shade(rRay, temp, lights, bounceCount); } else{ rShade = reflection.GetColor().r *environment.SampleEnvironment(rRay.dir); // rShade = Color(1,111,1); } } } /* Add shade with reflected and refracted colors */ shade += (rShade + tShade); return shade; };
void doRender(void* arg){ RenderParams rarg = *((RenderParams *)arg); //cout<<"Do render...."<<endl; bool pixelHit=false; HitInfo hitInfo; hitInfo.Init(); Point2 pixLoc = rarg.pixLocation; Cone r = rarg.ray; int PixIndex = rarg.pixIndex; Color shade(0,0,0); vector<Point2> haltonXY; float dx = rarg.PixParams.x; float dy = rarg.PixParams.y; float x=0; float y=0; _f.Normalize(); _s.Normalize(); const float pts[9]={_s.x,_u.x,-_f.x,_s.y,_u.y,-_f.y,_s.z,_u.z,-_f.z}; Matrix3 RotMat; RotMat.Set(pts); for(int i=0; i < MIN_N_SAMPLES; i++){ x = dx * Halton(i+1, H_BASE_1); y = dy * Halton(i+1, H_BASE_2); if(x > dx * 0.5) { x -= dx; } if(y < dy * 0.5) { y -= dy; } x += rarg.K.x; y += rarg.K.y; Point2 sampleLoc = Point2(x,y); haltonXY.push_back(sampleLoc); } vector<Color> shades; if(rootNode.GetNumChild()>0){ for(int i=0; i< MIN_N_SAMPLES;i++){ Point3 sampleDir = Point3(haltonXY.at(i).x, haltonXY.at(i).y, rarg.K.z); int rindex = rand() % MAX_N_SAMPLES; //rindex = i; Point3 randPos = rarg.ConfCirclePts.at(rindex); Cone sampleRay = Cone(randPos, sampleDir); sampleRay.dir = sampleRay.dir * RotMat; sampleRay.dir -= randPos - camera.pos; sampleRay.dir.Normalize(); sampleRay.radius = r.radius; sampleRay.tanAngle = r.tanAngle; r = sampleRay; if(RayTrace_2(r, hitInfo)) { pixelHit=true; shade = hitInfo.node->GetMaterial()->Shade(r, hitInfo, lights, 8); shades.push_back(shade); } hitInfo.Init(); } if(VarianceOverThreshold(shades)){ renderImage.SetSampleCountPixel(PixIndex, 255); hitInfo.Init(); for(int i=MIN_N_SAMPLES; i < MAX_N_SAMPLES; i++){ x = dx * Halton(i+1, H_BASE_1); y = dy * Halton(i+1, H_BASE_2); if(x > dx * 0.5) { x -= dx;} if(y < dy * 0.5) { y -= dy;} x += rarg.K.x; y += rarg.K.y; Point2 sampleLoc = Point2(x,y); haltonXY.push_back(sampleLoc); Point3 sampleDir = Point3(haltonXY.at(i).x, haltonXY.at(i).y, rarg.K.z); int rindex = rand() % MAX_N_SAMPLES; //rindex = i; Point3 randPos = rarg.ConfCirclePts.at(rindex); Cone sampleRay = Cone(randPos, sampleDir); sampleRay.dir = sampleRay.dir * RotMat; sampleRay.dir -= randPos - camera.pos; sampleRay.dir.Normalize(); sampleRay.radius = r.radius; sampleRay.tanAngle = r.tanAngle; r = sampleRay; if(RayTrace_2(r, hitInfo)) { pixelHit=true; shade = hitInfo.node->GetMaterial()->Shade(r, hitInfo, lights, 5); shades.push_back(shade); } hitInfo.Init(); } shade = AverageShades(shades, (int)shades.size()); } else{ shade = AverageShades(shades, (int)shades.size()); renderImage.SetSampleCountPixel(PixIndex, 0); } renderImage.PutPixel(PixIndex, shade, hitInfo.z); } if(!pixelHit){ Point3 uvw(pixLoc.x/ camera.imgWidth,pixLoc.y/camera.imgHeight,0); shade = background.Sample(uvw); renderImage.PutPixel(PixIndex, shade, BIGFLOAT); } pthread_mutex_lock(&setPix_mutex); renderImage.IncrementNumRenderPixel(1); pthread_mutex_unlock(&setPix_mutex); }
HitInfo CSGNode::intersects(Point3D origin, Vector3D dir) const { HitInfo info; origin = get_inverse() * origin; dir = get_inverse() * dir; bool first = true; for (ChildList::const_iterator it = m_children.begin(); it != m_children.end(); ++it) { HitInfo h = (*it)->intersects(origin, dir); for (unsigned int i = 0; i < h.hits.size(); i++) { h.hits.at(i).intersection = get_transform() * h.hits.at(i).intersection; h.hits.at(i).normal = get_inverse().transpose() * h.hits.at(i).normal; } for (unsigned int i = 0; i < h.lines.size(); i++) { h.lines.at(i).first.intersection = get_transform() * h.lines.at(i).first.intersection; h.lines.at(i).second.intersection = get_transform() * h.lines.at(i).second.intersection; h.lines.at(i).first.normal = get_inverse().transpose() * h.lines.at(i).first.normal; h.lines.at(i).second.normal = get_inverse().transpose() * h.lines.at(i).second.normal; } switch(m_type) { case UNION: { info = HitInfo::merge_info(info, h); break; } case INTERSECTION: { if (first) { info = h; } else if (h.empty()) { info.clear(); return info; } else { std::vector<HitInfo::LineSegment> lines; for (unsigned int i = 0; i < info.lines.size(); i++) { HitInfo::LineSegment line = info.lines.at(i); for (unsigned int j = 0; j < h.lines.size(); j++) { HitInfo::LineSegment sub = h.lines.at(j); if (line.first.t >= sub.first.t && line.second.t <= sub.second.t) { // subtracting line contains the first line lines = HitInfo::insert_line_in_order(lines, line); } else if (line.first.t < sub.first.t && line.second.t > sub.second.t) { // first line contains subtracting line lines = HitInfo::insert_line_in_order(lines, sub); } else if (line.first.t > sub.first.t && line.first.t < sub.second.t && line.second.t > sub.second.t) { // tail end of line overlaps with subtracting line. double len = (sub.second.intersection-line.first.intersection).length(); if (len > EPSILON) { lines = HitInfo::insert_line_in_order(lines, std::make_pair(line.first, sub.second)); } } else if (line.first.t < sub.first.t && line.second.t > sub.first.t && line.second.t < sub.second.t) { // head end of line overlaps with subtracting line double len = (line.second.intersection-sub.first.intersection).length(); if (len > EPSILON) { lines = HitInfo::insert_line_in_order(lines, std::make_pair(sub.first, line.second)); } } else { // no overlap, do nothing continue; } } } info.lines = lines; std::vector<Hit> hits; for (unsigned i = 0; i < info.hits.size(); i++) { Hit hit = info.hits.at(i); for (unsigned j = 0; j < h.lines.size(); j++) { HitInfo::LineSegment sub = h.lines.at(j); if (hit.t > sub.first.t && hit.t < sub.second.t) { hits.push_back(hit); break; } } } info.hits = hits; } break; } case DIFFERENCE: { if (first && h.empty()) { return info; } else if (first && !h.empty()) { info = HitInfo::merge_info(info, h); } else if (!h.empty()) { std::vector<HitInfo::LineSegment> lines; for (unsigned int i = 0; i < info.lines.size(); i++) { HitInfo::LineSegment line = info.lines.at(i); for (unsigned int j = 0; j < h.lines.size(); j++) { HitInfo::LineSegment sub = h.lines.at(j); if (line.first.t >= sub.first.t && line.second.t <= sub.second.t) { // subtracting line contains the first line continue; } else if (line.first.t < sub.first.t && line.second.t > sub.second.t) { // first line contains subtracting line; divide into two lines. sub.first.normal = -sub.first.normal; sub.second.normal = -sub.second.normal; double len1 = (sub.first.intersection - line.first.intersection).length(); double len2 = (line.second.intersection- sub.second.intersection).length(); if (len1 > EPSILON) { lines = HitInfo::insert_line_in_order(lines, std::make_pair(line.first, sub.first)); } if (len2 > EPSILON) { lines = HitInfo::insert_line_in_order(lines, std::make_pair(sub.second, line.second)); } } else if (line.first.t > sub.first.t && line.first.t < sub.second.t && line.second.t > sub.second.t) { // head end of line overlaps with subtracting line. sub.second.normal = -sub.second.normal; double len = (line.second.intersection-sub.second.intersection).length(); if (len > EPSILON) { lines = HitInfo::insert_line_in_order(lines, std::make_pair(sub.second, line.second)); } } else if (line.first.t < sub.first.t && line.second.t > sub.first.t && line.second.t < sub.second.t) { // tail end of line overlaps with subtracting line sub.first.normal = -sub.first.normal; double len = (line.first.intersection- sub.first.intersection).length(); if (len > EPSILON) { lines = HitInfo::insert_line_in_order(lines, std::make_pair(line.first, sub.first)); } } else { // no overlap, line remains unchanged. lines = HitInfo::insert_line_in_order(lines, line); } } } info.lines = lines; std::vector<Hit> hits; for (unsigned i = 0; i < info.hits.size(); i++) { Hit hit = info.hits.at(i); bool insert = true; for (unsigned j = 0; j < h.lines.size(); j++) { HitInfo::LineSegment sub = h.lines.at(j); if (hit.t > sub.first.t && hit.t < sub.second.t) { insert = false; } } if (insert) { hits.push_back(hit); } } info.hits = hits; } break; } } first = false; } return info; }
int main(void) { myEngine::Timing::Clock *clock = myEngine::Timing::Clock::createAndStart(); int temp = LoadScene(LOAD_FILE); Point3 cameraRight = (camera.dir ^ camera.up).GetNormalized(); double aspectRatio = static_cast<double>(camera.imgWidth) / static_cast<double>(camera.imgHeight); float camera_l = 1 / (tan((camera.fov / 2) * (M_PI/ 180))); Point3 Sx = cameraRight; Point3 Sy = (-1.0f) * camera.up; Point3 pixel; Point3 k = camera.pos + camera_l* camera.dir;// -cameraRight + camera.up; HitInfo hitInfo; //Color24 hitPixelColor = { 255,255,255 }; Color noHitPixelColor = { 0,0,0 }; Color24* temp_image = renderImage.GetPixels(); float* temp_zBuffer = renderImage.GetZBuffer(); for (int i = 0;i < camera.imgHeight; i++) { //printf("%d\n",i); for (int j = 0; j < camera.imgWidth; j++) { hitInfo.Init(); float flipped_i = camera.imgHeight - i - 1; pixel = k + (((2.0f*aspectRatio * (j + 0.5f)) / camera.imgWidth) - aspectRatio)*Sx + ((((flipped_i + 0.5) * 2) / camera.imgHeight) - 1)* Sy; pixelRay.p = camera.pos; pixelRay.dir = (pixel - camera.pos).GetNormalized(); if (TraceRay(&rootNode, pixelRay, hitInfo)) { #ifdef RELEASE_DEBUG temp_image[i*camera.imgWidth + j] = normalColor(hitInfo); #else temp_image[i*camera.imgWidth + j] = hitInfo.node->GetMaterial()->Shade(pixelRay, hitInfo, lights, 7); #endif temp_zBuffer[i*camera.imgWidth + j] = hitInfo.z; } else { temp_image[i*camera.imgWidth + j] = noHitPixelColor; temp_zBuffer[i*camera.imgWidth + j] = hitInfo.z; } } } renderImage.SaveImage("RayCasted.ppm"); renderImage.ComputeZBufferImage(); renderImage.SaveZImage("RayCastWithZ.ppm"); clock->updateDeltaTime(); double time = clock->getdeltaTime(); printf("Time to render ray casting %f", clock->getdeltaTime()); printf("Time to render zBuffer Image %f", clock->getdeltaTime()); ShowViewport(); }
const Vector3 RectangleLight::sampleLight(const unsigned int threadID, const Vector3 &from, const Vector3 &normal, const float time, const Scene &scene, const Vector3 &rVec, float &outSpec, bool isSecondary) const { Ray sampleRay(threadID); HitInfo sampleHit; Vector3 randDir = 0, tmpResult = 0; float e1, e2, tmpSpec = 0; bool cutOff = false; int samplesDone = 0; float samplesDoneRecip = 1.0f; ALIGN_SSE float falloff = 1.0f; do { // Get a random vector into the light e1 = Scene::getRand(threadID); e2 = Scene::getRand(threadID); e2 = (e2 > 0.99) ? 0.99 : e2; randDir = ((m_v1 + e1*(m_v2-m_v1) + e2*(m_v3-m_v1)) - from); float nDotL = dot(normal, randDir); Vector3 E = 0; float attenuate = 1.0f; if (nDotL > epsilon) // Only do work if light can be hit { // the inverse-squared falloff falloff = randDir.length2(); ALIGN_SSE float distanceRecip, distance; #ifndef NO_SSE fastrsqrtss(setSSE(falloff), distanceRecip); recipss(setSSE(falloff), falloff); recipss(setSSE(distanceRecip), distance); #else distance = sqrtf(falloff); distanceRecip = 1.0f / distance; falloff = 1.0f / falloff; #endif randDir *= distanceRecip; nDotL *= distanceRecip; if (m_castShadows) { sampleHit.t = distance - epsilon; // We need this to account for the fact that we CAN hit geometry, to avoid false positives. if (m_fastShadows) { sampleRay.set(threadID, from, randDir, time, 1.001f, 0, 0, IS_SHADOW_RAY); // Create shadow ray if (scene.trace(threadID, sampleHit, sampleRay, epsilon)) // Quick method, returns any hit { attenuate = 0.0f; } } else // Full method, accounts for transparency effects { float distanceTraversed = 0.0f; sampleRay.set(threadID, from, randDir, time, 1.001f, 0, 0, IS_PRIMARY_RAY); // Create primary ray while (distanceTraversed < distance && attenuate > epsilon) { if (scene.trace(threadID, sampleHit, sampleRay, epsilon)) { Vector3 hitN; sampleHit.getInterpolatedNormal(hitN); float nDL = dot(hitN, -randDir); if (nDL > 0.0) // Only attenuate on incoming direction { attenuate *= sampleHit.obj->m_material->refractAmt(); } Vector3 newP = Vector3(sampleRay.o[0], sampleRay.o[1], sampleRay.o[2]) + sampleHit.t * randDir; sampleRay.set(threadID, newP, randDir, time, 1.001f, 0, 0, IS_PRIMARY_RAY); distanceTraversed += sampleHit.t; } else { distanceTraversed = distance; } } } } } else { attenuate = 0.0f; } E = m_power * falloff * _1_4PI; // Light irradiance for this sample samplesDone++; samplesDoneRecip = 1.0f / (float)samplesDone; cutOff = (E * samplesDoneRecip).average() < m_noiseThreshold; // Stop sampling if contribution is below the noise threshold tmpResult += E * attenuate; tmpSpec += max(0.f, dot(rVec, randDir)) * attenuate; } while (samplesDone < m_numSamples && !cutOff); outSpec = tmpSpec * samplesDoneRecip; return tmpResult * samplesDoneRecip; }