Color Raytracer::CalnDiffusion( Collider* collider , int* hash, int rc, Color weight) { Primitive* pri = collider->GetPrimitive(); Color color = pri->GetMaterial()->color; if (pri->GetMaterial()->texture != NULL) { if (pri->getName() == 0) color = color * pri->GetTexture(collider->C); else color = color * pri->GetTexture(Vector3(collider->u, collider->v, 0)); } Color ret = color * scene->GetBackgroundColor() * pri->GetMaterial()->diff; for ( Light* light = scene->GetLightHead() ; light != NULL ; light = light->GetNext() ) ret += color * light->GetIrradiance( collider , scene->GetPrimitiveHead() , scene->GetCamera()->GetShadeQuality() , hash ); if (camera->GetAlgorithm() == "PM") ret += color * photonmap->GetIrradiance( collider , camera->GetSampleDist() , camera->GetSamplePhotons() ); if (camera->GetAlgorithm() == "PPM" || camera->GetAlgorithm() == "SPPM") { Hitpoint hitpoint; hitpoint.pos = collider->C; hitpoint.dir = collider->I; hitpoint.N = collider->N; hitpoint.primitive = collider->GetPrimitive(); hitpoint.rc = rc; hitpoint.weight = weight * color; hitpoint.R2 = photonmap->GetRadius2(collider, camera->GetSampleDist(), camera->GetSamplePhotons()); hitpointMap->Store(hitpoint); } return ret; }
// ----------------------------------------------------------- // Engine::Raytrace // Naive ray tracing: Intersects the ray with every primitive // in the scene to determine the closest intersection // ----------------------------------------------------------- Primitive* Engine::Raytrace( Ray& a_Ray, Color& a_Acc, int a_Depth, float a_RIndex, float& a_Dist ) { if (a_Depth > TRACEDEPTH) return 0; // trace primary ray a_Dist = 1000000.0f; vector3 pi; Primitive* prim = 0; int result; // find the nearest intersection for ( int s = 0; s < m_Scene->GetNrPrimitives(); s++ ) { Primitive* pr = m_Scene->GetPrimitive( s ); int res; if (res = pr->Intersect( a_Ray, a_Dist )) { prim = pr; result = res; // 0 = miss, 1 = hit, -1 = hit from inside primitive } } // no hit, terminate ray if (!prim) return 0; // handle intersection if (prim->IsLight()) { // we hit a light, stop tracing a_Acc = Color( 1, 1, 1 ); } else { // determine color at point of intersection pi = a_Ray.GetOrigin() + a_Ray.GetDirection() * a_Dist; // trace lights for ( int l = 0; l < m_Scene->GetNrPrimitives(); l++ ) { Primitive* p = m_Scene->GetPrimitive( l ); if (p->IsLight()) { Primitive* light = p; // calculate diffuse shading vector3 L = ((Sphere*)light)->GetCentre() - pi; NORMALIZE( L ); vector3 N = prim->GetNormal( pi ); if (prim->GetMaterial()->GetDiffuse() > 0) { float dot = DOT( N, L ); if (dot > 0) { float diff = dot * prim->GetMaterial()->GetDiffuse(); // add diffuse component to ray color a_Acc += diff * prim->GetMaterial()->GetColor() * light->GetMaterial()->GetColor(); } } } } } // return pointer to primitive hit by primary ray return prim; }
Color Raytracer::CalnRefraction( Collider* collider , Vector3 ray_V , int dep , bool refracted , int* hash, int rc, Color weight) { Primitive* pri = collider->GetPrimitive(); double n = pri->GetMaterial()->rindex; if ( !refracted ) n = 1 / n; bool nextRefracted = refracted; ray_V = ray_V.Refract( collider->N , n , &nextRefracted ); Color alpha = Color(1, 1, 1) * pri->GetMaterial()->refr; if (refracted) alpha *= (pri->GetMaterial()->absor * -collider->dist).Exp(); Color rcol = RayTracing( collider->C , ray_V , dep + 1 , nextRefracted , hash, rc, weight * alpha); return rcol * alpha; }
/*! @brief トレース @param[o] out: 出力輝度 @param[i] ray: 光線 @param[i] depth: 深度 */ void Renderer::Trace(Color& out, const Ray& ray, std::size_t depth) { Primitive* prim = NULL; Primitive::Param param; if((depth >= max_depth) || !FindNearest(&prim, param, ray)) { out = scene->GetBGColor(); return; } Vertex v; prim->CalcVertex(v, param, ray); Material* mtrl = prim->GetMaterial(); // emittance out = mtrl->e; #ifdef USE_LOCAL_ILLUMINATION // direct lighting Color direct; DirectLighting(direct, ray, v, *mtrl); ColorAdd3(&out, &out, &direct); #endif // USE_LOCAL_ILLUMINATION #ifdef USE_GLOBAL_ILLUMINATION // indirect lighting Color indirect; IndirectLighting(indirect, ray, v, *mtrl, depth); ColorAdd3(&out, &out, &indirect); #endif // USE_GLOBAL_ILLUMINATION }
Color Raytracer::CalnReflection( Collider* collider , Vector3 ray_V , int dep , bool refracted , int* hash, int rc, Color weight) { Primitive* pri = collider->GetPrimitive(); ray_V = ray_V.Reflect( collider->N ); if ( pri->GetMaterial()->drefl < EPS || dep > MAX_DREFL_DEP ) { Color alpha = pri->GetMaterial()->color * pri->GetMaterial()->refl; return RayTracing( collider->C , ray_V , dep + 1 , refracted , hash, rc, weight * alpha) * alpha; } Vector3 Dx = ray_V.GetAnVerticalVector(); Vector3 Dy = ray_V.Cross(Dx); Dx = Dx.GetUnitVector() * pri->GetMaterial()->drefl; Dy = Dy.GetUnitVector() * pri->GetMaterial()->drefl; int totalSample = camera->GetDreflQuality(); Color rcol, alpha = pri->GetMaterial()->color * pri->GetMaterial()->refl / totalSample; for ( int k = 0 ; k < totalSample ; k++ ) { double x , y; do { x = ran() * 2 - 1; y = ran() * 2 - 1; } while ( x * x + y * y > 1 ); x *= pri->GetMaterial()->drefl; y *= pri->GetMaterial()->drefl; rcol += RayTracing( collider->C , ray_V + Dx * x + Dy * y , dep + MAX_DREFL_DEP , refracted , NULL, rc, weight * alpha); } return rcol * alpha; }
// ray tracing Colour RayTracer::TraceRay(Ray& ray, int traceDepth) { if (traceDepth > MAXTRACEDEPTH) return Colour(); Colour litColour, reflectedColour; float distanceToIntersect = MAXDISTANCE; Vector3f intersectionPoint; Primitive* nearestPrimitive = 0; nearestPrimitive = mScene->GetFirstPrimitive(ray, distanceToIntersect); if (!nearestPrimitive) return Colour(); else { // Ambient,Specular lighting intersectionPoint = ray.GetOrigin() + ray.GetDirection() * distanceToIntersect; litColour = mScene->CalculatePrimitiveLightingAtPoint((*nearestPrimitive), intersectionPoint, ray.GetDirection()); // reflection float reflectionFactor = nearestPrimitive->GetMaterial()->Reflection; if (reflectionFactor > 0.0f) { Vector3f normal = nearestPrimitive->GetNormal(intersectionPoint); Vector3f reflected = ray.GetDirection() - normal * (2.0f * (ray.GetDirection()*normal)); Ray reflectedRay = Ray(intersectionPoint , reflected); reflectedColour = TraceRay(reflectedRay, traceDepth + 1) * reflectionFactor; } return litColour + reflectedColour; } }
void Scene::Setup(params::InterfaceGlRef _params) { Primitive* primitive; float planeDist = 25; //ground plane primitive = new PlanePrimitive(ci::Vec3f(0, -planeDist, 0), ci::Vec3f(0, 1, 0)); primitive->SetName("GroundPlane"); primitive->GetMaterial().SetDiffuseColor(ci::ColorA(1.0f, 0.2f, 0.2f)); primitive->GetMaterial().SetSpecularColor(ci::ColorA(1.0f, 1.0f, 1.0f)); primitive->GetMaterial().SetDiffuseCoefficient(1.0f); primitive->GetMaterial().SetSpecularCoefficient(0.0f); m_primitives.push_back(primitive); //top plane primitive = new PlanePrimitive(ci::Vec3f(0, planeDist, 0), ci::Vec3f(0, -1, 0)); primitive->SetName("TopPlane"); primitive->GetMaterial().SetDiffuseColor(ci::ColorA(0.2f, 1.0f, 0.2f)); primitive->GetMaterial().SetSpecularColor(ci::ColorA(1.0f, 1.0f, 1.0f)); primitive->GetMaterial().SetDiffuseCoefficient(1.0f); primitive->GetMaterial().SetSpecularCoefficient(0.0f); m_primitives.push_back(primitive); //side plane primitive = new PlanePrimitive(ci::Vec3f(planeDist, 0, 0), ci::Vec3f(-1, 0, 0)); primitive->SetName("RightPlane"); primitive->GetMaterial().SetDiffuseColor(ci::ColorA(0.2f, 0.2f, 1.0f)); primitive->GetMaterial().SetSpecularColor(ci::ColorA(1.0f, 1.0f, 1.0f)); primitive->GetMaterial().SetDiffuseCoefficient(1.0f); primitive->GetMaterial().SetSpecularCoefficient(0.0f); m_primitives.push_back(primitive); //side plane primitive = new PlanePrimitive(ci::Vec3f(-planeDist, 0, 0), ci::Vec3f(1, 0, 0)); primitive->SetName("LeftPlane"); primitive->GetMaterial().SetDiffuseColor(ci::ColorA(1.0f, 1.0f, 0.2f)); primitive->GetMaterial().SetSpecularColor(ci::ColorA(1.0f, 1.0f, 1.0f)); primitive->GetMaterial().SetDiffuseCoefficient(1.0f); primitive->GetMaterial().SetSpecularCoefficient(0.0f); m_primitives.push_back(primitive); //side plane primitive = new PlanePrimitive(ci::Vec3f(0, 0, planeDist), ci::Vec3f(0, 0, -1)); primitive->SetName("FrontPlane"); primitive->GetMaterial().SetDiffuseColor(ci::ColorA(1.0f, 0.2f, 1.0f)); primitive->GetMaterial().SetSpecularColor(ci::ColorA(1.0f, 1.0f, 1.0f)); primitive->GetMaterial().SetDiffuseCoefficient(1.0f); primitive->GetMaterial().SetSpecularCoefficient(0.0f); m_primitives.push_back(primitive); //side plane primitive = new PlanePrimitive(ci::Vec3f(0, 0, -planeDist), ci::Vec3f(0, 0, 1)); primitive->SetName("BackPlane"); primitive->GetMaterial().SetDiffuseColor(ci::ColorA(0.2f, 1.0f, 1.0f)); primitive->GetMaterial().SetSpecularColor(ci::ColorA(1.0f, 1.0f, 1.0f)); primitive->GetMaterial().SetDiffuseCoefficient(1.0f); primitive->GetMaterial().SetSpecularCoefficient(0.0f); m_primitives.push_back(primitive); //big sphere primitive = new SpherePrimitive(ci::Vec3f(5, 7, 0), 7); primitive->SetName("BigSphere"); primitive->GetMaterial().SetDiffuseColor(ci::ColorA(1.0f, 1.0f, 1.0f)); primitive->GetMaterial().SetSpecularColor(ci::ColorA(1.0f, 1.0f, 1.0f)); primitive->GetMaterial().SetDiffuseCoefficient(1.0f); primitive->GetMaterial().SetSpecularCoefficient(0.0f); primitive->GetMaterial().SetReflectionCoefficient(0.0f); primitive->GetMaterial().SetRefractionCoefficient(1.1f); m_primitives.push_back(primitive); //small sphere primitive = new SpherePrimitive(ci::Vec3f(-5, -5, -10), 5); primitive->SetName("SmallSphere"); primitive->GetMaterial().SetDiffuseColor(ci::ColorA(0.5f, 0.5f, 0.1f)); primitive->GetMaterial().SetSpecularColor(ci::ColorA(1.0f, 1.0f, 1.0f)); primitive->GetMaterial().SetDiffuseCoefficient(1.0f); primitive->GetMaterial().SetSpecularCoefficient(0.0f); primitive->GetMaterial().SetReflectionCoefficient(0.1f); primitive->GetMaterial().SetRefractionCoefficient(0.0f); m_primitives.push_back(primitive); //light1 primitive = new SpherePrimitive(ci::Vec3f(10, 24, 0), 2); primitive->SetName("Light1"); primitive->GetMaterial().SetDiffuseColor(ci::ColorA(1.0f, 1.0f, 1.0f)); primitive->SetIsLight(true); m_primitives.push_back(primitive); ////light2 /*primitive = new SpherePrimitive(ci::Vec3f(-10, 10, -10), 1); primitive->SetName("Light 2"); primitive->GetMaterial().SetDiffuseColor(ci::ColorA(0.7f, 0.7f, 0.7f)); primitive->SetIsLight(true); m_primitives.push_back(primitive);*/ for (int i=0; i<m_primitives.size(); i++) m_primitives[i]->AddParams(_params); }
ci::ColorA Scene::Raytrace(const ci::Ray& inRay, int inDepth, float& inDist, const float inRefractIndex) { if (inDepth > 3) return ci::ColorA::black(); Primitive* hitPrim = NULL; Primitive::E_INTERSECT_RESULT result; float currentInDist = inDist; for (int i=0; i<m_primitives.size(); i++) { Primitive* prim = m_primitives[i]; Primitive::E_INTERSECT_RESULT res = prim->Intersect(inRay, inDist); if (res != Primitive::MISS) { if (inDist <= currentInDist) { hitPrim = prim; result = res; } } } if (!hitPrim) return ci::ColorA::black(); if (hitPrim->IsLight()) return hitPrim->GetMaterial().GetDiffuseColor(); else { ci::Vec3f hitPoint = inRay.getOrigin() + inRay.getDirection() * inDist; ci::ColorA accumColor(0, 0, 0, 0); {//shading for (int i=0; i<m_primitives.size(); i++) { Primitive* prim = m_primitives[i]; if (prim->IsLight()) { Primitive* light = prim; //shadow feeler float shade = 1.0f; //get shadow feeler ray in direction of light ci::Vec3f L = (((SpherePrimitive*)light)->getCenter() - hitPoint).normalized(); float lightToHitPointDist = (((SpherePrimitive*)light)->getCenter() - hitPoint).length(); ci::Ray shadowFeelerRay(hitPoint + L * ci::EPSILON_VALUE, L); float LDist = 1000.0f; for (int j = 0; j<m_primitives.size(); j++) { Primitive* primJ = m_primitives[j]; if (primJ->IsLight()) break; else { Primitive::E_INTERSECT_RESULT result = primJ->Intersect(shadowFeelerRay, LDist); if (result == Primitive::HIT && LDist <= lightToHitPointDist) { shade = 0.0f; break; } } } ci::Vec3f N = hitPrim->GetNormal(hitPoint); float dotLN = L.dot(N); ci::Vec3f R = (L - 2.0f * dotLN * N).normalized(); ci::Vec3f V = inRay.getDirection().normalized(); if (dotLN > 0) { //calculate diffuse component float diffuseC = dotLN * hitPrim->GetMaterial().GetDiffuseCoefficient(); accumColor += diffuseC * hitPrim->GetMaterial().GetDiffuseColor() * light->GetMaterial().GetDiffuseColor() * shade; float dotVR = V.dot(R); if (dotVR > 0) { //calculate specular component float specularC = ci::math<float>::pow(dotVR, 20) * hitPrim->GetMaterial().GetSpecularCoefficient(); accumColor += specularC * hitPrim->GetMaterial().GetSpecularColor() * light->GetMaterial().GetDiffuseColor() * shade; } } } } } {//reflection if (hitPrim->GetMaterial().GetReflectionCoefficient() > 0.0f) { ci::Vec3f N = hitPrim->GetNormal(hitPoint); ci::Vec3f V = inRay.getDirection().normalized(); float dotVN = V.dot(N); ci::Vec3f R = (V - 2.0f * dotVN * N).normalized(); float reflectDist = 10000.0f; ci::ColorA reflectedColor = Raytrace(ci::Ray(hitPoint + R * ci::EPSILON_VALUE * 2, R), inDepth + 1, reflectDist, inRefractIndex); accumColor += reflectedColor * hitPrim->GetMaterial().GetDiffuseColor() * hitPrim->GetMaterial().GetReflectionCoefficient(); } } {//refraction if (hitPrim->GetMaterial().GetRefractionCoefficient() > 0.0f) { float refractIndex = hitPrim->GetMaterial().GetRefractionCoefficient(); float n = inRefractIndex / refractIndex; ci::Vec3f N = hitPrim->GetNormal(hitPoint) * (int)result; float cosI = N.dot(inRay.getDirection()); //float I = acos(cosI); float cosT2 = 1.0f - n * n * (1.0f - cosI * cosI); //float sinT2 = n * n * (1.0f - cosI * cosI); if (cosT2 >= 0.0f) { //if (sinT2 <= 1.0f) { //Vec3f T = ((n * inRay.getDirection()) - (n + sqrtf(1 - sinT2)) * N).normalized(); float cosT = sqrtf(cosT2); Vec3f T = ((n * inRay.getDirection()) - (n * cosI + sqrtf(cosT2)) * N).normalized(); float refractDist = 10000.0f; ci::ColorA refractedColor = Raytrace(ci::Ray(hitPoint + T * ci::EPSILON_VALUE * 1, T), inDepth + 1, refractDist, refractIndex); accumColor += refractedColor * hitPrim->GetMaterial().GetDiffuseColor() * hitPrim->GetMaterial().GetRefractionCoefficient(); } } } {//diffuse reflection - for color bleeding, ambient occlusion } {//soft shadows } {//anti-aliasing my multi-sampling } return accumColor; } }
Colour RayTracer::CalculateLighting(std::vector<Light*>* lights, Vector3* campos, RayHitResult* hitresult) { Colour outcolour; std::vector<Light*>::iterator lit_iter = lights->begin(); //Retrive the material for the intersected primitive Primitive* prim = (Primitive*)hitresult->data; Material* mat = prim->GetMaterial(); //the default output colour is the ambient colour outcolour = mat->GetAmbientColour(); // The hack f***s stuff up. //This is a hack to set a checker pattern on the planes //Do not modify it if (((Primitive*)hitresult->data)->m_primtype == Primitive::PRIMTYPE_Plane) { int dx = (hitresult->point[0]/2.0); int dy = (hitresult->point[1]/2.0); int dz = (hitresult->point[2]/2.0); if (dx % 2 || dy % 2 || dz % 2) { outcolour.red = 1.0; outcolour.green = 1.0; outcolour.blue = 1.0; } else { outcolour.red = 0.0; outcolour.green = 0.0; outcolour.blue = 0.0; } } ////Go through all the light sources in the scene //and calculate the lighting at the intersection point if (m_traceflag & TRACE_DIFFUSE_AND_SPEC) { while (lit_iter != lights->end()) { Vector3 light_pos = (*lit_iter)->GetLightPosition(); //position of the light source Vector3 normal = hitresult->normal; //surface normal at intersection Vector3 surface_point = hitresult->point; //location of the intersection on the surface //TODO: Calculate the surface colour using the illumination model from the lecture notes // 1. Compute the diffuse term // 2. Compute the specular term using either the Phong model or the Blinn-Phong model // 3. store the result in outcolour // DONE outcolour += CalculateDiffuseLighting((light_pos - surface_point).Normalise(), normal, **lit_iter, *mat); outcolour += CalculateSpecularLighting(surface_point, normal, light_pos - surface_point, *campos, **lit_iter, *mat); double dist = (light_pos - surface_point).Norm(); double att = 1.0 / (1.0 + (0 * dist) + (0.002 * dist * dist)); outcolour *= att; lit_iter++; } } // light and surface pont return outcolour; }