public ColourRGBA Trace(Ray r, Surface[] quads, Light[] lights, float c, ref float coef, ref Vector result, ref bool hitLight) { if (c < Config.Ray.MaxBounce) { Surface closest = null; Vector normal = new Vector(); float dist = 0; float closestDist = 0; foreach (Surface quad in quads) { if (quad.Intersect(r, ref dist)) { if (closest == null) { if (dist > 0) { closestDist = dist; closest = quad; } } else { if (dist > 0 && dist < closestDist) { closestDist = dist; closest = quad; } } } } if (closest != null) { //return closest.GetMat().GetColour(); { //Bounce off the surface then just f**k off //TODO: This is shit bro. closest.m_dist = closestDist; closest.m_lastRay = r; normal = closest.CalculateSurfaceNormal(); //This is just some error check for when im adding things to the tracer. if (normal == null) { Console.WriteLine("----------------------------------------"); Console.WriteLine(closest.ToString()); Console.WriteLine("This can't calculate the surface normal!"); Console.ReadKey(); Environment.Exit(1); } Ray ray = closest.Reflect(r.orgin, closest.CalculateSurfaceNormal(), closestDist, r); if (ray == null) { Console.WriteLine("----------------------------------------"); Console.WriteLine(closest.ToString()); Console.WriteLine("This can not reflect!"); Console.ReadKey(); Environment.Exit(1); } Ray lsr = null; //for each light we need to check if there is anything in the way the new ray orgin and the light. //check to see if this position has a visable light. foreach (Light ls in lights) { bool lightBlocker = false; //check if anything is in the way foreach (Surface s in quads) { float ld = 0; Vector sl = (ls.pos - ray.orgin).Normalize(); lsr = new Ray(ray.orgin, sl); if (s.Intersect(lsr, ref ld)) { if (ld > 0.01) { lightBlocker = true; break; } } } //check if there was a light blocker and if not add lighting to the ray point. if (!lightBlocker) { //Get the distance to the light so we know if its hitting us. //float lightPointDist = (float)SurfaceFunc.Vec3Distance(ray.orgin, ls.pos); /* * if (lightPointDist < 1000) * { * float lambert = 0; * if (lsr != null) * { * lambert = lsr.dir.DotProduct(closest.CalculateSurfaceNormal()) * coef; * } * else * { * //TODO Error * } * //Lambert disfuseion * result.m_x += lambert * ls.intesity.r * closest.GetMat().disfuse.r; * result.m_y += lambert * ls.intesity.g * closest.GetMat().disfuse.g; * result.m_z += lambert * ls.intesity.b * closest.GetMat().disfuse.b; * } */ float lambert = lsr.dir.DotProduct(closest.CalculateSurfaceNormal()) * coef; //float lambert = 1.0f; //Lambert disfuseion result.m_x += lambert * ls.intesity.r * closest.GetMat().disfuse.r; result.m_y += lambert * ls.intesity.g * closest.GetMat().disfuse.g; result.m_z += lambert * ls.intesity.b * closest.GetMat().disfuse.b; } coef *= closest.GetMat().reflect; if (coef < 0.0f) { break; } } ray.Trace(ray, quads, lights, c + 1, ref coef, ref result, ref hitLight); return(new ColourRGBA(result, 255)); } } else { return(new ColourRGBA(result, 255)); } } return(null); }
static void Main(string[] args) { Camera camera = new Camera(); camera.SetPositon(new Vector(0.00f, -10.0f, 1.0f)); camera.SetRotation(); if (camera.GetFov() != 45.0f) { camera.SetFov(45.0f); } SurfacePlane worldPlane = new SurfacePlane(); Material mat = new Material(); mat.disfuse = new ColourRGBA(255.0f, 125.0f, 136.0f, 255.0f); //mat.disfuse = new ColourRGBA(1.0f, 1.0f, 1.0f, 1.0f); mat.disfuse.Normalize(); mat.reflect = 0.1f; worldPlane.SetMat(mat); SurfaceSphere worldSphere = new SurfaceSphere(); Material smat = new Material(); smat.disfuse = new ColourRGBA(0.0f, 0.0f, 1.0f, 1.0f); smat.reflect = 0.9f; worldSphere.SetMat(smat); SurfaceSphere worldSphere2 = new SurfaceSphere(); worldSphere2.pos.m_x = -2.0f; worldSphere2.pos.m_y = -2.0f; worldSphere2.pos.m_z = 2.0f; SurfaceSphere worldSphere3 = new SurfaceSphere(); worldSphere3.pos.m_x = 2.0f; worldSphere3.pos.m_y = -2.0f; worldSphere3.pos.m_z = 2.0f; SurfaceSphere worldSphere4 = new SurfaceSphere(); worldSphere4.pos.m_x = 0.0f; worldSphere4.pos.m_y = 2.0f; worldSphere4.pos.m_z = 2.0f; Material smat2 = new Material(); smat2.disfuse = new ColourRGBA(0.5f, 1.0f, 0.5f, 1.0f); //smat2.reflect = 0.5f; Material smat3 = new Material(); smat3.disfuse = new ColourRGBA(0.5f, 0.5f, 0.5f, 1.0f); worldSphere2.SetMat(smat2); worldSphere3.SetMat(smat2); worldSphere4.SetMat(smat3); Surface[] Walls = new Surface[] { worldPlane, worldSphere, worldSphere2, worldSphere3 }; Console.WriteLine("Casting Rays"); Console.WriteLine("Casting: " + ((UInt64)(Width * Height) * rpp).ToString() + " rays!"); //Image to save Bitmap img = new Bitmap(Width, Height); Bitmap highestHits = new Bitmap(Width, Height); //Cast the ray bool hit = false; bool exit = false; float filmDist = 1.0f; //Aspect ratio float filmW = 1.0f; float filmH = 1.0f; if (Width > Height) { filmH = filmW * ((float)Height / (float)Width); } else if (Height > Width) { filmW = filmH * ((float)Width / (float)Height); } float halffilmW = 0.5f * filmW; float halffilmH = 0.5f * filmH; bool looped = false; DateTime startTime = DateTime.Now; Console.Write("Render Started: "); Console.WriteLine(startTime.ToString()); UInt64 hc = 0; UInt64 count = 0; while (!hit && !exit) { if (!looped) { exit = true; } else { if (camera.GetPositon().m_y <= -100) { break; } else { Vector p = camera.GetPositon(); p.m_y -= 1; camera.SetPositon(p); } camera.SetRotation(); } Vector FilmCenter = camera.GetPositon() - filmDist * camera.m_rotation.CameraZ; UInt64 thc = 0; count++; Console.Write("Count: " + count.ToString() + "\r"); UInt64 rayCount = 0; float RayColourContrib = 1.0f / rpp; float halfPixW = 0.5f / Width; float halfPixH = 0.5f / Height; float testRays = RayColourContrib * rpp; Ray ray = new Ray(); //Start casting rays for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { //Work out where we are casting this ray from. float filmX = -1.0f + 2.0f * ((float)x / (float)Width);; float filmY = -1.0f + 2.0f * ((float)y / (float)Height); //Vector result = new Vector(0.0f, 0.0f, 0.0f); float a = 1.0f; Vector rayColour = new Vector(); //build up our colour for (UInt64 r = 0; r < rpp; r++) { //Jittering AA float offX = filmX + Helpers.Rand.RandomBilateral() * halfPixW; float offY = filmY + Helpers.Rand.RandomBilateral() * halfPixH; Vector filmP = FilmCenter + offX * halffilmW * camera.m_rotation.CameraX + offY * halffilmH * camera.m_rotation.CameraY; ray.orgin = camera.GetPositon(); ray.dir = (filmP - camera.GetPositon()); float coef = 1.0f; Vector result = new Vector(0.0f, 0.0f, 0.0f); bool hitLight = false; //rayColour += RayColourContrib * (ray.Trace(ray, Walls, lights, 0, ref coef, ref result, ref hitLight).ColourToVector(ref a)); ray.Trace(ray, Walls, lights, 0, ref coef, ref result, ref hitLight); rayColour += RayColourContrib * result; rayCount++; } //ColourRGBA colour = ray.Trace(ray, Walls, 0, ref att, ref result); //rayColour.Normalize ColourRGBA colour = new ColourRGBA(rayColour, a); if (!looped) { float p = (float)rayCount / (float)((UInt64)(Width * Height) * rpp); Console.Write(((int)(p * 100)).ToString() + " perenct complete\r"); } //Nothing intersects with this ray so black if (colour == null) { //colour = new ColourRGBA(0.0f, 0.0f, 0.0f, 255.0f); colour = Config.Ray.SkyColour; } else { //Correct the gamma. /* * colour.r = Lin2srgb(colour.r); * colour.g = Lin2srgb(colour.g); * colour.b = Lin2srgb(colour.b); */ //colour.Normalize(); colour.Scale(255); colour.Clamp(); } //Convert our colour to a colour windows C# understands Color wColour = Color.FromArgb((int)colour.a, (int)colour.r, (int)colour.g, (int)colour.b); //If its not black we hit something if (colour.r != 0 || colour.g != 0 || colour.b != 0) { thc++; } img.SetPixel(x, y, wColour); } } if (hc < thc) { hc = thc; highestHits = img; } if (thc > 0) { //For when we are displaying the percent complete if (!looped) { Console.WriteLine(""); //Console.Write("Hits: " + thc.ToString() + "_y_" + camera.GetPositon().m_y.ToString() + "\n"); Console.Write("Hits: " + thc.ToString() + "\n"); //worldSphere.pos.PrintVector(); Console.Write("\n"); } else { Console.Write("Count: " + count.ToString() + " Hits: " + thc.ToString() + "\n"); } img.Save("hit/hit_" + thc.ToString() + "_c_" + count.ToString() + ".bmp"); } } if (hit) { highestHits.Save("hit.bmp"); Console.WriteLine("Hit Something"); } else { img.Save("shit.bmp"); } DateTime endTime = DateTime.Now; Console.WriteLine("Saved Image"); Console.Write("Image render completed in(h.m.s):"); Console.WriteLine((endTime - startTime).ToString()); Console.ReadKey(); }