//Check the material of the hit object and if the transparency is 0, return black. //Return calculated refracted value is it is transparent public Color RefractedColor(Computations c, int remaining = 1) { if (Utility.FE(c.rayObject.material.Transparency, 0) || remaining == 0) { return(Color.black); } //Check for infinite internal reflection double nRatio = c.n1 / c.n2; double cosI = Vector.Dot(c.eye, c.normal); double sin2T = nRatio * nRatio * (1 - (cosI * cosI)); if (sin2T > 1) { return(Color.black); } double cosT = Math.Sqrt(1.0 - sin2T); Vector direction = c.normal * (nRatio * cosI - cosT) - c.eye * nRatio; Ray refractRay = new Ray(c.underPoint, direction); Color refractedColor = ColorAt(refractRay, remaining - 1) * c.rayObject.material.Transparency; //Replace later with code for refraction calculations return(refractedColor); }
public Color ReflectedColor(Computations c, int remaining = 1) { if (remaining == 0 || Utility.FE(c.rayObject.material.Reflective, 0.0)) { return(Color.black); } Ray reflectionRay = new Ray(c.overPoint, c.reflectVector); return(ColorAt(reflectionRay, remaining - 1) * c.rayObject.material.Reflective); }
public Color ColorAt(Ray ray, int remaining = 1) { List <Intersection> hits = this.Intersections(ray); if (hits.Count == 0) { return(Color.black); } Intersection hit = this.Hit(hits); Computations c = Computations.Prepare(hit, ray, hits); Color finalColor = Scene.current.ShadeHit(c, remaining); return(finalColor); }
public double Schlick(Computations c) { double cos = Vector.Dot(c.eye, c.normal); if (c.n1 > c.n2) { double n = c.n1 / c.n2; double sin2T = (n * n) * (1.0 - (cos * cos)); if (sin2T > 1.0) { return(1.0); } double cosT = Math.Sqrt(1.0 - sin2T); cos = cosT; } double r0 = Math.Pow((c.n1 - c.n2) / (c.n1 + c.n2), 2); return(r0 + (1 - r0) * Math.Pow((1 - cos), 5)); }
public Color ShadeHit(Computations c, int remaining = 1) { if (c == null) { return(Color.black); } Color surfaceColor = new Color(0, 0, 0); for (int i = 0; i < lights.Count; i++) { //Is this light in shadow? if (c.rayObject.canReceiveShadows) { bool isShadow = IsShadowed(c.overPoint, lights[i]); surfaceColor += c.rayObject.Lighting(c.point, lights[i], c.eye, c.normal, isShadow); } } Color reflected = this.ReflectedColor(c, remaining); Color refracted = this.RefractedColor(c, remaining); if (c.rayObject.material.Reflective > 0 && c.rayObject.material.Transparency > 0) { double reflectance = this.Schlick(c); return(surfaceColor + reflected * reflectance + refracted * (1.0 - reflectance)); } return(surfaceColor + reflected + refracted); }
public static Computations Prepare(Intersection i, Ray ray, List <Intersection> xs) { if (i == null) { return(null); } Point temp = ray.Position(i.t); Computations c = new Computations(); c.rayObject = i.rayObject; c.t = i.t; c.point = temp; c.eye = -ray.direction.Normalize(); c.normal = i.rayObject.GetNormal(temp, i).Normalize(); c.n1 = RefractiveIndex.Vacuum; c.n2 = RefractiveIndex.Vacuum; if (c.normal.Dot(c.eye) < 0) { c.inside = true; c.normal = -c.normal; } else { c.inside = false; } //Transparency Intersections algorithm if (xs != null) { List <RayObject> container = new List <RayObject>(); for (int x = 0; x < xs.Count; x++) { if (i == xs[x]) { if (container.Count == 0) { c.n1 = RefractiveIndex.Vacuum; } else { c.n1 = container.Last <RayObject>().material.RefracIndex; } } if (container.Contains(xs[x].rayObject)) { container.Remove(xs[x].rayObject); } else { container.Add(xs[x].rayObject); } if (i == xs[x]) { if (container.Count == 0) { c.n2 = RefractiveIndex.Vacuum; } else { c.n2 = container.Last <RayObject>().material.RefracIndex; } break; } } } c.reflectVector = Vector.Reflect(ray.direction, c.normal); c.overPoint = c.point + (c.normal * Constants.epsilon); c.underPoint = c.point - (c.normal * Constants.epsilon); return(c); }