private IEnumerable<ISect> Intersections(Ray ray, Scene scene) { return scene.Things .Select(obj => obj.Intersect(ray)) .Where(inter => inter != null) .OrderBy(inter => inter.Dist); }
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 Shade(isect, scene, depth); }
private double TestRay(Ray ray, Scene scene) { var isects = Intersections(ray, scene); ISect isect = isects.FirstOrDefault(); if (isect == null) return 0; return isect.Dist; }
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; }
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)); } ret = Color.Plus(ret, GetReflectionColor(isect.Thing, Vector.Plus(pos, Vector.Times(.001, reflectDir)), normal, reflectDir, scene, depth)); return ret; }
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)); }
internal void RenderParallel(Scene scene, Int32[] rgb) { Parallel.For(0, screenHeight, y => { int stride = y * screenWidth; //Camera camera = scene.Camera; for (int x = 0; x < screenWidth; x++) { Color color = TraceRay(new Ray() { Start = scene.Camera.Pos, Dir = GetPoint(x, y, scene.Camera) }, scene, 0); rgb[x + stride] = color.ToInt32(); } }); }