public Light(Vec3 position, Vec3 color) { Position = position; Color = color; }
public Sphere(Vec3 c, Num r, Vec3 clr, Num refl = 0, Num trans = 0) { Center = c; Radius = r; Color = clr; Reflection = refl; Transparency = trans; }
public static Vec3 Normal(Sphere sphere, Vec3 pos) { return Vec3.Normalize(pos - sphere.Center); }
public static Num Magnitude(Vec3 v) { return (Num)Math.Sqrt((v.X*v.X) + (v.Y*v.Y) + (v.Z*v.Z)); }
public static Vec3 Normalize(Vec3 v) { return v / (Num)Math.Sqrt((v.X*v.X) + (v.Y*v.Y) + (v.Z*v.Z)); }
private static Vec3 trace(Ray ray, Scene scene, int depth) { var nearest = Num.MaxValue; Sphere obj = null; // search the scene for nearest intersection foreach (var o in scene.Objects) { var distance = Num.MaxValue; if (Sphere.Intersect(o, ray, out distance)) { if (distance < nearest) { nearest = distance; obj = o; } } } if (obj == null) { return(Vec3.Zero); } var point_of_hit = ray.Org + (ray.Dir * nearest); var normal = Sphere.Normal(obj, point_of_hit); bool inside = false; if (Vec3.Dot(normal, ray.Dir) > 0) { inside = true; normal = -normal; } Vec3 color = Vec3.Zero; var reflection_ratio = obj.Reflection; foreach (var l in scene.Lights) { var light_direction = Vec3.Normalize(l.Position - point_of_hit); Ray r; r.Org = point_of_hit + (normal * 1e-5f); r.Dir = light_direction; // go through the scene check whether we're blocked from the lights bool blocked = false; foreach (var o in scene.Objects) { if (Sphere.Intersect(o, r)) { blocked = true; break; } } if (!blocked) { color += l.Color * Math.Max(0, Vec3.Dot(normal, light_direction)) * obj.Color * (1.0f - reflection_ratio); } } var rayNormDot = Vec3.Dot(ray.Dir, normal); Num facing = Math.Max(0, -rayNormDot); Num fresneleffect = reflection_ratio + ((1 - reflection_ratio) * (Num)Math.Pow((1 - facing), 5)); // compute reflection if (depth < maxDepth && reflection_ratio > 0) { var reflection_direction = ray.Dir + (normal * 2 * rayNormDot * (-1.0f)); Ray r; r.Org = point_of_hit + (normal * 1e-5f); r.Dir = reflection_direction; var reflection = trace(r, scene, depth + 1); color += reflection * fresneleffect; } // compute refraction if (depth < maxDepth && (obj.Transparency > 0)) { var ior = 1.5f; var CE = Vec3.Dot(ray.Dir, normal) * (-1.0f); ior = inside ? (1.0f) / ior : ior; var eta = (1.0f) / ior; var GF = (ray.Dir + normal * CE) * eta; var sin_t1_2 = 1 - (CE * CE); var sin_t2_2 = sin_t1_2 * (eta * eta); if (sin_t2_2 < 1) { var GC = normal * (Num)Math.Sqrt(1 - sin_t2_2); var refraction_direction = GF - GC; Ray r; r.Org = point_of_hit - (normal * 1e-4f); r.Dir = refraction_direction; var refraction = trace(r, scene, depth + 1); color += refraction * (1 - fresneleffect) * obj.Transparency; } } return(color); }
public static Num Dot(Vec3 v1, Vec3 v2) { return (v1.X*v2.X) + (v1.Y*v2.Y) + (v1.Z*v2.Z); }
public static Vec3 Normal(Sphere sphere, Vec3 pos) { return(Vec3.Normalize(pos - sphere.Center)); }
public static Vec3 Normalize(Vec3 v) { return(v / (Num)Math.Sqrt((v.X * v.X) + (v.Y * v.Y) + (v.Z * v.Z))); }
public static Num Magnitude(Vec3 v) { return((Num)Math.Sqrt((v.X * v.X) + (v.Y * v.Y) + (v.Z * v.Z))); }
public static Num Dot(Vec3 v1, Vec3 v2) { return((v1.X * v2.X) + (v1.Y * v2.Y) + (v1.Z * v2.Z)); }