private void HandleRefraction(Computations comps, IntersectionCollection xs) { var containers = new List<Shape>(); foreach (var intersection in xs.Intersections) { if (intersection.T == T) comps.n1 = containers.Any() ? containers.Last().Material.RefractiveIndex : 1.0; if (containers.Contains(intersection.Object)) containers.Remove(intersection.Object); else containers.Add(intersection.Object); if (intersection.T == T) { comps.n2 = containers.Any() ? containers.Last().Material.RefractiveIndex : 1.0; break; } } }
internal Color RefractedColor(Computations comps, int remaining) { if (remaining == 0) { return(Color.Black); } if (comps.Object.Material.Transparency == 0) { return(Color.Black); } // Snell's law var nRatio = comps.n1 / comps.n2; var cosTheta_i = comps.EyeVector.Dot(comps.NormalVector); var sinTheta_t_squared = Math.Pow(nRatio, 2) * (1 - Math.Pow(cosTheta_i, 2)); if (sinTheta_t_squared > 1) { return(Color.Black); } var cosTheta_t = Math.Sqrt(1 - sinTheta_t_squared); var refractedRayDirection = comps.NormalVector * (nRatio * cosTheta_i - cosTheta_t) - comps.EyeVector * nRatio; var refractedRay = new Ray(comps.UnderPoint, refractedRayDirection); // Find the color of the refracted ray, making sure to multiply // by the transparency value to account for any opacity var color = ColorAt(refractedRay, --remaining) * comps.Object.Material.Transparency; return(color); }
internal Color ReflectedColor(Computations comps, int remaining = 1) { if (remaining < 1) { return(Color.Black); } if (comps.Object.Material.Reflective == 0.0) { return(Color.Black); } var reflectRay = new Ray(comps.OverPoint, comps.ReflectV); var color = ColorAt(reflectRay, --remaining); return(color * comps.Object.Material.Reflective); }
internal Color ShadeHit(Computations comps, int remaining = 1) { var isShadowed = IsShadowed(comps.OverPoint); var surface = comps.Object.Material.Lighting(comps.Object, LightSource, comps.OverPoint, comps.EyeVector, comps.NormalVector, isShadowed); var reflected = ReflectedColor(comps, remaining); var refracted = RefractedColor(comps, remaining); var material = comps.Object.Material; if (material.Reflective > 0 && material.Transparency > 0) { var reflectance = comps.Schlick(); return(surface + reflected * reflectance + refracted * (1 - reflectance)); } return(surface + reflected + refracted); }
public Computations PrepareComputations(Ray ray, IntersectionCollection xs = null) { var c = new Computations(); c.T = T; c.Object = Object; c.Point = ray.Position(T); c.EyeVector = -ray.Direction; c.NormalVector = Object.NormalAt(c.Point, this); if (c.NormalVector.Dot(c.EyeVector) < 0) { c.Inside = true; c.NormalVector = -c.NormalVector; } c.OverPoint = c.Point + c.NormalVector * C.Epsilon; c.UnderPoint = c.Point - c.NormalVector * C.Epsilon; c.ReflectV = ray.Direction.Reflect(c.NormalVector); xs = xs ?? new IntersectionCollection(); HandleRefraction(c, xs); return c; }