public IEnumerable <Vector2> GetPath(Vector2 start, Vector2 end) { _excludedContours = new List <int>(); var result = new List <Vector2>(); _currentPoint = start; _goal = end; _tracer = new PathTracer(_contours, _goal, _excludedContours); do { result.Add(_currentPoint); List <IntersectedContour> intersectedContours = Utils.GetIntersectedContours(_currentPoint, _goal, _contours); if (intersectedContours.Count == 0) { break; } intersectedContours.Sort(SortByDistance); var contour = intersectedContours.FirstOrDefault(item => _excludedContours.IndexOf(item.Contour.Id) < 0); if (contour == null) { throw new Exception("Can't find path because all contoures are excluded!"); } _currentPoint = contour.IntersectionPoint; result.Add(_currentPoint); _currentPoint = _tracer.Trace(_currentPoint, result, contour.Contour); } while (true); result.Add(_goal); return(result); }
public void TestPathTracer() { PCG pcg = new PCG(); for (int i = 0; i < 5; i++) { World world = new World(); float emittedRadiance = pcg.randomFloat(); float reflectance = pcg.randomFloat(); Material enclosureMaterial = new Material( Brdf: new DiffuseBRDF(pig: new UniformPigment(new Color(1f, 1f, 1f) * reflectance)), EmittedRadiance: new UniformPigment(new Color(1f, 1f, 1f) * emittedRadiance) ); world.addShape(new Sphere(material: enclosureMaterial)); PathTracer pathTracer = new PathTracer( world: world, pcg: pcg, numOfRays: 1, maxDepth: 100, russianRouletteLimit: 101 ); Ray ray = new Ray(origin: new Point(0f, 0f, 0f), dir: new Vec(1f, 0f, 0f)); Color color = pathTracer.computeRadiance(ray); float expected = emittedRadiance / (1.0f - reflectance); Assert.True(Utility.areClose(expected, color.r, 1e-3f), $"TestPathTracer failed - Assert i={i}, 1/3"); Assert.True(Utility.areClose(expected, color.g, 1e-3f), $"TestPathTracer failed - Assert i={i}, 2/3"); Assert.True(Utility.areClose(expected, color.b, 1e-3f), $"TestPathTracer failed - Assert i={i}, 3/3"); } }
static void Main(string[] args) { int nx = 300; int ny = 300; int ns = 50; var(world, cam) = Scenes.CornellScene("../../../../SampleObj/teapot.obj", new SunsetquestRandom(), nx, ny); var worldBVH = new BVH(world); var wl = new IHitable[] { worldBVH }; var pathTracer = new PathTracer(nx, ny, ns, false); uint totalRayCount = 0; sw.Start(); var image = pathTracer.RenderScene(wl, cam, ref totalRayCount, (pcComplete => Console.WriteLine($"{pcComplete}%"))); sw.Stop(); image.Save("test.png"); float seconds = sw.ElapsedMilliseconds / 1000f; float rate = totalRayCount / seconds; float mRate = rate / 1_000_000; Console.WriteLine($"totalRayCount: {totalRayCount}"); Console.WriteLine($"BVH max depth: {worldBVH.MaxTestCount}"); Console.WriteLine($"Duration: {seconds} | Rate: {mRate} MRays / sec."); }
public void Init(OpenTKApp app, CancellationToken exitToken) { _exitToken = exitToken; _app = app; _tasks = new Task[parallelBundles]; _r = RNG.CreateMultipleRNGs(parallelBundles); Screen.Clear(0x2222ff); _acc = new Accumulator(Screen); //var tracer = new WhittedStyleTracer(); var tracer = new PathTracer(); _scene = new Scene(tracer, constructBVH: true); _sceneManager = new SceneManager(_camera, _scene); _sceneManager.Add(SceneDefinitions.Default); _sceneManager.Add(SceneDefinitions.DarkRoom); _sceneManager.Add(SceneDefinitions.PathTracerBoxCool); _sceneManager.Add(SceneDefinitions.PathTracerBox); _sceneManager.Add(SceneDefinitions.BeerTest); _sceneManager.Add(SceneDefinitions.Teapot); _sceneManager.SetScene(0); Statistics.Enabled = false; }
public void BoxTest() { var box0 = new Vec(0, 0, 0); var box1 = new Vec(10, 20, 30); Assert.IsTrue(equalF(PathTracer.probeBox(new Vec(5, 5, 5), box0, box1), -5.0), "Inside box"); Assert.IsTrue(equalF(PathTracer.probeBox(new Vec(5, 25, 5), box0, box1), 5.0), "Outside the box"); }
public void CylTest() { var cyl0 = new Vec(-10, 6, 12); Assert.IsTrue(equalF(PathTracer.probeCylinder(new Vec(-10, 6, 13), cyl0, 3, 3), -1.0), "Inside cyl"); Assert.IsTrue(equalF(PathTracer.probeCylinder(new Vec(-10, 6, 11), cyl0, 3, 3), 1.0), "Outside cyl"); Assert.IsTrue(equalF(PathTracer.probeCylinder(new Vec(-10, 7, 17), cyl0, 3, 10), -2.0), "Inside cyl radial"); Assert.IsTrue(equalF(PathTracer.probeCylinder(new Vec(-10, 10, 17), cyl0, 3, 10), 1.0), "Outside cyl radial"); }
private void OnGUI() { if (GUILayout.Button("Start Render")) { PathTracer p = SceneView.lastActiveSceneView.camera.gameObject.GetComponent <PathTracer>(); if (p == null) { p = SceneView.lastActiveSceneView.camera.gameObject.AddComponent <PathTracer>(); p.Setup(SceneView.lastActiveSceneView.camera); } } if (GUILayout.Button("Stop Render")) { PathTracer p = SceneView.lastActiveSceneView.camera.gameObject.GetComponent <PathTracer>(); if (p != null) { p.Dispose(); Object.DestroyImmediate(p); } } EditorGUILayout.Space(); if (GUILayout.Button("Debug Uniform Grid")) { GameObject existing_grid = GameObject.Find("debug_grid"); if (existing_grid != null) { Object.DestroyImmediate(existing_grid.gameObject); } AccelerationStructures.BuildUniformGridGPU(); GameObject grid = GameObject.CreatePrimitive(PrimitiveType.Cube); grid.name = "debug_grid"; grid.transform.position = AccelerationStructures.SceneBounds.center; grid.transform.localScale = AccelerationStructures.SceneBounds.size; Material grid_material = new Material(Shader.Find("PathTracing/UniformGridDebug")); grid_material.SetBuffer("grid_data", AccelerationStructures.GridData); grid_material.SetVector("grid_origin", AccelerationStructures.GridInfo.grid_origin); grid_material.SetVector("grid_size", AccelerationStructures.GridInfo.grid_size); grid_material.SetInt("num_cells_x", (int)AccelerationStructures.GridInfo.nx); grid_material.SetInt("num_cells_y", (int)AccelerationStructures.GridInfo.ny); grid_material.SetInt("num_cells_z", (int)AccelerationStructures.GridInfo.nz); grid.GetComponent <MeshRenderer>().material = grid_material; } }
private void TracePolygons(IPolygon[] polygons) { tracer = new PathTracer(polygons, goal, excludedPolygons); do { var intersection = FindNearestPolygonIntersection(polygons); if (intersection == null) { return; } currentPoint = intersection.Intersection; currentPath.Add(currentPoint); currentPoint = tracer.Trace(currentPoint, currentPath, intersection.Polygon); currentPath.Add(currentPoint); } while (true); }
public static void Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, TraceWriter log) { string name = req.Query["name"]; int nx = 300; int ny = 300; int ns = 50; string path = (new System.Uri(Assembly.GetExecutingAssembly().CodeBase)).AbsolutePath; path = Path.GetFullPath(path); path = Path.GetDirectoryName(path); path += @"\..\teapot.obj"; log.Info($"Obj path: {path}"); var(world, cam) = Scenes.CornellScene(path, new SunsetquestRandom(), nx, ny); var worldBVH = new BVH(world); var wl = new IHitable[] { worldBVH }; var pathTracer = new PathTracer(nx, ny, ns, false); uint totalRayCount = 0; var sw = Stopwatch.StartNew(); var image = pathTracer.RenderScene(wl, cam, ref totalRayCount, (pcComplete => log.Info($"{pcComplete}%"))); sw.Stop(); //image.Save("test.png"); float seconds = sw.ElapsedMilliseconds / 1000f; float rate = totalRayCount / seconds; float mRate = rate / 1_000_000; log.Info($"totalRayCount: {totalRayCount}"); log.Info($"BVH max depth: {worldBVH.MaxTestCount}"); log.Info($"Duration: {seconds} | Rate: {mRate} MRays / sec."); log.Info($"C# Queue trigger function processed: "); }
public static void ExecuteRender(string file, int width, int height, string pfmFile, string ldrFile, int spp, char rend, Dictionary<string, float> variables, float factor, float gamma, int maxDepth, int nRays, int rrLimit) { Console.WriteLine($"File describing the scene: {file}"); Console.WriteLine($"Image size: {width}x{height}"); Console.WriteLine($"Output PFM-file: {pfmFile}"); Console.WriteLine($"Output LDR-file: {ldrFile}"); Console.WriteLine($"Samples-per-pixel (antialiasing): {spp}"); // Console.WriteLine($"Maximum ray depth: {maxDepth}"); // Console.WriteLine($"Number of sampled rays: {nRays}"); // Console.WriteLine($"Russian Roulette Lower Limit: {rrLimit}"); Console.WriteLine("User-defined overridden variables"); if (variables.Count == 0) Console.WriteLine(" - No Variables"); foreach (var item in variables) { Console.WriteLine($" - {item.Key} = {item.Value}"); } Scene scene = new Scene(); using (FileStream inputSceneStream = File.OpenRead(file)) { try { scene = Scene.parseScene(inputFile: new InputStream(stream: inputSceneStream, fileName: file), variables: variables); } catch (GrammarError e) { SourceLocation loc = e.sourceLocation; Console.WriteLine($"{loc.fileName}:{loc.lineNum}:{loc.colNum}: {e.Message}"); return; } } HdrImage image = new HdrImage(width, height); // Run the ray-tracer ImageTracer tracer = new ImageTracer(i: image, c: scene.camera, sps: (int)MathF.Sqrt(spp)); Render renderer; if (rend == 'o') { Console.WriteLine("\nUsing on/off renderer:"); renderer = new OnOffRender(world: scene.world, background: CC.Black); } else if (rend == 'f') { Console.WriteLine("\nUsing flat renderer:"); renderer = new FlatRender(world: scene.world, background: CC.Black); } else if (rend == 'r') { Console.WriteLine("\nUsing a path tracer:"); renderer = new PathTracer(world: scene.world, numOfRays: nRays, maxDepth: maxDepth, russianRouletteLimit: rrLimit); Console.WriteLine($">>>> Max depth: {((PathTracer)renderer).maxDepth}"); Console.WriteLine($">>>> Russian Roulette Limit: {((PathTracer)renderer).russianRouletteLimit}"); Console.WriteLine($">>>> Number of rays: {((PathTracer)renderer).numOfRays}"); } else if (rend == 'p') { Console.WriteLine("\nUsing a point-light tracer: "); renderer = new PointLightRender(world: scene.world, background: CC.Black); Console.WriteLine($">> Ambient color: {((PointLightRender)renderer).ambientColor}"); } else { Console.WriteLine($"Unknown renderer: {rend}"); return; } Stopwatch sw = new Stopwatch(); sw.Start(); tracer.fireAllRays(renderer); Console.WriteLine("Saving in pfm format..."); using (FileStream outpfmstream = File.OpenWrite(pfmFile)) { image.savePfm(outpfmstream); Console.WriteLine($"Image saved in {pfmFile}"); } Convert.ExecuteConvert(pfmFile, ldrFile, factor, gamma, null); sw.Stop(); TimeSpan ts = sw.Elapsed; string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10); Console.WriteLine("\nRun Time: " + elapsedTime); Console.WriteLine("See you next time!\n"); } //RenderScene
public static void ExecuteDemo(int width, int height, int angle, bool orthogonal, string pfmFile, string ldrFile, int scene, float?luminosity, int spp, char rendType) { Stopwatch sw = new Stopwatch(); sw.Start(); Console.WriteLine("Starting Demo with these parameters:\n"); Console.WriteLine("Width: " + width + " pixels"); Console.WriteLine("Height: " + height + " pixels"); Console.WriteLine("Angle: " + angle + " degrees"); Console.WriteLine(orthogonal ? "Orthogonal Camera" : "Perspective Camera"); Console.WriteLine("pfmFile: " + pfmFile); Console.WriteLine("ldrFile: " + ldrFile); Console.WriteLine("Samples per pixel: " + spp); Console.WriteLine("Render type: " + dictRend[rendType]); Console.WriteLine("\n"); HdrImage image = new HdrImage(width, height); // Camera initialization Console.WriteLine("Creating the camera..."); // var cameraTransf = Transformation.RotationZ(Utility.DegToRad(angle)) * Transformation.Translation(-2.0f, 0.0f, 0.5f) * Tsf.RotationY(Utility.DegToRad(15)); var cameraTransf = Transformation.Translation(-2.0f, 0.0f, 0.0f); Camera camera; if (orthogonal) { camera = new OrthogonalCamera(aspectRatio: (float)width / height, transformation: cameraTransf); } else { camera = new PerspectiveCamera(aspectRatio: (float)width / height, transformation: cameraTransf); } // Default value on/off renderer Render?renderer = null; Console.WriteLine("Creating the scene..."); World world = new World(); List <float> Vertices = new List <float>() { -0.5f, 0.5f }; switch (scene) { case 1: //One sphere for each vertex of the cube foreach (var x in Vertices) { foreach (var y in Vertices) { foreach (var z in Vertices) { world.addShape(new Sphere(Tsf.Translation(new Vec(x, y, z)) * Tsf.Scaling(new Vec(0.1f, 0.1f, 0.1f)))); } // z } // y } // x //Adding two more spheres to break simmetry world.addShape(new Sphere(Tsf.Translation(new Vec(0f, 0f, -0.5f)) * Tsf.Scaling(0.1f))); world.addShape(new Sphere(Tsf.Translation(new Vec(0f, 0.5f, 0f)) * Tsf.Scaling(0.1f))); break; case 2: HdrImage img = new HdrImage(); string inputpfm = "Texture/CokeTexture.pfm"; using (FileStream inputStream = File.OpenRead(inputpfm)) { img.readPfm(inputStream); Console.WriteLine($"Texture {inputpfm} has been correctly read from disk."); } Material groundM = new Material(new DiffuseBRDF(new CheckeredPigment(CC.BrightGreen, CC.Orange, 4)), new UniformPigment(CC.Black)); world.addShape(CC.SKY); world.addShape(new Plane(Tsf.Translation(0f, 0f, -3f), groundM)); world.addShape( new Cylinder( transformation: Tsf.Translation(.5f, -1f, -1f) * Transformation.Scaling(.6f, 0.6f, 1.3f) * Tsf.RotationY(Utility.DegToRad(45)), material: new Material( Brdf: new DiffuseBRDF(new ImagePigment(img)) //EmittedRadiance: new UniformPigment(CC.Red)// new ImagePigment(img) ) ) ); world.addShape( new Cylinder( transformation: Tsf.Translation(.5f, 1f, -1f) * Transformation.Scaling(.6f, 0.6f, 1.3f) * Tsf.RotationY(Utility.DegToRad(-45)), material: new Material( Brdf: new DiffuseBRDF(new ImagePigment(img)) //EmittedRadiance: new UniformPigment(CC.Red)// new ImagePigment(img) ) ) ); break; case 3: PCG pcg = new PCG(); Material sph1Mat = new Material(new DiffuseBRDF(new UniformPigment(CC.BlueChill))); Material sph2Mat = new Material(new DiffuseBRDF(new UniformPigment(Color.random()))); Material boxMat = new Material(new DiffuseBRDF(new UniformPigment(CC.BrightGreen))); world.addShape(new Sphere(Tsf.Scaling(500f), CC.skyMat)); world.addShape(new Plane(Tsf.Translation(0f, 0f, -1f), CC.groundMat)); world.addShape(new CSGUnion(new Sphere(Transformation.Translation(0.5f, -2.6f, 1f) * Transformation.Scaling(0.6f), sph2Mat), new Box(new Point(0f, -2.25f, 0.9f), new Point(1f, -3.25f, 1.8f), null, boxMat))); world.addShape(new Sphere(Tsf.Translation(3f, 5f, 1.6f) * Tsf.Scaling(2.0f, 4.0f, 2.0f), CC.refMat)); world.addShape(new Sphere(Tsf.Translation(4f, -1f, 1.3f) * Tsf.Scaling(1.0f), sph1Mat)); world.addShape(new Sphere(Tsf.Translation(-4f, -0.5f, 1f) * Tsf.Scaling(2f), sph2Mat)); break; case 4: Material mat = new Material(null, new UniformPigment(new Color(10f, 10f, 10f))); world.addShape(CC.SKY); world.addShape(new Plane(Tsf.Scaling(-3f, 0f, 0f) * Tsf.RotationY(Utility.DegToRad(270)), mat)); world.addShape(CC.wikiShape(Tsf.RotationZ(Utility.DegToRad(23)))); // world.addShape(CC.wikiShape(Tsf.RotationZ(Utility.DegToRad(45)))); break; case 5: Material skyM = new Material(new DiffuseBRDF(new UniformPigment(CC.SkyBlue)), new UniformPigment(CC.SkyBlue)); Material checkered = new Material(new DiffuseBRDF(new CheckeredPigment(CC.Blue, CC.Yellow)), new UniformPigment(CC.Black)); Material ground = new Material(new DiffuseBRDF(new CheckeredPigment(CC.LightRed, CC.Orange)), new UniformPigment(CC.Black)); world.addShape(new Sphere(Tsf.Scaling(500f), skyM)); world.addShape(new Cylinder(Tsf.Translation(0f, 2f, -0.5f) * Tsf.Scaling(0.5f), checkered)); world.addShape(new Cone(r: 0.5f, material: checkered)); world.addShape(new Plane(Tsf.Translation(0f, 0f, -1f), ground)); break; default: break; } switch (rendType) { case 'o': renderer = new OnOffRender(world); break; case 'f': renderer = new FlatRender(world); break; case 'p': renderer = new PointLightRender(world); break; case 'r': renderer = new PathTracer(world, CC.Black, new PCG()); break; default: break; } // Ray tracing Console.WriteLine("Rendering the scene..."); var rayTracer = new ImageTracer(image, camera, (int)Math.Sqrt(spp)); if (renderer == null) { renderer = new OnOffRender(world); } rayTracer.fireAllRays(renderer); // Write PFM image Console.WriteLine("Saving in pfm format..."); using (FileStream outpfmstream = File.OpenWrite(pfmFile)) { image.savePfm(outpfmstream); Console.WriteLine($"Image saved in {pfmFile}"); } Convert.ExecuteConvert(pfmFile, ldrFile, Default.factor, Default.gamma, luminosity); sw.Stop(); TimeSpan ts = sw.Elapsed; string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10); Console.WriteLine("RunTime " + elapsedTime); }//Demo