public XMLProcessor(XmlReader doc, World worldref) { _sceneXML = new XmlDocument(); _sceneReader = doc; _sceneXML.Load(_sceneReader); _world = worldref; }
/// <summary> /// Constructor, requires filename and handle for the world /// </summary> /// <param name="filename">File to open</param> /// <param name="worldref">World reference</param> public XMLProcessor(string filename, World worldref) { try { _sceneXML = new XmlDocument(); _sceneReader = new XmlTextReader(filename); _sceneXML.Load(_sceneReader); _rootNode = _sceneXML.DocumentElement; _world = worldref; } catch (System.IO.FileNotFoundException e) { Console.WriteLine(e.ToString()); Environment.Exit(1); } }
/// <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(); } } }
/// <summary> /// Parameterized constructor for a given render fragment /// </summary> /// <param name="w_arg">Reference to world, passed to RenderSceneFragment</param> /// <param name="h0_arg">Smallest horizontal render point</param> /// <param name="h1_arg">Largest horizontal render point</param> /// <param name="v0_arg">Smallest horizontal render point</param> /// <param name="v1_arg">Largest hozitontal render point</param> /// <param name="tno_arg">Thread id</param> public RenderFragmentParameters(World w_arg, int h0_arg, int h1_arg, int v0_arg, int v1_arg, int tno_arg) { worldRef = w_arg; horizontal0 = h0_arg; horizontal1 = h1_arg; vertical0 = v0_arg; vertical1 = v1_arg; threadNo = tno_arg; // construct new thread using lambda expression for parameterized thread start thread = new Thread(() => worldRef.Camera.RenderSceneFragment(worldRef, horizontal0, horizontal1, vertical0, vertical1, threadNo)); thread.Priority = ThreadPriority.Highest; }
/// <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 a single rectangular chunk of the scene /// </summary> /// <param name="worldRef">Reference to the world</param> /// <param name="xCoord1">Smallest x coordinate</param> /// <param name="xCoord2">Largest x coordinate</param> /// <param name="yCoord1">Smallest y coordinate</param> /// <param name="yCoord2">Largest y coordinate</param> /// <param name="threadNum">Thread number</param> public abstract void RenderSceneFragment(World worldRef, int xCoord1, int xCoord2, int yCoord1, int yCoord2, int threadNum);
/// <summary> /// Renders the world on a single thread [deprecated, use RenderSceneMultiThreaded] /// </summary> /// <param name="world">World reference</param> public abstract void RenderScene(World world);
/// <summary> /// Renders a single rectangular chunk of the scene /// </summary> /// <param name="worldRef">Reference to the world</param> /// <param name="xCoord1">Smallest x coordinate</param> /// <param name="xCoord2">Largest x coordinate</param> /// <param name="yCoord1">Smallest y coordinate</param> /// <param name="yCoord2">Largest y coordinate</param> /// <param name="threadNum">Thread number</param> public override void RenderSceneFragment(World worldRef, int xCoord1, int xCoord2, int yCoord1, int yCoord2, int threadNum) { RGBColor L = new RGBColor(); Ray ray = new Ray(); ViewPlane vp = worldRef.CurrentViewPlane; int depth = 0; Point2D samplePoint = new Point2D(); Point2D samplePointPixelSpace = new Point2D(); Point2D samplePointOnDisk = new Point2D(); Point2D samplePointOnLens = new Point2D(); Sampler screenSamplerClone = GlobalVars.VIEWPLANE_SAMPLER.Clone(); Sampler lensSamplerClone = depthSampler.Clone(); //vp.s /= zoom; //Vector2 tmp2 = new Vector2(vp.hres * 0.5f, vp.vres*0.5f); for (int r = yCoord1; r < yCoord2; r++) { for (int c = xCoord1; c < xCoord2; c++) { L = GlobalVars.COLOR_BLACK; for (int n = 0; n < vp.NumSamples; n++) { //Sample on unit square samplePoint = screenSamplerClone.SampleUnitSquare(); //Sample in screenspace //Vector2 tmp1 = new Vector2(c, r); //pp.coords = vp.s * (tmp1 - tmp2 * sp.coords); samplePointPixelSpace.coords.X = vp.PixelSize * (c - vp.HorizontalResolution * 0.5f + samplePoint.coords.X); samplePointPixelSpace.coords.Y = vp.PixelSize * (r - vp.VerticalResolution * 0.5f + samplePoint.coords.Y); samplePointOnDisk = lensSamplerClone.SampleDisk(); samplePointOnLens.coords.X = samplePointOnDisk.coords.X * radius; samplePointOnLens.coords.Y = samplePointOnDisk.coords.Y * radius; //lp.coords = dp.coords * radius; ray.Origin = _eye + samplePointOnLens.coords.X * u + samplePointOnLens.coords.Y * v; ray.Direction = GetRayDirection(samplePointPixelSpace, samplePointOnLens); L += worldRef.CurrentTracer.TraceRay(ray, depth); } L /= vp.NumSamples; L *= _exposureTime; worldRef.DisplayPixel(r, c, L); } } DequeueNextRenderFragment(); }
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(); } } }
/// <summary> /// Parameterized constructor, hands off to base class /// </summary> /// <param name="worldPointer">Pointer to current world</param> public Whitted(World worldPointer) : base(worldPointer) { }
/// <summary> /// Renders a single rectangular chunk of the scene /// </summary> /// <param name="worldRef">Reference to the world</param> /// <param name="xCoord1">Smallest x coordinate</param> /// <param name="xCoord2">Largest x coordinate</param> /// <param name="yCoord1">Smallest y coordinate</param> /// <param name="yCoord2">Largest y coordinate</param> /// <param name="threadNum">Thread number</param> public override void RenderSceneFragment(World worldRef, int xCoord1, int xCoord2, int yCoord1, int yCoord2, int threadNum) { //To avoid clashes with other threads accessing sampler, clone the main world sampler Sampler localSampler = worldRef.CurrentViewPlane.ViewPlaneSampler.Clone(); RGBColor L; ViewPlane vp = worldRef.CurrentViewPlane; Ray ray = new Ray(_eye, new Vect3D(0, 0, 0)); int depth = 0; //Depth of recursion Point2D unitSquareSample = new Point2D(); //Sample point on a unit square Point2D sampleInScreenSpace = new Point2D(); ; //Sample point translated into screen space int height = yCoord2 - yCoord1; int width = xCoord2 - xCoord1; for (int row = 0; row < height; row++) { for (int column = 0; column < width; column++) { L = GlobalVars.COLOR_BLACK; //Start with no color, everything is additive for (int sample = 0; sample < vp.NumSamples; sample++) { unitSquareSample = localSampler.SampleUnitSquare(); sampleInScreenSpace.coords.X = worldRef.CurrentViewPlane.PixelSize * (column + xCoord1 - 0.5f * vp.HorizontalResolution + unitSquareSample.coords.X); sampleInScreenSpace.coords.Y = worldRef.CurrentViewPlane.PixelSize * (row + yCoord1 - 0.5f * vp.VerticalResolution + unitSquareSample.coords.Y); ray.Direction = GetRayDirection(sampleInScreenSpace); L = L + worldRef.CurrentTracer.TraceRay(ray, depth); } L /= vp.NumSamples; L *= _exposureTime; worldRef.DisplayPixel(row + yCoord1, column + xCoord1, L); } } DequeueNextRenderFragment(); }
public XMLProcessor(World worldref) { _sceneXML = new XmlDocument(); _world = worldref; }
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(); } }
public RayCaster(World w) { worldPointer = w; }