public Color ColorAt(Ray r, int remaining) { List <Intersection> xs = IntersectWorld(r); Intersection i = Intersection.Hit(xs); if (i is null) { return(new Color(0, 0, 0)); } else { Computations comps = Computations.PrepareComputations(i, r, xs); return(ShadeHit(comps, remaining)); } }
public static double Schlick(Computations comps) { double cos = Tuple.Dot(comps.eyev, comps.normalv); if (comps.n1 > comps.n2) { double n = comps.n1 / comps.n2; double sin2T = Math.Pow(n, 2.0) * (1.0 - Math.Pow(cos, 2.0)); if (sin2T > 1.0) { return(1.0); } double cosT = Math.Sqrt(1.0 - sin2T); cos = cosT; } double r0 = Math.Pow(((comps.n1 - comps.n2) / (comps.n1 + comps.n2)), 2.0); return(r0 + (1 - r0) * Math.Pow((1 - cos), 5.0)); }
// Possibly change lighting call point -> overpoint to fix checkboard pattern public Color ShadeHit(Computations comps, int remaining) { bool shadowed = IsShadowedFromAllLights(comps.overPoint); Color surfaceColor = new Color(0, 0, 0); foreach (Light lt in Lights) { surfaceColor += comps.shape.Material.Lighting(comps.shape, lt, comps.overPoint, comps.eyev, comps.normalv, shadowed); } Color reflectedColor = ReflectedColor(comps, remaining); Color refractedColor = RefractedColor(comps, remaining); Material material = comps.shape.Material; if (material.Reflectivity > 0 && material.Transparency > 0) { double reflectance = Intersection.Schlick(comps); return(surfaceColor + reflectedColor * reflectance + refractedColor * (1.0 - reflectance)); } return(surfaceColor + reflectedColor + refractedColor); }
public static Computations PrepareComputations(Intersection i, Ray r, List <Intersection> xs = null) { if (xs is null) { xs = new List <Intersection>(); xs.Add(i); } Computations comps = new Computations(); comps.t = i.T; comps.shape = i.S; comps.point = r.Position(comps.t); comps.eyev = -r.Direction; comps.normalv = comps.shape.NormalAt(comps.point, i); if (Tuple.Dot(comps.normalv, comps.eyev) < 0) { comps.inside = true; comps.normalv = -comps.normalv; } else { comps.inside = false; } comps.reflectv = Tuple.Reflect(r.Direction, comps.normalv); comps.overPoint = comps.point + comps.normalv * Globals.EPSILON; comps.underPoint = comps.point - comps.normalv * Globals.EPSILON; List <Shape> containers = new List <Shape>(); foreach (Intersection j in xs) { if (Globals.EqualityOfDouble(j.T, i.T) && j.S == i.S) { if (containers.Count == 0) { comps.n1 = 1.0; } else { comps.n1 = containers[containers.Count - 1].Material.RefractiveIndex; } } if (containers.Contains(j.S)) { containers.Remove(j.S); } else { containers.Add(j.S); } if (Globals.EqualityOfDouble(j.T, i.T) && j.S == i.S) { if (containers.Count == 0) { comps.n2 = 1.0; } else { comps.n2 = containers[containers.Count - 1].Material.RefractiveIndex; } break; } } return(comps); }