private Color Shade(ISect isect, Scene scene, int depth) { var d = isect.Ray.Dir; var pos = Vector.Plus(Vector.Times(isect.Dist, isect.Ray.Dir), isect.Ray.Start); var normal = isect.Thing.Normal(pos); var reflectDir = Vector.Minus(d, Vector.Times(2*Vector.Dot(normal, d), normal)); Color ret = Color.DefaultColor; ret = Color.Plus(ret, GetNaturalColor(isect.Thing, pos, normal, reflectDir, scene)); if (depth >= MaxDepth) { return Color.Plus(ret, Color.Make(.5, .5, .5)); } return Color.Plus(ret, this.GetReflectionColor(isect.Thing, Vector.Plus(pos, Vector.Times(.001, reflectDir)), normal, reflectDir, scene, depth)); }
private Color TraceRay(Ray ray, Scene scene, int depth) { var isects = Intersections(ray, scene); ISect isect = isects.FirstOrDefault(); if (isect == null) { return Color.Background; } return this.Shade(isect, scene, depth); }
private Color GetReflectionColor(SceneObject thing, Vector pos, Vector norm, Vector rd, Scene scene, int depth) { return Color.Times(thing.Surface.Reflect(pos), this.TraceRay(new Ray {Start = pos, Dir = rd}, scene, depth + 1)); }
private static double TestRay(Ray ray, Scene scene) { var isects = Intersections(ray, scene); ISect isect = isects.FirstOrDefault(); if (isect == null) { return 0; } return isect.Dist; }
private static IEnumerable<ISect> Intersections(Ray ray, Scene scene) { return scene.Things .Select(obj => obj.Intersect(ray)) .Where(inter => inter != null) .OrderBy(inter => inter.Dist); }
private static 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; }
internal void Render(Scene scene) { for (int y = 0; y < this.screenHeight; y++) { for (int x = 0; x < this.screenWidth; x++) { Color color = this.TraceRay(new Ray {Start = scene.Camera.Pos, Dir = this.GetPoint(x, y, scene.Camera)}, scene, 0); this.setPixel(x, y, color.ToDrawingColor()); } } }