public void Render(List <Sphere> objects, List <Light> lights) { float fov = (float)Math.PI / 3f; Bitmap bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height); LockBitmap lockBitmap = new LockBitmap(bmp); lockBitmap.LockBits(); int width = lockBitmap.Width; int height = lockBitmap.Height; var result = Parallel.For(0, height, (j, state) => { var result1 = Parallel.For(0, width, (i, state1) => { { var dirx = i + .5f - width / 2f; var diry = -(j + .5f) + height / 2f; var dirz = -height / (2f * (float)Math.Tan(fov / 2f)); var vcam = new Vec3f(0, 0, 0); var vdir = new Vec3f(dirx, diry, dirz).normalize(); Vec3f res = cast_ray(vcam, vdir, objects, lights); float max = Math.Max(res.x, Math.Max(res.y, res.z)); if (max > 1) { res *= (1 / max); } Color col = Color.FromArgb((int)(255 * res.x), (int)(255 * res.y), (int)(255 * res.z)); lockBitmap.SetPixel(i, j, col); } }); }); lockBitmap.UnlockBits(); pictureBox1.Image = bmp; }
public Light(Vec3f position, float intensity) { this.position = position; this.intensity = intensity; }
public Sphere(Vec3f center, float radius, Material material) { Center = center; Radius = radius; Material = material; }
private static bool SceneIntersect(Vec3f orig, Vec3f dir, List <Sphere> spheres, ref Vec3f hit, ref Vec3f N, ref Material material) { var spheresDist = float.MaxValue; foreach (var sphere in spheres) { var disti = 0f; if (sphere.RayIntersect(orig, dir, ref disti) && disti < spheresDist) { spheresDist = disti; hit = orig + dir * disti; N = (hit - sphere.Center).normalize(); material = sphere.Material; } } List <float> dists = new List <float>(); dists.Add(spheresDist); var floor = float.MaxValue; if (Math.Abs(dir.y) > 1e-3) { // The checkerboard plane has equation y = -4. var d = -(orig.y + 8) / dir.y; var pt = orig + dir * d; if (d > 0 && Math.Abs(pt.x) < 10 && pt.z <= 0 && pt.z >= -30 && d < spheresDist) { floor = d; hit = pt; N = new Vec3f(0, 1, 0); var c1 = new Vec3f(.3f, .3f, .3f); var c2 = new Vec3f(.3f, .2f, .1f); material = new Material(1, new[] { .9f, .1f, .0f, .0f }, new Vec3f(.3f, .3f, .3f), 10); } } dists.Add(floor); var ceiling = float.MaxValue; if (Math.Abs(dir.y) > 1e-3) { var d = -(orig.y - 6) / dir.y; var pt = orig + dir * d; if (d > 0 && Math.Abs(pt.x) <= 10 && pt.z <= 0 && pt.z >= -30 && d < spheresDist) { ceiling = d; hit = pt; N = new Vec3f(0, -1, 0); var c1 = new Vec3f(.3f, .3f, .3f); var c2 = new Vec3f(.3f, .2f, .1f); material = new Material(1, new[] { .9f, .1f, .0f, .0f }, new Vec3f(.3f, .3f, .3f), 10); } } dists.Add(ceiling); var right_wall = float.MaxValue; if (Math.Abs(dir.x) > 1e-3) { // The checkerboard plane has equation y = -4. var d = -(orig.x - 10) / dir.x; var pt = orig + dir * d; if (d > 0 && pt.y <= 6 && pt.y >= -8 && pt.z <= 0 && pt.z >= -30 && d < spheresDist) { right_wall = d; hit = pt; N = new Vec3f(-1, 0, 0); var c1 = new Vec3f(0, 1, 0); var c2 = new Vec3f(.3f, .2f, .1f); //material.DiffColor = c1; material = new Material(1, new[] { .9f, .1f, .0f, .0f }, new Vec3f(.1f, .3f, .1f), 10); } } dists.Add(right_wall); var left_wall = float.MaxValue; if (Math.Abs(dir.x) > 1e-3) { // The checkerboard plane has equation y = -4. var d = -(orig.x + 10) / dir.x; var pt = orig + dir * d; if (d > 0 && pt.y <= 6 && pt.y >= -8 && pt.z <= 0 && pt.z >= -30 && d < spheresDist) { left_wall = d; hit = pt; N = new Vec3f(1, 0, 0); var c1 = new Vec3f(1, 0, 0); var c2 = new Vec3f(.3f, .2f, .1f); material = new Material(1, new[] { .9f, .1f, .0f, .0f }, new Vec3f(.3f, .1f, .1f), 10); } } dists.Add(left_wall); var front_wall = float.MaxValue; if (Math.Abs(dir.z) > 1e-3f) { // The checkerboard plane has equation y = -4. var d = -(orig.z + 30) / dir.z; var pt = orig + dir * d; if (d > 0 && pt.y <= 6 && pt.y >= -8 && Math.Abs(pt.x) <= 10 && d < spheresDist) { front_wall = d; hit = pt; N = new Vec3f(0, 0, 1); var c1 = new Vec3f(.3f, .3f, .3f); var c2 = new Vec3f(.3f, .2f, .1f); material = front_wall_material; } } dists.Add(front_wall); var back_wall = float.MaxValue; if (Math.Abs(dir.z) > 1e-3f) { // The checkerboard plane has equation y = -4. var d = -(orig.z) / dir.z; var pt = orig + dir * d; if (d > 0 && pt.y <= 6 && pt.y >= -8 && Math.Abs(pt.x) <= 10 && d < spheresDist) { front_wall = d; hit = pt; N = new Vec3f(0, 0, -1); var c1 = new Vec3f(.3f, .3f, .3f); var c2 = new Vec3f(.3f, .2f, .1f); material = new Material(1, new[] { .9f, .1f, .0f, .0f }, new Vec3f(.1f, .1f, .7f), 10); } } dists.Add(front_wall); return(dists.Min() < 1000); }
private static Vec3f Reflect(Vec3f I, Vec3f N) { return(I - N * 2f * (I * N)); }