private Vector TraceRay(Vector O, Vector D, double tMin, double tMax, int depth) { var(closestPrimitive, closest_t) = ClosestIntersection(O, D, tMin, tMax); if (closestPrimitive == null) { return(Vector.FromColor(_options.BgColor)); } var view = D.Multiply(-1); var P = O.Add(D.Multiply(closest_t)); Vector normal = new Vector(); if (closestPrimitive is Plane plane) { normal = plane.Normal; } if (closestPrimitive is Sphere sphere) { if (sphere.LightTransparent) { return(Vector.FromColor(sphere.Color)); } normal = P.Subtract(sphere.Center); } if (closestPrimitive is Box box) { normal = box.GetNormal(O, D, tMin); } if (closestPrimitive is Surface surface) { normal = surface.GetNormal(O, D, closest_t); } if (closestPrimitive is Torus torus) { normal = torus.GetNormal(O, D, closest_t); } if (closestPrimitive is Disk disk) { normal = disk.GetNormal(); } normal = normal.Multiply(1 / normal.Lenght()); //unit vector if (normal.DotProduct(D) > 0) { normal = normal.Multiply(-1); } var color = closestPrimitive.Color; if (closestPrimitive is Plane) { var x = (int)Math.Round(O.D1 + D.D1 * closest_t) % 2; var z = (int)Math.Round(O.D3 + D.D3 * closest_t) % 2; if (x == z) { color = Color.FromRgb(0, 0, 0); } } var local_color = Vector.FromColor(color) .Multiply(ComputeLighting(P, normal, view, closestPrimitive.Specular)); var r = closestPrimitive.Reflect; if (depth <= 0 || r <= 0) { return(local_color); } var R = ReflectRay(view, normal); var reflectedColor = TraceRay(P, R, 0.001d, double.PositiveInfinity, depth - 1); return(local_color.Multiply(1 - r).Add(reflectedColor.Multiply(r))); }
private Vector ReflectRay(Vector r, Vector normal) { return(normal.Multiply(2 * r.DotProduct(normal)).Subtract(r)); }