コード例 #1
0
ファイル: raytracer.cpp プロジェクト: patback66/COEN148
// -----------------------------------------------------------
// 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;
}
コード例 #2
0
ファイル: Scene.cpp プロジェクト: akshayloke/RayTracer
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;
	}
}