Esempio n. 1
0
Color traceRay(Ray* ray, Scene* scene, int objectCount, int lightCount, int maxBounces, double ambientLighting) {
	Color shaderResult (0,0,0);
	Ray* shadowRay = new Ray();
	Ray* reflectionRay = new Ray();
	RayIntersection primaryObjectHit = testRayIntersection(ray, scene, objectCount, 0, MINIMAL_DISTANCE);

	if(primaryObjectHit.objectId >= 0) {
		Object* sceneObject = scene->getObjectList().at(primaryObjectHit.objectId);
		// calulate brightness and specularity
		Color specular (0,0,0);
		Color diffuse (0,0,0);
		Color reflection (0,0,0);
		
		Vect intersectionPoint = primaryObjectHit.location;
		Color ambient = sceneObject->getColorAt(intersectionPoint).scale(ambientLighting);
		shadowRay->setOrigin(intersectionPoint);

		Vect normalAtIntersection = sceneObject->getNormalAt(intersectionPoint);
		Vect reflectionDirection = ray->getReflectingDirection(normalAtIntersection);
		

		double lightImportance = 1;
		if(lightCount > 1) {
			lightImportance = 1.0 / lightCount;
		}

		for(int lightIndex = 0; lightIndex < lightCount; lightIndex++) {
			Light *lightSource = scene->getLightList().at(lightIndex);
			Vect pointToLightVect = lightSource->getPosition().subtract(intersectionPoint);
			Vect lightDirection = pointToLightVect.normalize();

			// Test if light is visible or hidden to render shadows
			double diffuseFactor = normalAtIntersection.dot(lightDirection);
			double specularFactor = reflectionDirection.dot(lightDirection);
			bool shadowed = false;

			if(diffuseFactor > 0) // object is facing the light source - add diffuse
			{
				// check if it is shadowed;
				shadowRay->setDirection(lightDirection);
				double lightDistance = pointToLightVect.magnitude();
				shadowed = (testRayIntersection(shadowRay, scene, objectCount, lightDistance, MINIMAL_DISTANCE).objectId > -1);
			}

			if(!shadowed && diffuseFactor > 0) {
				diffuse = diffuse.add(sceneObject->getColorAt(intersectionPoint).scale(diffuseFactor));
			}

			if(!shadowed && specularFactor > 0 && sceneObject->getMaterial().getRoughness() > 0) {
				specular = specular.add(lightSource->getColor().scale(pow(specularFactor, 10) * sceneObject->getMaterial().getRoughness()));
			}
			
		}		
		

		if(maxBounces > 0 && sceneObject->getMaterial().getReflectivity() > 0) {
			reflectionRay->setOrigin(intersectionPoint);
			reflectionRay->setDirection(reflectionDirection);
			reflection = traceRay(reflectionRay, scene, objectCount, lightCount, --maxBounces, ambientLighting).scale(sceneObject->getMaterial().getReflectivity() * 0.25);
		}


		shaderResult = ambient.add(diffuse).add(specular).add(reflection).normalize();
	} else {
		shaderResult = scene->getBackgroundColor();
	}

	delete shadowRay;
	delete reflectionRay;

	return shaderResult;
}