public Colour CalculateLighting(Intersection intersection, Ray ray, int recursionDepth) { const int maxRecursionDepth = 10; //todo if (recursionDepth > maxRecursionDepth || !ray.IsColourSignificant) { return new Colour(0,0,0); } throw new NotImplementedException(); }
/// <summary> /// Determines whether a given ray intersects with any scene objects (other than excludedObject) /// </summary> /// <param name="ray">The ray to test</param> /// <param name="scene">The scene to test</param> /// <param name="excludedObject">An object that is not tested for intersections</param> /// <param name="intersection">If the intersection test succeeds, contains the closest intersection</param> /// <returns>A value indicating whether or not any scene object intersected with the ray</returns> private bool TryCalculateIntersection(Ray ray, Scene scene, DrawableSceneObject excludedObject, out Intersection intersection) { var closestDistance = float.PositiveInfinity; var closestIntersection = new Intersection(); foreach (var sceneObject in scene.DrawableObjects) { Intersection i; if (sceneObject != excludedObject && sceneObject.TryCalculateIntersection(ray, out i)) { if (i.Distance < closestDistance) { closestDistance = i.Distance; closestIntersection = i; } } } if (closestDistance == float.PositiveInfinity) { intersection = new Intersection(); return false; } else { intersection = closestIntersection; return true; } }
/// <summary> /// Recursive algorithm base /// </summary> /// <param name="intersection">The intersection the recursive step started from</param> /// <param name="ray">The ray, starting from the intersection</param> /// <param name="scene">The scene to trace</param> private Color CalculateRecursiveColor(Intersection intersection, Scene scene, int depth) { // Ambient light: var color = Color.Lerp(Color.Black, intersection.Color * scene.AmbientLightColor, scene.AmbientLightIntensity); foreach (Light light in scene.Lights) { var lightContribution = new Color(); var towardsLight = (light.Position - intersection.Point).Normalized(); var lightDistance = Util.Distance(intersection.Point, light.Position); // Accumulate diffuse lighting: var lightEffectiveness = Vector3.Dot(towardsLight, intersection.Normal); if (lightEffectiveness > 0.0f) { lightContribution = lightContribution + (intersection.Color * light.GetIntensityAtDistance(lightDistance) * light.Color * lightEffectiveness); } // Render shadow var shadowRay = new Ray(intersection.Point, towardsLight); Intersection shadowIntersection; if (TryCalculateIntersection(shadowRay, scene, intersection.ObjectHit, out shadowIntersection) && shadowIntersection.Distance < lightDistance) { var transparency = shadowIntersection.ObjectHit.Material.Transparency; var lightPassThrough = Util.Lerp(.25f, 1.0f, transparency); lightContribution = Color.Lerp(lightContribution, Color.Zero, 1 - lightPassThrough); } color += lightContribution; } if (depth < ReflectionDepth) { // Reflection ray var objectReflectivity = intersection.ObjectHit.Material.Reflectivity; if (objectReflectivity > 0.0f) { var reflectionRay = GetReflectionRay(intersection.Point, intersection.Normal, intersection.ImpactDirection); Intersection reflectionIntersection; if (TryCalculateIntersection(reflectionRay, scene, intersection.ObjectHit, out reflectionIntersection)) { color = Color.Lerp(color, CalculateRecursiveColor(reflectionIntersection, scene, depth + 1), objectReflectivity); } } // Refraction ray var objectRefractivity = intersection.ObjectHit.Material.Refractivity; if (objectRefractivity > 0.0f) { var refractionRay = GetRefractionRay(intersection.Point, intersection.Normal, intersection.ImpactDirection, objectRefractivity); Intersection refractionIntersection; if (TryCalculateIntersection(refractionRay, scene, intersection.ObjectHit, out refractionIntersection)) { var refractedColor = CalculateRecursiveColor(refractionIntersection, scene, depth + 1); color = Color.Lerp(color, refractedColor, 1 - (intersection.ObjectHit.Material.Opacity)); } } } color = color.Limited; return color; }
protected override Tuple LocalNormalAt(Tuple localPoint, Intersection hit) { return(localPoint - Tuple.Point(0, 0, 0)); }
private Color Shade(Intersection isect, Scene scene, int depth) { var d = isect.Ray.Dir; var pos = new Vector( isect.Dist * isect.Ray.Dir.X + isect.Ray.Start.X, isect.Dist * isect.Ray.Dir.Y + isect.Ray.Start.Y, isect.Dist * isect.Ray.Dir.Z + isect.Ray.Start.Z ); var normal = isect.Thing.Normal(pos); var reflectDir = Vector.Minus(d, Vector.Times(2 * Vector.Dot(normal, d), normal)); // TODO: whats wrong with this? /*var reflectDir = new Vector( d.X - (2.0f * normal.X * d.X * normal.X), d.Y - (2.0f * normal.Y * d.Y * normal.Y), d.Z - (2.0f * normal.Z * d.Z * normal.Z) );*/ Color natColor = GetNaturalColor(isect.Thing, pos, normal, reflectDir, scene); Color ret = new Color(Color.DefaultColor.R + natColor.R,Color.DefaultColor.R + natColor.G, Color.DefaultColor.R + natColor.B); if (depth >= MaxDepth) { return new Color(ret.R + Color.Grey.R, ret.G + Color.Grey.G, ret.B + Color.Grey.B); } Color refColor = GetReflectionColor(isect.Thing, new Vector(pos.X + .001f * reflectDir.X, pos.Y + .001f * reflectDir.Y, pos.Z + .001f * reflectDir.Z), normal, reflectDir, scene, depth); return new Color(ret.R + refColor.R, ret.G + refColor.G, ret.B + refColor.B); }
private Intersection ClosestIntersection(Ray ray, Scene scene) { Intersection closest = new Intersection() { Dist = float.MaxValue, Thing = null, Ray = null }; for (int i = 0; i < scene.Things.Length; i++) { var thing = scene.Things[i]; Intersection intersection = thing.Intersect(ray); if (intersection != null && intersection.Dist < closest.Dist) { closest = intersection; } } return closest.Thing == null ? null : closest; }
// Get illumination for lightsource with index i private Vector3 CalculateIllumination(Intersection intersect, int i, bool drawDebugLine) { Ray shadowRay = new Ray(); shadowRay.origin = intersect.intersectionPoint; // Keep an non-normalized directon in case we need to calculate length later Vector3 rayDirection = lights[i].pos - intersect.intersectionPoint; shadowRay.t = rayDirection.Length(); // Normalize for calulating intersections shadowRay.direction = Vector3.Normalize(rayDirection); // Offset the origin by a small margin shadowRay.origin += 0.001f * shadowRay.direction; // Check if any primitives intersect with this shadowray Intersection lightBlocker = Intersect(shadowRay); if (lightBlocker != null) { // Intersection point is in the shadow, return black. if (drawDebugLine) { Debugger.DrawDebugLine( shadowRay.origin.X, shadowRay.origin.Z, lightBlocker.intersectionPoint.X, lightBlocker.intersectionPoint.Z, System.Drawing.Color.Orange); } return(new Vector3(0, 0, 0)); } //shadowRay = new Ray(); //shadowRay.origin = intersect.intersectionPoint; //// Keep an non-normalized directon in case we need to calculate length later //rayDirection = lights[i].pos - intersect.intersectionPoint; //shadowRay.t = rayDirection.Length(); //// Normalize for calulating intersections //shadowRay.direction = Vector3.Normalize(rayDirection); //// Offset the origin by a small margin //shadowRay.origin += 0.001f * shadowRay.direction; //// Check if any primitives intersect with this shadowray //lightBlocker = Intersect(shadowRay); // Intersection point is in the shadow, return black. if (drawDebugLine) { Debugger.DrawDebugLine( shadowRay.origin.X, shadowRay.origin.Z, lights[i].pos.X, lights[i].pos.Z, System.Drawing.Color.Yellow); } // No intersection happened so we can calculate light color/intensity: float dist = rayDirection.Length(); float attenuation = 1 / (dist * dist); return(lights[0].color * Vector3.Dot(intersect.normal, shadowRay.direction) * attenuation); }
public override Vector LocalNormalAt(Point local_point, Intersection hit = null) => this.Normal;
/// <summary> /// Determines whether a given ray intersects with any scene objects (other than excludedObject) /// </summary> /// <param name="ray">The ray to test</param> /// <param name="scene">The scene to test</param> /// <param name="excludedObject">An object that is not tested for intersections</param> /// <param name="intersection">If the intersection test succeeds, contains the closest intersection</param> /// <returns>A value indicating whether or not any scene object intersected with the ray</returns> private bool TryCalculateIntersection(Ray ray, Scene scene, DrawableSceneObject excludedObject, out Intersection intersection) { var closestDistance = float.PositiveInfinity; var closestIntersection = new Intersection(); foreach (var sceneObject in scene.DrawableObjects) { Intersection i; if (sceneObject != excludedObject && sceneObject.TryCalculateIntersection(ray, out i)) { if (i.Distance < closestDistance) { closestDistance = i.Distance; closestIntersection = i; } } } if (closestDistance == float.PositiveInfinity) { intersection = new Intersection(); return(false); } else { intersection = closestIntersection; return(true); } }
/// <summary> /// Recursive algorithm base /// </summary> /// <param name="intersection">The intersection the recursive step started from</param> /// <param name="ray">The ray, starting from the intersection</param> /// <param name="scene">The scene to trace</param> private Color CalculateRecursiveColor(Intersection intersection, Scene scene, int depth) { // Ambient light: var color = Color.Lerp(Color.Black, intersection.Color * scene.AmbientLightColor, scene.AmbientLightIntensity); foreach (Light light in scene.Lights) { var lightContribution = new Color(); var towardsLight = (light.Position - intersection.Point).Normalized(); var lightDistance = Util.Distance(intersection.Point, light.Position); // Accumulate diffuse lighting: var lightEffectiveness = VectorMath.DotProduct(towardsLight, intersection.Normal); if (lightEffectiveness > 0.0f) { lightContribution = lightContribution + (intersection.Color * light.GetIntensityAtDistance(lightDistance) * light.Color * lightEffectiveness); } // Render shadow var shadowRay = new Ray(intersection.Point, towardsLight); Intersection shadowIntersection; if (TryCalculateIntersection(shadowRay, scene, intersection.ObjectHit, out shadowIntersection) && shadowIntersection.Distance < lightDistance) { var transparency = shadowIntersection.ObjectHit.Material.Transparency; var lightPassThrough = Util.Lerp(.25f, 1.0f, transparency); lightContribution = Color.Lerp(lightContribution, Color.Zero, 1 - lightPassThrough); } color += lightContribution; } if (depth < ReflectionDepth) { // Reflection ray var objectReflectivity = intersection.ObjectHit.Material.Reflectivity; if (objectReflectivity > 0.0f) { var reflectionRay = GetReflectionRay(intersection.Point, intersection.Normal, intersection.ImpactDirection); Intersection reflectionIntersection; if (TryCalculateIntersection(reflectionRay, scene, intersection.ObjectHit, out reflectionIntersection)) { color = Color.Lerp(color, CalculateRecursiveColor(reflectionIntersection, scene, depth + 1), objectReflectivity); } } // Refraction ray var objectRefractivity = intersection.ObjectHit.Material.Refractivity; if (objectRefractivity > 0.0f) { var refractionRay = GetRefractionRay(intersection.Point, intersection.Normal, intersection.ImpactDirection, objectRefractivity); Intersection refractionIntersection; if (TryCalculateIntersection(refractionRay, scene, intersection.ObjectHit, out refractionIntersection)) { var refractedColor = CalculateRecursiveColor(refractionIntersection, scene, depth + 1); color = Color.Lerp(color, refractedColor, 1 - (intersection.ObjectHit.Material.Opacity)); } } } color = color.Limited; return(color); }
//public Computation(float t, RayObject rayObject, // Point point, Vector3 eyeV, // Vector3 normalV, bool inside, // Vector3 reflectV, float n1, // float n2) //{ // this.t = t; // this.rayObject = rayObject; // this.point = point; // this.eyeV = eyeV; // this.normalV = normalV; // this.inside = inside; // overPoint = point + normalV * Utilities.shadowPointEpsilon; // this.reflectV = reflectV; // this.n1 = n1; // this.n2 = n2; //} public Computation(Intersection i, Ray r, List <Intersection> xs = null) { this.t = i.t; this.rayObject = i.rayObject; this.point = r.GetPointPosition(i.t); this.eyeV = -r.direction; this.normalV = rayObject.GetNormal(point); // Checks if eye vector and normal are pointing in the same direction // if dot product is less than zero that point in the same direction. if (Vector3.Dot(eyeV, normalV) < 0) { inside = true; normalV = -normalV; } else { inside = false; } // If a List<Intersection> parameter is not passed into the method // create one using i as the only intersection in the list if (xs == null) { xs = new List <Intersection>() { i } } ; // Transparency Intersections algorithm List <RayObject> containers = new List <RayObject>(); foreach (Intersection intersect in xs) { // n1 if (i == intersect) { if (containers.Count == 0) { this.n1 = 1.0f; } else { this.n1 = containers.Last <RayObject>().material.RefractIndex; } } if (containers.Contains(intersect.rayObject)) { containers.Remove(intersect.rayObject); //Console.WriteLine("Object Removed: " + intersect.rayObject.ToString()); } else { containers.Add(intersect.rayObject); //Console.WriteLine("Object Added: " + intersect.rayObject.ToString()); } //Console.WriteLine("List Lenght: " + containers.Count); // n2 if (i == intersect) { if (containers.Count == 0) { this.n2 = 1.0f; } else { this.n2 = containers[containers.Count - 1].material.RefractIndex; } break; } } this.reflectV = Vector3.Reflection(r.direction, this.normalV); this.overPoint = point + normalV * Utilities.OVER_POINT_EPSILON; this.underPoint = point - normalV * Utilities.UNDER_POINT_EPSILON; }
public static IntersectionState Prepare(ref Intersection i, ref Ray r) => Prepare(ref i, ref r, new List <Intersection> { i });
protected override Tuple LocalNormalAt(Tuple p, Intersection hit) { return(Tuple.Vector(0, 1, 0)); }