Beispiel #1
0
        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);
        }
Beispiel #2
0
        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();
        }