internal void update() { Vector diff = new Vector(position, lookAt); this.direction = -diff.normalize(); this.right = new Vector(0, 1, 0).cross(direction).normalize(); this.down = -right.cross(direction); }
public static Camera Create(Vector pos, Vector lookAt) { Vector forward = Vector.Norm(Vector.Minus(lookAt, pos)); Vector down = new Vector(0, -1, 0); Vector right = Vector.Times(1.5f, Vector.Norm(Vector.Cross(forward, down))); Vector up = Vector.Times(1.5f, Vector.Norm(Vector.Cross(forward, right))); return new Camera() { Pos = pos, Forward = forward, Up = up, Right = right }; }
public static Vector Norm(Vector v) { /*float mag = Mag(v); float div = mag == 0 ? float.PositiveInfinity : 1 / mag; return Times(div, v);*/ float sqrLength, invLength; sqrLength = v.X * v.X + v.Y * v.Y + v.Z * v.Z; invLength = SceneObject.InvSqrt(sqrLength); return new Vector(v.X * invLength, v.Y * invLength, v.Z * invLength); }
private void SetupScene(int numberOfBalls) { scene = new Scene(); scene.Background = new Background(new RayTracer.Color(0.0, 0.0, 0.0), 0.1);//new Background(new Color(.2, .3, .4), 0.5); RayTracer.Vector campos = new RayTracer.Vector(0, 0, -5); scene.Camera = new Camera(campos, campos / -2, new RayTracer.Vector(0, 1, 0).Normalize()); Random rnd = new Random(); for (int i = 0; i < numberOfBalls; i++) { // setup a solid reflecting sphere scene.Shapes.Add(new SphereShape(new RayTracer.Vector(rnd.Next(-100, 100) / 50.0, rnd.Next(-100, 100) / 50.0, rnd.Next(0, 200) / 50.0), .2, new SolidMaterial(new RayTracer.Color(rnd.Next(0, 100) / 100.0, rnd.Next(0, 100) / 100.0, rnd.Next(0, 100) / 100.0), 0.4, 0.0, 2.0))); } // setup the chessboard floor scene.Shapes.Add(new PlaneShape(new RayTracer.Vector(0.1, 0.9, -0.5).Normalize(), 1.2, new ChessboardMaterial(new RayTracer.Color(1, 1, 1), new RayTracer.Color(0, 0, 0), 0.2, 0, 1, 0.7))); scene.Lights.Add(new Light(new RayTracer.Vector(5, 10, -1), new RayTracer.Color(0.8, 0.8, 0.8))); scene.Lights.Add(new Light(new RayTracer.Vector(-3, 5, -15), new RayTracer.Color(0.8, 0.8, 0.8))); }
public MainWindow() { InitializeComponent(); light = new RayTracer.Light(1, new RayTracer.Point(-15, 10, 20)); RayTracer.Point point = new RayTracer.Point(5.3368f, 8.0531f, 9.8769f); RayTracer.Vector direction = new RayTracer.Vector(-0.38363f, -0.42482f, -0.82f); RayTracer.Vector directionUp = new RayTracer.Vector(-0.16485f, 0.90515f, -0.391826f); this.camera = new RayTracer.Camera(-1, point, direction, directionUp, 60f); Button front = (Button)this.FindName("viewButtonFront"); front.Foreground = new SolidColorBrush(Colors.Red); TextBox positionZ, depth; positionZ = (TextBox)this.FindName("positionZ"); positionZ.IsEnabled = false; depth = (TextBox)this.FindName("rectangleDepth"); depth.IsEnabled = false; }
public static Vector Minus(Vector v1, Vector v2) { return new Vector(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z); }
public static bool Equals(Vector v1, Vector v2) { return (v1.X == v2.X) && (v1.Y == v2.Y) && (v1.Z == v2.Z); }
public static float Mag(Vector v) { return SceneObject.Sqrt(Dot(v, v)); }
public static Vector Cross(Vector v1, Vector v2) { return new Vector(((v1.Y * v2.Z) - (v1.Z * v2.Y)), ((v1.Z * v2.X) - (v1.X * v2.Z)), ((v1.X * v2.Y) - (v1.Y * v2.X))); }
public static float Dot(Vector v1, Vector v2) { return (v1.X * v2.X) + (v1.Y * v2.Y) + (v1.Z * v2.Z); }
public override Vector Normal(Vector pos) { return Vector.Norm(Vector.Minus(pos, Center)); }
public double dot(Vector v) { return this.x * v.x + this.y * v.y + this.z * v.z; }
public override Vector Normal(Vector pos) { float vx = pos.X - Center.X; float vy = pos.Y - Center.Y; float vz = pos.Z - Center.Z; float sqrLength, invLength; sqrLength = vx * vx + vy * vy + vz * vz; invLength = SceneObject.InvSqrt(sqrLength); return new Vector(vx * invLength, vy * invLength, vz * invLength); }
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); }
public Plane(Vector normal, double distance, Color color) { this.distance = distance; this.normal = normal.normalize(); this.color = color; }
public static Vector Times(float n, Vector v) { return new Vector(v.X * n, v.Y * n, v.Z * n); }
private Color GetNaturalColor(SceneObject thing, Vector pos, Vector norm, Vector rd, Scene scene) { Color ret = Color.Make(0, 0, 0); foreach (Light light in scene.Lights) { Vector ldis = Vector.Minus(light.Pos, pos); Vector livec = Vector.Norm(ldis); double neatIsect = TestRay(new Ray() { Start = pos, Dir = livec }, scene); bool isInShadow = !((neatIsect > Vector.Mag(ldis)) || (neatIsect == 0)); if (!isInShadow) { double illum = Vector.Dot(livec, norm); Color lcolor = illum > 0 ? Color.Times(illum, light.Color) : Color.Make(0, 0, 0); double specular = Vector.Dot(livec, Vector.Norm(rd)); Color scolor = specular > 0 ? Color.Times(Math.Pow(specular, thing.Surface.Roughness), light.Color) : Color.Make(0, 0, 0); ret = Color.Plus(ret, Color.Plus(Color.Times(thing.Surface.Diffuse(pos), lcolor), Color.Times(thing.Surface.Specular(pos), scolor))); } } return ret; }
public static Vector Norm(Vector v) { double mag = Mag(v); double div = mag == 0 ? double.PositiveInfinity : 1 / mag; return Times(div, v); }
public static double Mag(Vector v) { return Math.Sqrt(Dot(v, v)); }
private Color GetNaturalColor(SceneObject thing, Vector pos, Vector norm, Vector rd, Scene scene) { Color ret = new Color(Color.DefaultColor.R, Color.DefaultColor.G, Color.DefaultColor.B); Vector rdNormalized = Vector.Norm(rd); for (int i = 0; i < scene.Lights.Length; i++) { Light light = scene.Lights[i]; float vx = light.Pos.X - pos.X; float vy = light.Pos.Y - pos.Y; float vz = light.Pos.Z - pos.Z; float sqrLength, invLength; sqrLength = vx * vx + vy * vy + vz * vz; invLength = SceneObject.InvSqrt(sqrLength); Vector livec = new Vector(vx * invLength, vy * invLength, vz * invLength); float neatIsect = TestRay(new Ray() { Start = pos, Dir = livec }, scene); bool isInShadow = !((neatIsect == 0) || (neatIsect > vx * vx + vy * vy + vz * vz)); if (!isInShadow) { float illum = livec.X * norm.X + livec.Y * norm.Y + livec.Z * norm.Z; float specular = livec.X * rdNormalized.X + livec.Y * rdNormalized.Y + livec.Z * rdNormalized.Z; Color lcolor = illum > 0 ? Color.Times(illum, light.Color) : Color.Background; Color scolor = specular > 0 ? Color.Times((float)Math.Pow(specular, thing.Surface.Roughness), light.Color) : Color.Background; var diffuseSurfaceColor = thing.Surface.Diffuse(pos); var specularSurfaceColor = thing.Surface.Specular(pos); ret.R += diffuseSurfaceColor.R * lcolor.R + specularSurfaceColor.R * scolor.R; ret.G += diffuseSurfaceColor.G * lcolor.G + specularSurfaceColor.G * scolor.G; ret.B += diffuseSurfaceColor.B * lcolor.B + specularSurfaceColor.B * scolor.B; } } return ret; }
public Vector cross(Vector v) { return new Vector(this.y * v.z - this.z * v.y, -(this.x * v.z - this.z * v.x), this.x * v.y - this.y * v.x); }
public static Vector Plus(Vector v1, Vector v2) { return new Vector(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z); }
private Color GetReflectionColor(SceneObject thing, Vector pos, Vector norm, Vector rd, Scene scene, int depth) { return Color.Times(thing.Surface.Reflect(pos), TraceRay(new Ray() { Start = pos, Dir = rd }, scene, depth + 1)); }
public abstract Vector Normal(Vector pos);
public static Bitmap run_raytracer(LinkedList<Object> objects, LinkedList<LightSource> lights, Camera c, Size size) { Console.WriteLine("Daniel Bolink's Ray Tracer"); //image size int width = size.Width; int height = size.Height; // Create Camera //Camera c = new Camera(new Position(0, 0, -10), new Position(0,0,0)); //create colors Color BGColor = new Color(0, 0, 0); //Color BLACK = new Color(0, 0, 0); //Color WHITE = new Color(255, 255, 255); //Color GREEN = new Color(0, 255, 0); //Color YELLOW = new Color(255, 255, 0); //Color ORANGE = new Color(255, 0, 255); //Color RED = new Color(200, 0, 0); //Color BLUE = new Color(0, 0, 255); //create Objects in frame //red plane at below 10 units //Object p1 = new Plane(new Vector(0, 1, 0), -1, RED); //blue sphere 10 units ahead radis 0.5 //Object s1 = new Sphere(1, new Position(0, 0, 0), BLACK); //Object s2 = new Sphere(1, new Position(2, 0, 0), ORANGE); //add Objects to list //objects.AddLast(s1); //objects.AddLast(p1); //objects.AddLast(s2); //add Light Sources //LightSource l1 = new LightSource(new Position(20, 5, 10), WHITE); //LightSource l2 = new LightSource(new Position(-20, 5, 10), BLUE); //add lightsources to linked list //lights.AddLast(l1); //lights.AddLast(l2); // Create Pixels Color[,] pixels = new Color[width, height]; //ray tracing algorithm for(int x = 0; x < width; x++) { for (int y = 0; y<height; y++) { double xamnt = (x + 0.5) / width; double yamnt = ((height - y) + 0.5) / height; Vector ray_direction = (c.direction + (c.right * (xamnt-0.5) + (c.down * (yamnt - 0.5)))).normalize(); Ray ray = new Ray(c.position, ray_direction); LinkedList<ObjectPair> intersection_objects = new LinkedList<ObjectPair>(); foreach(Object o in objects) { double val = o.find_intersection(ray); if (val > 0) { intersection_objects.AddLast(new ObjectPair(o, val)); } //Console.WriteLine(val); } //Console.WriteLine(intersection_objects.Count); if(intersection_objects.Count == 0) { pixels[x, y] = BGColor; } else { ObjectPair winner = new ObjectPair(null, -1); foreach (ObjectPair o in intersection_objects) { if (winner.val == -1) { winner = o; } else if(winner.val > o.val && o.val >= 0) { winner = o; } } if(winner.val > 0) { Color final_color = winner.obj.color; Position intersection_point = ray.origin + (ray.direction * (winner.val * 0.999)); foreach (LightSource l in lights) { Boolean shadowed = false; Vector light_direction = new Vector(l.origin, intersection_point).normalize(); //Vector light_direction = new Vector(intersection_point, l.origin).normalize(); Ray shadow_ray = new Ray(intersection_point, light_direction); foreach(Object o in objects) { double obj_intersection = o.find_intersection(shadow_ray); if(obj_intersection > 0) { shadowed = true; break; } } if (!shadowed) { Vector Winner_obj_normal = winner.obj.getNormalAt(intersection_point); double diffuse_coeffient = (shadow_ray.direction.normalize().dot(Winner_obj_normal)); Vector reflection_direction = shadow_ray.direction - (2 * (shadow_ray.direction.dot(Winner_obj_normal)/Winner_obj_normal.magnitude()*Winner_obj_normal)); Ray reflection = new Ray(intersection_point, reflection_direction); double specular_coefficient = reflection.direction.dot(ray.direction); final_color += l.color * 0.15; if(diffuse_coeffient > 0) { final_color += l.color * diffuse_coeffient * 0.15; } if(specular_coefficient > 0) { final_color += l.color * Math.Pow(specular_coefficient, 1000); } } } pixels[x, y] = final_color.clip(); } else { pixels[x, y] = BGColor; } } } } //create image Bitmap bmp = CreateImg(pixels); //Process photoViewer = Process.Start("RayTracer.png"); //prompt for exit //Console.WriteLine("Press any key to exit."); //Console.ReadKey(); return bmp; }
public override Vector Normal(Vector pos) { return Norm; }
private void button1_Click(object sender, EventArgs e) { string selection = (string)comboBox1.SelectedItem; if (o == null) { o = new Object(); } switch (selection) { case "Plane": try { double plane_normal_x = Convert.ToDouble(txtbox_x.Text); double plane_normal_y = Convert.ToDouble(txtbox_y.Text); double plane_normal_z = Convert.ToDouble(txtbox_z.Text); double plane_color_r = Convert.ToDouble(color_txtbox_r.Text); double plane_color_g = Convert.ToDouble(color_txtbox_g.Text); double plane_color_b = Convert.ToDouble(color_txtbox_b.Text); Color color = new Color(plane_color_r, plane_color_g, plane_color_b); Vector normal = new Vector(plane_normal_x, plane_normal_y, plane_normal_z); double distance = Convert.ToDouble(sphere_txtbox_radius.Text); o = new Plane(normal, distance, color); if (!RayTracer_Form.objects.Contains(o)) { RayTracer_Form.objects.AddLast(o); } parent.updateObjects(); Console.WriteLine("Plane Created"); } catch(Exception ex) { Console.WriteLine(ex); } break; case "Sphere": try { double sphere_x = Convert.ToDouble(txtbox_x.Text); double sphere_y = Convert.ToDouble(txtbox_y.Text); double sphere_z = Convert.ToDouble(txtbox_z.Text); double sphere_r = Convert.ToDouble(color_txtbox_r.Text); double sphere_g = Convert.ToDouble(color_txtbox_g.Text); double sphere_b = Convert.ToDouble(color_txtbox_b.Text); Position center = new Position(sphere_x, sphere_y, sphere_z); double radius = Convert.ToDouble(sphere_txtbox_radius.Text); Color c = new Color(sphere_r, sphere_g, sphere_b); o = new Sphere(radius, center, c); if (RayTracer_Form.objects.Contains(o)) { } else { RayTracer_Form.objects.AddLast(o); } parent.updateObjects(); Console.WriteLine("Sphere Created"); } catch (Exception ex) { Console.WriteLine(ex); } break; default: return; } this.Hide(); }