public BVHNode(Hitable[] list, int low, int high, float t0, float t1) { if (low < 0 || high > list.Length) { throw new Exception("BVHNode Contruction error low <0 || high >list.Length"); } int length = high - low; if (length <= 0) { throw new Exception("BVHNode Contruction error low >= high"); } if (length == 1) { _left = _right = list[low]; _box = _left.BoundVolume(t0, t1); } else if (length == 2) { _left = list[low]; _right = list[low + 1]; _box = AABB.SurroundingBox(_left.BoundVolume(t0, t1), _right.BoundVolume(t0, t1)); } else { Array.Sort(list, low, high - low, new BVHComparer((int)(3 * Exten.rand01()))); int mid = (low + high) / 2; _left = new BVHNode(list, low, mid, t0, t1); _right = new BVHNode(list, mid, high, t0, t1); _box = AABB.SurroundingBox(_left.BoundVolume(t0, t1), _right.BoundVolume(t0, t1)); } }
public Ray GenRay(float s, float t) { vec3 offset = lenRadius * random_in_unit_disk(); var point = origin + offset; var time = openTime + (closeTime - openTime) * Exten.rand01(); return(new Ray(point, lower_left_corner + s * horizontal + t * vertical - point, time)); }
vec3 random_in_unit_disk() { vec3 p; do { p = 2.0f * new vec3(Exten.rand01(), Exten.rand01(), 0) - new vec3(1, 1, 0); } while (glm.dot(p, p) >= 1.0f); return(p); }
void shuff(int [] vs) { for (int i = 0; i < vs.Length - 1; ++i) { int nextIdx = i + 1 + (int)((vs.Length - i - 1) * Exten.rand01()); var temp = vs[i]; vs[i] = vs[nextIdx]; vs[nextIdx] = temp; } }
public vec3 RandomCosineDir() { float r1 = Exten.rand01(); float r2 = Exten.rand01() / fuzz; r2 = (float)Math.Pow(2.72, -r2*r2); double z = Math.Sqrt(1 - r2); double phi = 2 * Math.PI * r1; double x = Math.Cos(phi) * Math.Sqrt(r2); double y = Math.Sin(phi) * Math.Sqrt(r2); return new vec3((float)x, (float)y, (float)z); }
public vec3 Generate(vec3 point, vec3 normal) { float r1 = Exten.rand01(); float r2 = Exten.rand01(); var pc = _sphere.GetCenter(0) - point; float cosMax = MathF.Sqrt(1 - _sphere.radius * _sphere.radius / glm.dot(pc, pc)); float z = 1 + r2 * (cosMax - 1); float phi = r1 * 2.0f * MathF.PI; float x = MathF.Cos(phi) * MathF.Sqrt(1 - z * z); float y = MathF.Sin(phi) * MathF.Sqrt(1 - z * z); ONB oNB = new ONB(glm.normalize(pc)); return(oNB.Local(x, y, z)); }
public Noise() { for (int i = 0; i < _randomValue.Length; ++i) { _randomValue[i] = Exten.rand01(); } for (int i = 0; i < maxL; ++i) { _xAxis[i] = i; //(int)(maxL * Exten.rand01()); _yAxis[i] = i; //(int)(maxL * Exten.rand01()); _zAxis[i] = i; //(int)(maxL * Exten.rand01()); } shuff(_xAxis); shuff(_yAxis); shuff(_zAxis); }
public vec3 Generate(vec3 point, vec3 normal) { var r = Exten.rand01(); if (r < 0.5f) { return(_pdfs[0].Generate(point, normal)); } else if (r < 0.75f) { return(_pdfs[1].Generate(point, normal)); } else { return(_pdfs[2].Generate(point, normal)); } }
static Hitable FinalTest() { int nb = 20; Hitable[] list = new Hitable[30]; Hitable[] boxlist = new Hitable[10000]; Material ground = new Lambertian(new SolidTexture(new vec3(0.48f, 0.83f, 0.53f))); int b = 0; for (int i = 0; i < nb; i++) { for (int j = 0; j < nb; j++) { float w = 100; float x0 = -1000 + i * w; float z0 = -1000 + j * w; float y0 = 0; float x1 = x0 + w; float y1 = 100 * (Exten.rand01() + 0.01f); float z1 = z0 + w; boxlist[b++] = new Box(new vec3(x0, y0, z0), new vec3(x1, y1, z1), ground); } } int l = 0; list[l++] = new BVHNode(boxlist, 0, b, 0, 1); Material light = new DiffuseLight(new SolidTexture(new vec3(7, 7, 7))); list[l++] = new XZRect(554, 123, 423, 147, 412, light); vec3 center = new vec3(400, 400, 200); //public Sphere(vec3 c, vec3 c1, float r, Material m, float time1, float time2) list[l++] = new Sphere(center, center + new vec3(30, 0, 0), 50, new Lambertian(new SolidTexture(new vec3(0.7f, 0.3f, 0.1f))), 0, 1); list[l++] = new Sphere(new vec3(260, 150, 45), 50, new Dieletric(1.5f)); list[l++] = new Sphere(new vec3(0, 150, 145), 50, new Metal(new vec3(0.8f, 0.8f, 0.9f), 10.0f)); Hitable boundary = new Sphere(new vec3(360, 150, 145), 70, new Dieletric(1.5f)); list[l++] = boundary; boundary = new Sphere(new vec3(0, 0, 0), 5000, new Dieletric(1.5f)); Texture pertext = new NoiseTexture(new Noise()); list[l++] = new Sphere(new vec3(220, 280, 300), 80, new Lambertian(pertext)); return(new HitList(list.Where(arg => arg != null).ToArray())); }
public bool Scatter(Ray ray, HitRecord hitRecord, out ScatterRecord sRecord) { sRecord = new ScatterRecord(); var normal = hitRecord.normal; var point = hitRecord.point; sRecord.attenuation = new vec3(1.0f, 1.0f, 1.0f); float eta = ref_idx; var n = normal; if (glm.dot(ray.direction, normal) > 0)//从内到外 { n = new vec3(-normal.x, -normal.y, -normal.z); } else { eta = 1.0f / eta; } vec3 r; float prob = 1.0f; if (Exten.refract(ray.direction, n, eta, out r)) { float cosi = -glm.dot(ray.direction, n); float cost = -glm.dot(r, n); prob = fresnel(cosi, cost, eta); } if (Exten.rand01() < prob) { vec3 reflected = Exten.reflect(ray.direction, normal); sRecord.pdf = new ConstPDF(reflected); } else { sRecord.pdf = new ConstPDF(r); } return true; }
static float drand48() { return(Exten.rand01()); }
public static void Main(string[] args) { Exten.r = new Random(0); int width = 600; int height = 300; string outPath = "1.png"; int sampleCount = 5; bool bvh = false; if (args.Length >= 1) { sampleCount = int.Parse(args[0]); } if (args.Length >= 2) { width = int.Parse(args[1]); } if (args.Length >= 3) { height = int.Parse(args[2]); } if (args.Length >= 4) { outPath = args[3]; } if (args.Length >= 5) { bvh = bool.Parse(args[4]); } scene = CornellBox(); // SimpleLight(); //random_scene(bvh); vec3 lookfrom = new vec3(278, 278, -800); vec3 lookat = new vec3(278, 278, 0); float dist_to_focus = 10.0f; float aperture = 0.0f; Camera camera = new Camera(lookfrom, lookat, new vec3(0, 1, 0), 40, (float)(width) / (float)(height), aperture, dist_to_focus, 0, 1); Bitmap bmp = new Bitmap(width, height); for (int i = height - 1; i >= 0; --i) { ShowProgress((height - i) / (float)height); for (int j = 0; j < width; ++j) { var c = new vec3(0, 0, 0); for (int k = 0; k < sampleCount; ++k) { float x = (j + Exten.rand01()) / (float)width; float y = (i + Exten.rand01()) / (float)height; var ray = camera.GenRay(x, y); c += RayTracing(ray, 0); } c /= sampleCount; //printColor(c.gamma()); c = c.gamma(); int r = (int)(c.x * 255.99f); int g = (int)(c.y * 255.99f); int b = (int)(c.z * 255.99f); r = clamp(r, 0, 255); g = clamp(g, 0, 255); b = clamp(b, 0, 255); Color o = Color.FromArgb(r, g, b); #if UNITY_EDITOR bmp.SetPixel(j, i, o); #else bmp.SetPixel(j, height - i - 1, o); #endif } } bmp.Save(outPath, ImageFormat.Png); HideProgress(); }