// if no object is hit, draw a gradient static Vector3 color(Ray r, Hitable world, int depth) { hit_record rec = new hit_record(); // see if an object is hit if (world.hit(r, 0.001f, float.MaxValue, ref rec)) { // shade the indicated point Ray scattered = new Ray(); Vector3 attenuation = new Vector3(); if (depth < 50 && rec.mat.scatter(r, rec, ref attenuation, ref scattered)) { return(attenuation * color(scattered, world, depth + 1)); } else { // reached our max depth, don't render any further return(new Vector3()); } } else { // no object hit, draw the background Vector3 unit_dir = r.direction().unit_vector(); float t = 0.5f * (unit_dir.y() + 1.0f); return((new Vector3(1.0f, 1.0f, 1.0f)) * (1.0f - t) + (new Vector3(0.5f, 0.7f, 1.0f) * t)); } }
public Ray getRay(float s, float t) { Vector3 rd = lens_radius * Utils.random_in_unit_disk(); Vector3 offset = u * rd.x() + v * rd.y(); float time = (float)Utils.rnd.NextDouble() * (time0 - time1); return(new Ray(origin + offset, lower_left + s * horizontal + t * vertical - origin - offset, time)); }
public bool hit(Ray r, float tmin, float tmax) { float t0 = Utils.fmin((_min.x() - r.origin().x()) / r.direction().x(), (_max.x() - r.origin().x()) / r.direction().x()); float t1 = Utils.fmax((_min.x() - r.origin().x()) / r.direction().x(), (_max.x() - r.origin().x()) / r.direction().x()); tmin = Utils.fmax(t0, tmin); tmax = Utils.fmin(t1, tmax); if (tmax <= tmin) { return(false); } t0 = Utils.fmin((_min.y() - r.origin().y()) / r.direction().y(), (_max.y() - r.origin().y()) / r.direction().y()); t1 = Utils.fmax((_min.y() - r.origin().y()) / r.direction().y(), (_max.y() - r.origin().y()) / r.direction().y()); tmin = Utils.fmax(t0, tmin); tmax = Utils.fmin(t1, tmax); if (tmax <= tmin) { return(false); } t0 = Utils.fmin((_min.z() - r.origin().z()) / r.direction().z(), (_max.z() - r.origin().z()) / r.direction().z()); t1 = Utils.fmax((_min.y() - r.origin().y()) / r.direction().y(), (_max.z() - r.origin().z()) / r.direction().z()); tmin = Utils.fmax(t0, tmin); tmax = Utils.fmin(t1, tmax); if (tmax <= tmin) { return(false); } return(true); }
public override Vector3 value(float u, float v, ref Vector3 p) { float sins = (float)(Math.Sin(p.x() * size) * Math.Sin(p.y() * size) * Math.Sin(p.z() * size)); if (sins > 0.0f) { return(even.value(u, v, ref p)); } else { return(odd.value(u, v, ref p)); } }
public float noise(Vector3 p) { float u = p.x() - (float)Math.Floor(p.x()); float v = p.y() - (float)Math.Floor(p.y()); float w = p.z() - (float)Math.Floor(p.z()); int i = (int)Math.Floor(p.x()); int j = (int)Math.Floor(p.y()); int k = (int)Math.Floor(p.z()); Vector3[,,] c = new Vector3[2, 2, 2]; for (int di = 0; di < 2; di++) { for (int dj = 0; dj < 2; dj++) { for (int dk = 0; dk < 2; dk++) { c [di, dj, dk] = ran_vecs [perm_x [(i + di) & 255] ^ perm_y [(j + dj) & 255] ^ perm_z [(k + dk) & 255]]; } } } return(Utils.trilinear_interpolation(c, u, v, w)); }
public static void Main(string[] args) { // output to a ppm file Console.Write("P3\n" + nx + " " + ny + " " + "\n255\n"); // create the world List <Hitable> world = new List <Hitable>(); world.Add(new Moving_Sphere(new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 0.0f, -2.0f), 0.0f, 10.0f, 0.5f, new Lambertian(new Const_Texture(new Vector3(0.137f, 0.467f, 1.0f))))); world.Add(new Sphere(new Vector3(1.0f, 0.0f, -1.0f), 0.5f, new Dielectric(1.5f))); world.Add(new Sphere(new Vector3(1.0f, 0.0f, -1.0f), -0.3f, new Dielectric(1.5f))); world.Add(new Sphere(new Vector3(-1.0f, 0.0f, -1.0f), 0.5f, new Metal(new Noise(10.0f)))); world.Add(new Sphere(new Vector3(0.0f, -100.5f, -1.0f), 100.0f, new Lambertian(new Marble(new Vector3(0.0f, 0.8f, 0.0f), 5.0f)))); BVH_Node tree = new BVH_Node(world, 0.0f, 10.0f); // init the camera Vector3 lookfrom = new Vector3(3.0f, 2.0f, 2.0f); Vector3 lookat = new Vector3(0.0f, 0.0f, -1.0f); float dist_to_focus = (lookfrom - lookat).length(); float apeture = 0.5f; Camera cam = new Camera(lookfrom, lookat, new Vector3(0.0f, 1.0f, 0.0f), 40.0f, (float)nx / (float)ny, apeture, dist_to_focus, 0.0f, 10.0f); for (int i = ny - 1; i >= 0; i--) { for (int j = 0; j < nx; j++) { // supersampling for antialiasing Vector3 col = new Vector3(); for (int s = 0; s < ns; s++) { float u = (float)(j + Utils.rnd.NextDouble()) / (float)nx; float v = (float)(i + Utils.rnd.NextDouble()) / (float)ny; Ray r = cam.getRay(u, v); col += color(r, tree, 0); } col /= (float)ns; // gamma correction col = new Vector3((float)Math.Sqrt(col.x()), (float)Math.Sqrt(col.y()), (float)Math.Sqrt(col.z())); // values written to file int ir = (int)(255.99f * col.r()); int ig = (int)(255.99f * col.g()); int ib = (int)(255.99f * col.b()); Console.Write(ir + " " + ig + " " + ib + "\n"); } } }
public static Vector3 cross(Vector3 a, Vector3 b) { return(new Vector3(a.y() * b.z() - a.z() * b.y(), -(a.x() * b.z() - a.z() * b.x()), a.x() * b.y() - a.y() * b.x())); }
// other operations public static float dot(Vector3 a, Vector3 b) { return(a.x() * b.x() + a.y() * b.y() + a.z() * b.z()); }