// sample: samples a single path up to a maximum depth private Vector3 Sample(Ray ray, int depth, int x, int y) { // find nearest ray/scene intersection Scene.Intersect(ray); if (ray.objIdx == -1) { // no scene primitive encountered; skybox return(1.0f * scene.SampleSkydome(ray.D)); } // calculate intersection point Vector3 I = ray.O + ray.t * ray.D; // get material at intersection point Material material = scene.GetMaterial(ray.objIdx, I); if (material.emissive) { // hit light return(material.diffuse); } // terminate if path is too long if (depth >= MAXDEPTH) { return(Vector3.Zero); } // handle material interaction float r0 = RTTools.RandomFloat(); Vector3 R = Vector3.Zero; if (r0 < material.refr) { // dielectric: refract or reflect RTTools.Refraction(ray.inside, ray.D, ray.N, ref R); Ray extensionRay = new Ray(I + R * EPSILON, R, 1e34f); extensionRay.inside = (Vector3.Dot(ray.N, R) < 0); return(material.diffuse * Sample(extensionRay, depth + 1, x, y)); } else if ((r0 < (material.refl + material.refr)) && (depth < MAXDEPTH)) { // pure specular reflection R = Vector3.Reflect(ray.D, ray.N); Ray extensionRay = new Ray(I + R * EPSILON, R, 1e34f); return(material.diffuse * Sample(extensionRay, depth + 1, x, y)); } else { // diffuse reflection if (x == 500 && y == 400) { //Console.WriteLine("test"); //return new Vector3(255,255,255); } R = RTTools.DiffuseReflection(RTTools.GetRNG(), ray.N); Ray extensionRay = new Ray(I + R * EPSILON, R, 1e34f); return(Vector3.Dot(R, ray.N) * material.diffuse * Sample(extensionRay, depth + 1, x, y)); } }
static public void Refraction(bool inside, Vector3 D, Vector3 N, ref Vector3 R) { float nc = inside ? 1 : 1.2f, nt = inside ? 1.2f : 1; float nnt = nt / nc, ddn = Vector3.Dot(D, N); float cos2t = 1.0f - nnt * nnt * (1 - ddn * ddn); R = Vector3.Reflect(D, N); if (cos2t >= 0) { float r1 = RTTools.RandomFloat(); float a = nt - nc, b = nt + nc, R0 = a * a / (b * b), c = 1 + ddn; float Tr = 1 - (R0 + (1 - R0) * c * c * c * c * c); if (r1 < Tr) { R = (D * nnt - N * (ddn * nnt + (float)Math.Sqrt(cos2t))); } } }