public RtColor ShadeHit(Computations computations, int remaining) { var colorTotal = RtColor.Black; foreach (var light in Lights) { // var inShadow = IsShadowed(light.Position, computations.OverPosition); var intensity = light.IntensityAt(computations.OverPosition, this); var surface = computations.Shape.Material.Lighting( computations, light, intensity); var reflected = ReflectedColor(computations, remaining); var refracted = RefractedColor(computations, remaining); var material = computations.Shape.Material; if (material.Reflective > 0 && material.Transparency > 0) { var reflectance = computations.Schlick(); colorTotal += surface + reflected * reflectance + refracted * (1 - reflectance); } else { colorTotal += surface + reflected + refracted; } } return(colorTotal); }
public RtColor ReflectedColor(Computations computations, int remaining) { if (computations.Shape.Material.Reflective == 0 || remaining <= 0) { return(RtColor.Black); } var reflectRay = new Ray(computations.OverPosition, computations.ReflectVector); var reflectColor = ColorAt(reflectRay, remaining - 1); return(reflectColor * computations.Shape.Material.Reflective); }
public RtColor Lighting(Computations computations, Light light, double intensity) { var color = Color; if (Pattern != null) { color = Pattern.PatternAtShape(computations.Shape, computations.OverPosition); } var effectiveColor = color * light.Intensity; var ambient = effectiveColor * Ambient; // var lightPosition = light.Position; RtColor sum = RtColor.Black; foreach (var lightPosition in light.GetSamples()) { var lightVector = (lightPosition - computations.Position).Normalize(); var lightDotNormal = lightVector.Dot(computations.NormalVector); if (lightDotNormal < 0 || intensity == 0) { continue; } sum += effectiveColor * Diffuse * lightDotNormal; var reflectVector = lightVector.Negate().Reflect(computations.NormalVector); var reflectDotEye = reflectVector.Dot(computations.EyeVector); if (reflectDotEye > 0) { var factor = Math.Pow(reflectDotEye, Shininess); sum += light.Intensity * Specular * factor; } } var results = ambient + (sum / light.Samples) * intensity; return(results); }
public RtColor RefractedColor(Computations computations, int remaining) { if (computations.Shape.Material.Transparency == 0 || remaining == 0) { return(RtColor.Black); } var nRatio = computations.n1 / computations.n2; var cosi = computations.EyeVector.Dot(computations.NormalVector); var sin2t = Math.Pow(nRatio, 2) * (1 - Math.Pow(cosi, 2)); if (sin2t > 1) { return(RtColor.Black); } var cost = Math.Sqrt(1.0 - sin2t); var direction = computations.NormalVector * (nRatio * cosi - cost) - computations.EyeVector * nRatio; var refractRay = new Ray(computations.UnderPosition, direction); var color = ColorAt(refractRay, remaining - 1) * computations.Shape.Material.Transparency; return(color); }
public Computations PrepareComputations(Ray ray, IntersectionList intersections) { var computations = new Computations() { Time = Time, Shape = Shape, Position = ray.Position(Time), EyeVector = ray.Direction.Negate(), }; computations.NormalVector = Shape.NormalAt(computations.Position, this); if(computations.NormalVector.Dot(computations.EyeVector) < 0) { computations.Inside = true; computations.NormalVector = computations.NormalVector.Negate(); } else { computations.Inside = false; } computations.ReflectVector = ray.Direction.Reflect(computations.NormalVector); List<Shape> container = new List<Shape>(); if(intersections != null && intersections.Count > 0) { foreach (var intersection in intersections.Items) { if (intersection == this) { if (container.Count == 0) { computations.n1 = 1.0; } else { computations.n1 = container.Last().Material.RefractiveIndex; } } if (container.Contains(intersection.Shape)) { container.Remove(intersection.Shape); } else { container.Add(intersection.Shape); } if (intersection == this) { if (container.Count == 0) { computations.n2 = 1.0; } else { computations.n2 = container.Last().Material.RefractiveIndex; } break; } } } return computations; }