//calculates the color at the given 3D point using phong shading. private Color GetObjectColor(IntersectionTester.Intersection point, Vector3 viewFrom) { Light light = scene.light; Vector3 location = point.intersectionPoint; Vector3 normal = point.intersectionNormal; Vector3 lightDirection = (light.Pos - location); float lightDistance = lightDirection.Length; lightDirection = lightDirection.Normalize(); Vector3 shadowOrigin = location + 0.01f * normal; if (IntersectionTester.GetInShadow(new Ray(shadowOrigin, lightDirection), lightDistance)) { return(scene.ambientLight); } Vector3 reflect = GetReflectionVector(lightDirection, normal).Normalize(); float phongConstant = point.hitObject.phongConstant; float colorFactor = reflect * viewFrom; Color specular = Math.Sign(colorFactor) * (float)Math.Pow(colorFactor, phongConstant) * scene.light.Color; Color diffuse = lightDirection * normal * point.hitObject.DiffuseColor; return(specular + diffuse + scene.ambientLight); }
private Color GetPixelColor(float x, float y) { Vector3 pixelPos = GetWorldSpacePixel(x, y); Vector3 pixelDirection = pixelPos - cameraPos; Ray pixelRay = new Ray(cameraPos, pixelDirection); IntersectionTester.Intersection hit = IntersectionTester.GetClosestObject(pixelRay); SceneObject closestObject = hit.hitObject; if (closestObject == null) { return(backgroundColor); } return(GetColorWithReflections(hit, pixelDirection, 0)); }
//given a point and a view direction, returns the color including reflections private Color GetColorWithReflections(IntersectionTester.Intersection point, Vector3 direction, int depth) { const int MAX_DEPTH = 5; if (depth > MAX_DEPTH) { return(backgroundColor); } List <KeyValuePair <float, Color> > reflections = new List <KeyValuePair <float, Color> > { new KeyValuePair <float, Color>(1 - point.hitObject.reflectivity, GetObjectColor(point, direction)) }; const float REFLECTION_FALLOFF = 0.9f; float currentWeight = REFLECTION_FALLOFF * point.hitObject.reflectivity; IntersectionTester.Intersection currentHit = point; Vector3 currentDirection = direction; if (currentWeight > 0.01f) { Vector3 reflectionVector = GetReflectionVector(currentDirection, currentHit.intersectionNormal).Normalize(); Vector3 reflectionOrigin = currentHit.intersectionPoint + 0.01f * reflectionVector; Ray reflectionRay = new Ray(reflectionOrigin, reflectionVector); currentHit = IntersectionTester.GetClosestObject(reflectionRay); if (currentHit.hitObject != null) { reflections.Add(new KeyValuePair <float, Color>(currentWeight, GetColorWithReflections(currentHit, reflectionVector, depth + 1))); } else { reflections.Add(new KeyValuePair <float, Color>(currentWeight, backgroundColor)); } } return(Color.GetWeightedAverage(reflections)); }