public Color ShadeHit(Comps comps, int remaining = 5) { var result = Color.Black; foreach (var light in this.Lights) { var surface = comps.Object.Material.Lighting( comps.Object, light, comps.OverPoint, comps.Eye, comps.Normal, light.IntensityAt(comps.OverPoint, this)); var reflected = this.ReflectedColor(comps, remaining); var refracted = this.RefractedColor(comps, remaining); var material = comps.Object.Material; if (material.Reflective > 0 && material.Transparency > 0) { var reflectance = comps.Schlick(); result += surface + reflected * reflectance + refracted * (1 - reflectance); } else { result += surface + reflected + refracted; } } return(result); }
public Color RefractedColor(Comps comps, int remaining = 5) { if (remaining < 1 || comps.Object.Material.Transparency == 0) { return(Color.Black); } // Find the ratio of first index of refraction to the second. // (Yup, this is inverted from the definition of Snell's Law.) var n_ratio = comps.n1 / comps.n2; // cos(theta_i) is the same as the dot product of the two vectors var cos_i = comps.Eye.Dot(comps.Normal); // Find sin(theta_t)^2 via trigonometric identity var sin2_t = n_ratio * n_ratio * (1 - cos_i * cos_i); if (sin2_t > 1) { return(Color.Black); } Interlocked.Increment(ref Stats.SecondaryRays); // Find cos(theta_t) via trigonometric identity var cos_t = Math.Sqrt(1.0 - sin2_t); // Compute the direction of the refracted ray var direction = comps.Normal * (n_ratio * cos_i - cos_t) - comps.Eye * n_ratio; // Create the refracted ray var refract_ray = new Ray(comps.UnderPoint, direction, RayType.Refraction); // Find the color of the refracted ray, making sure to multiply // by the transparency value to account for any opacity return(this.ColorAt(refract_ray, remaining - 1) * comps.Object.Material.Transparency); }
public Color ReflectedColor(Comps comps, int remaining = 5) { if (remaining < 1 || comps.Object.Material.Reflective == 0) { return(Color.Black); } var specularComp = Color.White; if (comps.Object.Material.SpecularMap != null) { specularComp = comps.Object.Material.SpecularMap.PatternAtShape(comps.Object, comps.OverPoint); } Interlocked.Increment(ref Stats.SecondaryRays); var reflectRay = new Ray(comps.OverPoint, comps.Reflect, RayType.Reflection); var color = this.ColorAt(reflectRay, remaining - 1); return(color * comps.Object.Material.Reflective * specularComp); }