Exemple #1
0
        /// <summary>
        /// Renders a frame for the current world across a given number of threads
        /// </summary>
        /// <param name="world">Current world with camera</param>
        /// <param name="numThreads">Number of threads to split workload across</param>
        public virtual void RenderSceneMultithreaded(World world, int numThreads)
        {
            // local ref for viewplane for minimized member accesses
            ViewPlane vp = world.CurrentViewPlane;

            // set zoom for frame zero to ensure animation does not cause increasing zoom
            if(GlobalVars.frameno == 0)
                vp.PixelSize /= _zoom;

            // list of all active threads, for spinwait
            List<RenderFragmentParameters> threads = new List<RenderFragmentParameters>();
            // concurrent queue for thread safe dequeue of render chunks
            taskQueue = new ConcurrentQueue<RenderFragmentParameters>();

            //Find out how many chunks the screen can be divided into;
            int hChunks = (int)Math.Floor((decimal)vp.HorizontalResolution / (decimal)GlobalVars.FRAGMENT_SIZE);
            int vChunks = (int)Math.Floor((decimal)vp.VerticalResolution / (decimal)GlobalVars.FRAGMENT_SIZE);
            //Find out the size of the boundaries which do not fit into chunks
            int hRemaining = vp.HorizontalResolution % GlobalVars.FRAGMENT_SIZE;
            int vRemaining = vp.VerticalResolution % GlobalVars.FRAGMENT_SIZE;

            int threadNo = 0; //Label for each thread created

            //Queue up render chunks
            int hor0, hor1, vert0, vert1;
            RenderFragmentParameters parameters;
            for(int v = 0; v < vChunks; v++)
            {
                for(int h = 0; h < hChunks; h++)
                {
                    //Queue up threads
                    hor0 = GlobalVars.FRAGMENT_SIZE * h;
                    hor1 = GlobalVars.FRAGMENT_SIZE * (h + 1);
                    vert0 = GlobalVars.FRAGMENT_SIZE * v;
                    vert1 = GlobalVars.FRAGMENT_SIZE * (v + 1);
                    parameters = new RenderFragmentParameters(world, hor0, hor1, vert0, vert1, threadNo);
                    threads.Add(parameters);
                    taskQueue.Enqueue(parameters);
                    threadNo++;
                }
                //Add in additional fragments for the right screen edge if resolution isn't nicely
                //divisible
                if(hRemaining != 0)
                {
                    hor0 = GlobalVars.FRAGMENT_SIZE * hChunks;
                    hor1 = vp.HorizontalResolution;
                    vert0 = GlobalVars.FRAGMENT_SIZE * v;
                    vert1 = GlobalVars.FRAGMENT_SIZE * (v + 1);
                    parameters = new RenderFragmentParameters(world, hor0, hor1, vert0, vert1, threadNo);
                    threads.Add(parameters);
                    taskQueue.Enqueue(parameters);
                }
            }
            //Add in additional fragments for the top edge if resolution isn't nicely divisible
            if(vRemaining != 0)
            {
                for(int h = 0; h < hChunks; h++)
                {
                    hor0 = GlobalVars.FRAGMENT_SIZE * h;
                    hor1 = GlobalVars.FRAGMENT_SIZE * (h + 1);
                    vert0 = GlobalVars.FRAGMENT_SIZE * vChunks;
                    vert1 = vp.VerticalResolution;
                    parameters = new RenderFragmentParameters(world, hor0, hor1, vert0, vert1, threadNo);
                    threads.Add(parameters);
                    taskQueue.Enqueue(parameters);
                }
                //Add in corner edge fragment if the right edge of the screen wasn't nicely divisible
                if (hRemaining != 0)
                {
                    hor0 = GlobalVars.FRAGMENT_SIZE * hChunks;
                    hor1 = vp.HorizontalResolution;
                    vert0 = GlobalVars.FRAGMENT_SIZE * vChunks;
                    vert1 = vp.VerticalResolution;
                    parameters = new RenderFragmentParameters(world, hor0, hor1, vert0, vert1, threadNo);
                    threads.Add(parameters);
                    taskQueue.Enqueue(parameters);
                }
            }

            // dequeue either the provided number of threads, or the total number of threads, whichever is smaller
            int numThreadsToDequeue = (numThreads < threadNo) ? numThreads : threadNo;

            // dequeue the initial thread count of threads
            RenderFragmentParameters[] initialThreads = new RenderFragmentParameters[numThreadsToDequeue];
            for (int i = 0; i < numThreadsToDequeue; i++)
            {
                while(!taskQueue.TryDequeue(out initialThreads[i])) { // ensure every dequeue succeeds
                }
            }

            // begin rendering in all dequeued threads
            foreach(RenderFragmentParameters renderFragment in initialThreads)
            {
                renderFragment.Begin();
            }

            //Set the thread priority for main thread to low
            Thread.CurrentThread.Priority = ThreadPriority.Lowest;

            //Spinwait for all threads
            bool allDone = false;
            do
            {
                allDone = true;
                foreach (RenderFragmentParameters thread in threads)
                {
                    if (thread.thread.IsAlive)
                    {
                        allDone = false;
                    }
                }
                world.PollEvents();

            } while (!allDone);

            // update liveimage
            world.LiveView.LiveImage = new SFML.Graphics.Image((uint)vp.HorizontalResolution, (uint)vp.VerticalResolution, world.RenderImage);
        }
        /// <summary>
        /// Renders the world on a single thread [deprecated, use RenderSceneMultiThreaded]
        /// </summary>
        /// <param name="world">World reference</param>
        public override void RenderScene(World worldRef)
        {
            RGBColor lightingSum;
            ViewPlane vp = worldRef.CurrentViewPlane;
            Ray ray = new Ray(_eye,new Vect3D(0,0,0));
            int depth = 0; //Depth of recursion
            Point2D sp = new Point2D(); //Sample point on a unit square
            Point2D pp = new Point2D(); ; //Sample point translated into screen space

            worldRef.OpenWindow(vp.HorizontalResolution, vp.VerticalResolution);
            vp.PixelSize /= _zoom;

            for(int row = 0; row < vp.VerticalResolution; row++)
            {
                for(int column = 0; column < vp.HorizontalResolution; column++)
                {
                    lightingSum = GlobalVars.COLOR_BLACK; //Start with no color, everything is additive

                    for(int sample = 0; sample < vp.NumSamples; sample ++)
                    {
                        sp = worldRef.CurrentViewPlane.ViewPlaneSampler.SampleUnitSquare();
                        pp.coords.X = worldRef.CurrentViewPlane.PixelSize * (column - 0.5f * vp.HorizontalResolution + sp.coords.X);
                        pp.coords.Y = worldRef.CurrentViewPlane.PixelSize * (row - 0.5f * vp.VerticalResolution + sp.coords.Y);
                        ray.Direction = GetRayDirection(pp);
                        lightingSum = lightingSum + worldRef.CurrentTracer.TraceRay(ray, depth);
                    }

                    lightingSum /= vp.NumSamples;
                    lightingSum *= _exposureTime;
                    worldRef.DisplayPixel(row, column, lightingSum);

                    //Poll events in live render view
                    worldRef.PollEvents();
                }
            }
        }
        public override void RenderScene(World w)
        {
            RGBColor L = new RGBColor();
            Ray ray = new Ray();
            ViewPlane vp = w.CurrentViewPlane;
            int depth = 0;

            Point2D sp = new Point2D();
            Point2D pp = new Point2D();
            Point2D dp = new Point2D();
            Point2D lp = new Point2D();

            //w.open_window(vp.hres, vp.vres);
            vp.PixelSize /= _zoom;

            for(int r = 0; r < vp.VerticalResolution-1; r++)
            {
                for(int c = 0; c < vp.HorizontalResolution-1; c++)
                {
                    L = GlobalVars.COLOR_BLACK;

                    for(int n = 0; n < vp.NumSamples; n++)
                    {
                        //Sample on unit square
                        sp = vp.ViewPlaneSampler.SampleUnitSquare();
                        //Sample in screenspace
                        pp.coords.X = vp.PixelSize * (c - vp.HorizontalResolution * 0.5f + sp.coords.X);
                        pp.coords.Y = vp.PixelSize * (r - vp.VerticalResolution * 0.5f + sp.coords.Y);

                        dp = depthSampler.SampleDisk();
                        lp.coords.X = dp.coords.X * radius;
                        lp.coords.Y = dp.coords.Y * radius;

                        ray.Origin = _eye + lp.coords.X * u + lp.coords.Y * v;
                        ray.Direction = GetRayDirection(pp, lp);
                        L += w.CurrentTracer.TraceRay(ray, depth);
                    }
                    L /= vp.NumSamples;
                    L *= _exposureTime;
                    w.DisplayPixel(r, c, L);
                    w.PollEvents();
                }
            }
        }
Exemple #4
0
        static void Main(string[] args)
        {
            bool multithread = false;
            int threads = 2;

            int a = 0;
            int numArgs = args.Length;

            if(numArgs == 0)
            {
                Console.WriteLine("Usage: scsraytracer -I \"Input XML path\" -O \"Output bmp path\"");
                Console.WriteLine("Additional options:\n-V: Verbose output, default off\n-T #: Number of threads");
                Console.ReadKey();
                return;
            }
            try {
                //Cycle through all arguments
                while (a < numArgs)
                {
                    string arg = args[a];
                    if (arg.Equals("-I") && GlobalVars.inFile == null)
                    {
                        if ((a + 1 < numArgs) && File.Exists(args[a+1]))
                        {
                            GlobalVars.inFile = args[a + 1];
                            a += 2;
                        }
                        else
                        {
                            throw new ArgumentException("Invalid input file location");
                        }
                    }
                    else if (arg.Equals("-O") && GlobalVars.outFile == null)
                    {
                        if ((a + 1 < numArgs))
                        {
                            GlobalVars.outFile = args[a + 1];
                            a += 2;
                        }
                        else
                        {
                            throw new ArgumentException("Invalid output file location");
                        }
                    }
                    else if (arg.Equals("-V"))
                    {
                        GlobalVars.verbose = true;
                        a++;
                    }
                    else if (arg.Equals("-T"))
                    {
                        multithread = true;
                        threads = Convert.ToInt32(args[a + 1]);
                        a += 2;
                    }
                }

                if(GlobalVars.outFile == null)
                {
                    throw new ArgumentException();
                }

                if(File.Exists(GlobalVars.outFile))
                {
                    GetUserInput:
                    Console.Write("File " + GlobalVars.outFile + " exists! Overwrite? (y/n): ");
                    switch(Console.ReadKey().KeyChar)
                    {
                        case 'y':
                            //do nothing
                            break;
                        case 'n':
                            Console.WriteLine("\nOk, exiting now.");
                            return;
                        default:
                            Console.Write("\n");
                            goto GetUserInput;
                    }
                }

            }
            catch (ArgumentException e)
            {
                Console.WriteLine(e.ToString());
                Console.WriteLine("Usage: scsraytracer -I \"Input XML path\" -O \"Output bmp path\"");
                Console.WriteLine("Additional options:\n-V: Verbose output, default off\n-T #: Number of threads");
                Console.ReadKey();
                return;
            }
            //Elevate process priority to high

            using (Process p = Process.GetCurrentProcess())
                p.PriorityClass = ProcessPriorityClass.High;
            World w = new World();
            GlobalVars.WORLD_REF = w;

            w.Build();
            w.OpenWindow(w.CurrentViewPlane.HorizontalResolution, w.CurrentViewPlane.VerticalResolution);
            //GlobalVars.frameno = 120;
            //w.Animate();
            //while (GlobalVars.frameno < 130)
            //{
                //w.camera.setEye(new Point3D(200, 200, GlobalVars.cam_zcoord));
            //    w.camera.setLookat(new Point3D(0, 0, GlobalVars.lookat_zcoord));
            //    w.camera.compute_uvw();

                switch (multithread)
                {
                    case false:
                        w.Camera.RenderSceneMultithreaded(w, 1);
                        break;
                    case true:
                        w.Camera.RenderSceneMultithreaded(w, threads);
                        break;
                }

                w.SaveDisplayedImage(GlobalVars.outFile);
                //w.SaveDisplayedImage("E:\\weird\\frame_" + GlobalVars.frameno + ".bmp");
                //    GlobalVars.cam_zcoord -= 10;
                //    GlobalVars.lookat_zcoord -= 10;
                //    GlobalVars.frameno += 1;

                //GlobalVars.frameno+=1;
                //w.Animate();
            //}

            while(!GlobalVars.should_close)
            {
                w.PollEvents();
            }
        }