private Vector3 CastPrimaryRay(Ray ray, Scene scene, int depth = 0) { foreach (Primitive p in scene.primitives) { p.Intersect(ray); } //Nu alleen nog de kleur van het object, geen shadow rays e.d. if (ray.objectHit == null) //If no object has been hit load the skybox. { return Vector3.Zero; } if (ray.D.Y < .01f && ray.D.Y > -.01f) { if (depth != 0) Debug.Rays.Add(ray); } Vector3 intersection = ray.GetPoint(); Vector3 color = ray.objectHit.GetTexture(intersection); if (ray.objectHit.specular && depth < 20) { //Object is een spiegel, cast een tweede primary ray Vector3 N = ray.objectHit.GetNormal(ray.GetPoint()); Vector3 R = ray.D - 2 * (Vector3.Dot(ray.D, N) * N); Ray secondaryRay = new Ray(intersection, R, float.MaxValue); return color * CastPrimaryRay(secondaryRay, scene, depth + 1); } //Object weerkaatst licht diffuus, cast shadowrays naar lampen OF max depth is gehaald en meer primary rays tekenen wordt te duur return color * CastShadowRay(intersection, ray.objectHit, scene); }
public Ray4( Ray[] rays ) { int l = rays.Length; float[] ox4 = new float[l], oy4 = new float[l], oz4 = new float[l]; float[] dx4 = new float[l], dy4 = new float[l], dz4 = new float[l]; float[] t = new float[l]; float[] nx4 = new float[l], ny4 = new float[l], nz4 = new float[l]; int[] objIdx = new int[l]; int[] inside = new int[l]; for (int i = 0; i < rays.Length; i++) { ox4[i] = rays[i].O.X; oy4[i] = rays[i].O.Y; oz4[i] = rays[i].O.Z; dx4[i] = rays[i].D.X; dy4[i] = rays[i].D.Y; dz4[i] = rays[i].D.Z; t[i] = rays[i].t; nx4[i] = rays[i].N.X; ny4[i] = rays[i].N.Y; nz4[i] = rays[i].N.Z; objIdx[i] = rays[i].objIdx; inside[i] = rays[i].inside ? 1 : 0; } Ox4 = new Vector<float>(ox4); Oy4 = new Vector<float>(oy4); Oz4 = new Vector<float>(oz4); Dx4 = new Vector<float>(dx4); Dy4 = new Vector<float>(dy4); Dz4 = new Vector<float>(dz4); t4 = new Vector<float>(t); Nx4 = new Vector<float>(nx4); Ny4 = new Vector<float>(ny4); Nz4 = new Vector<float>(nz4); objIdx4 = new Vector<int>(objIdx); inside4 = new Vector<int>(inside); returnMask = new Vector<int>(0); }
private static void IntersectSphere (int idx, Sphere sphere, Ray ray) { Vector3 L = sphere.pos - ray.O; float tca = Vector3.Dot (L, ray.D); if (tca < 0) return; float d2 = Vector3.Dot (L, L) - tca * tca; if (d2 > sphere.r) return; float thc = (float)Math.Sqrt (sphere.r - d2); float t0 = tca - thc; float t1 = tca + thc; if (t0 > 0) { if (t0 > ray.t) return; ray.N = Vector3.Normalize (ray.O + t0 * ray.D - sphere.pos); ray.objIdx = idx; ray.t = t0; } else { if ((t1 > ray.t) || (t1 < 0)) return; ray.N = Vector3.Normalize (sphere.pos - (ray.O + t1 * ray.D)); ray.objIdx = idx; ray.t = t1; } }
public static void Intersect( Ray ray ) { IntersectSphere( 0, plane1, ray ); IntersectSphere( 1, plane2, ray ); for( int i = 0; i < 6; i++ ) IntersectSphere( i + 2, sphere[i], ray ); IntersectSphere( 8, light, ray ); }
public Ray this[int index] { get { Vector3 O = new Vector3(Ox4[index], Oy4[index], Oz4[index]); Vector3 D = new Vector3(Dx4[index], Dy4[index], Dz4[index]); Ray ray = new Ray(O, D, t4[index]); ray.N = new Vector3(Nx4[index], Ny4[index], Nz4[index]); ray.objIdx = objIdx4[index]; ray.inside = inside4[index] == 1 ? true : false; return ray; } }
public void RenderPixel(Camera cam, Surface screen, Scene scene, float hi, float wi, int x, int y) { Vector3[] points = cam.GetPoints; Vector3 direction = new Vector3(); Vector3 result; Ray ray; if (AntiAlias) { float offX = 1 / 2f * 1 / screen.width; float offY = 1 / 2f * 1 / screen.height; Vector3 directionLB = points[0] + wi * (points[1] - points[0]) + hi * (points[2] - points[0]); Vector3 directionRB = points[0] + (wi + offX) * (points[1] - points[0]) + hi * (points[2] - points[0]); Vector3 directionLO = points[0] + wi * (points[1] - points[0]) + (hi + offY) * (points[2] - points[0]); Vector3 directionRO = points[0] + (wi + offX) * (points[1] - points[0]) + (hi + offY) * (points[2] - points[0]); ray = new Ray(cam.Position, directionLB, float.MaxValue); Ray ray2 = new Ray(cam.Position, directionRB, float.MaxValue); Ray ray3 = new Ray(cam.Position, directionLO, float.MaxValue); Ray ray4 = new Ray(cam.Position, directionRO, float.MaxValue); Vector3 res1 = CastPrimaryRay(ray, scene); Vector3 res2 = CastPrimaryRay(ray2, scene); Vector3 res3 = CastPrimaryRay(ray3, scene); Vector3 res4 = CastPrimaryRay(ray4, scene); result = (res1 + res2 + res3 + res4) / 4; } else { direction = points[0] + wi * (points[1] - points[0]) + hi * (points[2] - points[0]); ray = new Ray(cam.Position, direction, float.MaxValue); result = CastPrimaryRay(ray, scene); } if (ray.D.Y < .01f && ray.D.Y > -.01f && x % 10 == 0) { Debug.Rays.Add(ray); } //screen.pixels[x + y * screen.width] = VectorToColor(CastPrimaryRay(ray, screen, scene, 0)); screen.pixels[x + y * screen.width] = VectorToColor(result); }
// sample: samples a single path up to a maximum depth private Vector3 Sample( Ray ray, int depth ) { // 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 ); } 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 ); } else { // diffuse reflection 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 ); } }
public void Update() { // construct a look-at matrix E = Vector3.Normalize( target - pos ); up = Vector3.UnitY; right = Vector3.Cross( up, E ); up = Vector3.Cross( E, right ); // calculate focal distance Ray ray = new Ray( pos, E, 1e34f ); Scene.Intersect( ray ); focalDistance = Math.Min( 20, ray.t ); // calculate virtual screen corners Vector3 C = pos + focalDistance * E; p1 = C - 0.5f * focalDistance * aspectRatio * right + 0.5f * focalDistance * up; p2 = C + 0.5f * focalDistance * aspectRatio * right + 0.5f * focalDistance * up; p3 = C - 0.5f * focalDistance * aspectRatio * right - 0.5f * focalDistance * up; }
//Code overgenomen uit slides public override void Intersect(Ray ray) { //possibly have to change this to incorporate intersecting the orb from inside Vector3 c = this.position - ray.O; float t = Vector3.Dot(c, ray.D); Vector3 q = c - t * ray.D; float p2 = Vector3.Dot(q, q); float r2 = radius * radius; if (p2 > r2) return; t -= (float)Math.Sqrt(r2 - p2); if ((t < ray.l) && (t > 0)) { ray.l = t; ray.objectHit = this; } // or: ray.t = min( ray.t, max( 0, t ) ); }
public override void Intersect(Ray ray) { float eps = 0.000001f; Vector3 P = Vector3.Cross(ray.D, e2); float det = Vector3.Dot(e1, P); if (det > -eps && det < eps) { return; } Vector3 T = ray.O - p; float inv_det = 1 / det; float u = Vector3.Dot(T, P) * inv_det; if (u < 0 || u > 1) { return; } Vector3 Q = Vector3.Cross(T, e1); float v = Vector3.Dot(ray.D, Q) * inv_det; if (v < 0 || u + v > 1) { return; } float t = Vector3.Dot(e2, Q) * inv_det; if (t > eps && t < ray.l) { ray.l = t; ray.objectHit = this; } }
private Vector3 SampleIterative2(Ray _ray) { int depth = 0; Vector3 currentMaterial = new Vector3(1.0f, 1.0f, 1.0f); Ray ray = _ray; while (true) { Scene.Intersect(ray); if (ray.objIdx == -1) { return currentMaterial * (scene.SampleSkydome(ray.D)); } Vector3 I = ray.O + ray.t * ray.D; Material material = scene.GetMaterial(ray.objIdx, I); if (material.emissive) { return material.diffuse; } if (depth >= MAXDEPTH) { return Vector3.Zero; } float r0 = RTTools.RandomFloat(); Vector3 R = Vector3.Zero; if (r0 < material.refr) { 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); currentMaterial *= material.diffuse; ray = extensionRay; depth++; continue; } else if ((r0 < (material.refl + material.refr)) && (depth < MAXDEPTH)) { R = Vector3.Reflect(ray.D, ray.N); Ray extensionRay = new Ray(I + R * EPSILON, R, 1e34f); currentMaterial *= material.diffuse; ray = extensionRay; depth++; continue; } else { R = RTTools.DiffuseReflection(RTTools.GetRNG(), ray.N); Ray extensionRay = new Ray(I + R * EPSILON, R, 1e34f); currentMaterial *= material.diffuse; ray = extensionRay; depth++; continue; } } return Vector3.Zero; }
private Vector3 SampleIterative(Ray inputRay) { int depth = inputRay.testingDepth; Ray workingRay = inputRay; Vector3 returnObj = new Vector3(1.0f, 1.0f, 1.0f); // to save iterations over the material while (depth <= MAXDEPTH) { Scene.Intersect(workingRay); // find nearest ray/scene intersection if (workingRay.objIdx == -1) // no scene primitive encountered; skybox { return 1.0f * scene.SampleSkydome(workingRay.D) * returnObj; } Vector3 I = workingRay.O + workingRay.t * workingRay.D; // calculate intersection point Material material = scene.GetMaterial(workingRay.objIdx, I); // get material at intersection point if (material.emissive) // hit light { return material.diffuse * returnObj; } float r0 = RTTools.RandomFloat(); Vector3 R = Vector3.Zero; if (r0 < material.refr) // dielectric: refract or reflect { RTTools.Refraction(workingRay.inside, workingRay.D, workingRay.N, ref R); Ray extensionRay = new Ray(I + R * EPSILON, R, 1e34f, depth + 1); extensionRay.inside = (Vector3.Dot(workingRay.N, R) < 0); workingRay = extensionRay; if (returnObj == new Vector3(1.0f, 1.0f, 1.0f)) { returnObj = (material.diffuse); } else { returnObj *= material.diffuse; } if (depth == MAXDEPTH) { return returnObj * (workingRay.O + workingRay.t * workingRay.D); } else { continue; } } else if ((r0 < (material.refl + material.refr)) && (depth < MAXDEPTH)) // pure specular reflection { R = Vector3.Reflect(workingRay.D, workingRay.N); Ray extensionRay = new Ray(I + R * EPSILON, R, 1e34f, depth + 1); workingRay = extensionRay; if (returnObj == Vector3.Zero) { returnObj = (material.diffuse); } else { returnObj *= material.diffuse; } if (depth == MAXDEPTH) { return returnObj * (workingRay.O + workingRay.t * workingRay.D); } else { continue; } } else // diffuse reflection { R = RTTools.DiffuseReflection(RTTools.GetRNG(), workingRay.N); Ray extensionRay = new Ray(I + R * EPSILON, R, 1e34f, depth + 1); workingRay = extensionRay; if (returnObj == Vector3.Zero) { returnObj = (material.diffuse); } else { returnObj *= material.diffuse; } if (depth == MAXDEPTH) { return Vector3.Dot(R, workingRay.N) * (workingRay.O + workingRay.t * workingRay.D); } else { continue; } } } return Vector3.Zero; }
private Vector3 CastShadowRay(Vector3 intersection, Primitive prim, Scene scene) { Vector3 light = new Vector3(0, 0, 0); foreach (Light l in scene.lights) { //Richting van de ray is van lamp naar object Vector3 toLight = intersection - l.pos; float tmax = toLight.Length - 2 * Epsilon; Ray shadowRay = new Ray(l.pos - toLight * Epsilon, toLight, float.MaxValue); //Negatief, omdat de shadowray van lamp naar object gaat ipv andersom Vector3 N = -1f * prim.GetNormal(intersection); float incidence = Vector3.Dot(N, shadowRay.D); if (incidence > 0) { foreach (Primitive p in scene.primitives) { p.Intersect(shadowRay); //Als de ray iets raakt tussen de lamp en het object, abort mission if (shadowRay.l < tmax) { break; } } //Check of er geen objecten tussen de lamp en het object zitten if (shadowRay.l >= tmax) { light += (l.color * (1 / (shadowRay.l * shadowRay.l))) * incidence; } } } foreach (Spotlight spot in scene.spots) { //Richting van de ray is van lamp naar object Vector3 toLight = intersection - spot.pos; float tmax = toLight.Length - 2 * Epsilon; Ray shadowRay = new Ray(spot.pos - toLight * Epsilon, toLight, float.MaxValue); //Negatief, omdat de shadowray van lamp naar object gaat ipv andersom Vector3 N = -1f * prim.GetNormal(intersection); float incidence = Vector3.Dot(N, shadowRay.D); float incidenceOnSpot = Vector3.Dot(shadowRay.D, spot.D); if (incidence > 0 && incidenceOnSpot > spot.minDot) { foreach (Primitive p in scene.primitives) { p.Intersect(shadowRay); //Als de ray iets raakt tussen de lamp en het object, abort mission if (shadowRay.l < tmax) { break; } } //Check of er geen objecten tussen de lamp en het object zitten if (shadowRay.l >= tmax) { light += (spot.color * (1 / (shadowRay.l * shadowRay.l))) * incidence; } } } return light; }
//All virtual methods are implemented in the children classes with override methods. public virtual void Intersect(Ray ray) //For the intersection. { }