public void render(IDisplay display) { this.display = display; display.imageBegin(imageWidth, imageHeight, 32); // set members variables bucketCounter = 0; // start task SunflowSharp.Systems.Timer timer = new SunflowSharp.Systems.Timer(); timer.start(); BucketThread[] renderThreads = new BucketThread[scene.getThreads()]; for (int i = 0; i < renderThreads.Length; i++) { renderThreads[i] = new BucketThread(this); renderThreads[i].setPriority(scene.getThreadPriority()); renderThreads[i].start(); } for (int i = 0; i < renderThreads.Length; i++) { try { renderThreads[i].join(); } catch (Exception e) { UI.printError(UI.Module.BCKT, "Bucket processing thread {0} of {1} was interrupted", i + 1, renderThreads.Length); } } timer.end(); UI.printInfo(UI.Module.BCKT, "Render time: {0}", timer.ToString()); display.imageEnd(); }
public void render(IDisplay display) { this.display = display; display.imageBegin(imageWidth, imageHeight, 32); // set members variables bucketCounter = 0; // start task SunflowSharp.Systems.Timer timer = new SunflowSharp.Systems.Timer(); timer.start(); BucketThread[] renderThreads = new BucketThread[scene.getThreads()]; for (int i = 0; i < renderThreads.Length; i++) { renderThreads[i] = new BucketThread(this); renderThreads[i].setPriority(scene.getThreadPriority()); renderThreads[i].start(); } for (int i = 0; i < renderThreads.Length; i++) { try { renderThreads[i].join(); } catch (Exception e) { UI.printError(UI.Module.BCKT, "Bucket processing thread {0} of {1} was interrupted", i + 1, renderThreads.Length); } finally { renderThreads[i].updateStats(); } } timer.end(); UI.printInfo(UI.Module.BCKT, "Render time: {0}", timer.ToString()); display.imageEnd(); }
public void build(PrimitiveList primitives) { this.primitives = primitives; int n = primitives.getNumPrimitives(); UI.printDetailed(UI.Module.ACCEL, "Getting bounding box ..."); bounds = primitives.getWorldBounds(null); objects = new int[n]; for (int i = 0; i < n; i++) objects[i] = i; UI.printDetailed(UI.Module.ACCEL, "Creating tree ..."); int initialSize = 3 * (2 * 6 * n + 1); List<int> tempTree = new List<int>((initialSize + 3) / 4); BuildStats stats = new BuildStats(); Timer t = new Timer(); t.start(); buildHierarchy(tempTree, objects, stats); t.end(); UI.printDetailed(UI.Module.ACCEL, "Trimming tree ..."); tree = tempTree.ToArray(); // display stats stats.printStats(); UI.printDetailed(UI.Module.ACCEL, " * Creation time: %s", t); UI.printDetailed(UI.Module.ACCEL, " * Usage of init: %3d%%", 100 * tree.Length / initialSize); UI.printDetailed(UI.Module.ACCEL, " * Tree memory: %s", Memory.SizeOf(tree)); UI.printDetailed(UI.Module.ACCEL, " * Indices memory: %s", Memory.SizeOf(objects)); }
public FastDisplay() { image = null; frame = null; t = new Timer(); frames = 0; seconds = 0; }
public RealtimeBenchmark(bool showGUI, int threads) { IDisplay display = /*showGUI ? new FastDisplay() :*/ new FileDisplay(false); UI.printInfo(UI.Module.BENCH, "Preparing benchmarking scene ..."); // settings parameter("threads", threads); // spawn regular priority threads parameter("threads.lowPriority", false); parameter("resolutionX", 512); parameter("resolutionY", 512); parameter("aa.min", -3); parameter("aa.max", 0); parameter("depths.diffuse", 1); parameter("depths.reflection", 1); parameter("depths.refraction", 0); parameter("bucket.order", "hilbert"); parameter("bucket.size", 32); options(SunflowAPI.DEFAULT_OPTIONS); // camera Point3 eye = new Point3(30, 0, 10.967f); Point3 target = new Point3(0, 0, 5.4f); Vector3 up = new Vector3(0, 0, 1); parameter("transform", Matrix4.lookAt(eye, target, up)); parameter("fov", 45.0f); camera("camera", "pinhole"); parameter("camera", "camera"); options(SunflowAPI.DEFAULT_OPTIONS); // geometry createGeometry(); // this first render is not timed, it caches the acceleration data // structures and tesselations so they won't be // included in the main timing UI.printInfo(UI.Module.BENCH, "Rendering warmup frame ..."); render(SunflowAPI.DEFAULT_OPTIONS, display); // now disable all output - and run the benchmark UI.set(null); Timer t = new Timer(); t.start(); float phi = 0; int frames = 0; while (phi < 4 * Math.PI) { eye.x = 30 * (float)Math.Cos(phi); eye.y = 30 * (float)Math.Sin(phi); phi += (float)(Math.PI / 30); frames++; // update camera parameter("transform", Matrix4.lookAt(eye, target, up)); camera("camera", null); render(SunflowAPI.DEFAULT_OPTIONS, display); } t.end(); UI.set(new ConsoleInterface()); UI.printInfo(UI.Module.BENCH, "Benchmark results:"); UI.printInfo(UI.Module.BENCH, " * Average FPS: {0,6:0.00", frames / t.seconds()); UI.printInfo(UI.Module.BENCH, " * Total time: {0}", t); }
public bool build(Options options) { // read options maxDiffuseDepth = options.getInt("depths.diffuse", maxDiffuseDepth); maxReflectionDepth = options.getInt("depths.reflection", maxReflectionDepth); maxRefractionDepth = options.getInt("depths.refraction", maxRefractionDepth); string giEngineType = options.getstring("gi.engine", null); giEngine = PluginRegistry.giEnginePlugins.createObject(giEngineType); string caustics = options.getstring("caustics", null); causticPhotonMap = PluginRegistry.causticPhotonMapPlugins.createObject(caustics); // validate options maxDiffuseDepth = Math.Max(0, maxDiffuseDepth); maxReflectionDepth = Math.Max(0, maxReflectionDepth); maxRefractionDepth = Math.Max(0, maxRefractionDepth); SunflowSharp.Systems.Timer t = new SunflowSharp.Systems.Timer(); t.start(); // count total number of light samples int numLightSamples = 0; for (int i = 0; i < lights.Length; i++) { numLightSamples += lights[i].getNumSamples(); } // initialize gi engine if (giEngine != null) { if (!giEngine.init(options, scene)) { return(false); } } if (!calculatePhotons(causticPhotonMap, "caustic", 0, options)) { return(false); } t.end(); UI.printInfo(UI.Module.LIGHT, "Light Server stats:"); UI.printInfo(UI.Module.LIGHT, " * Light sources found: {0}", lights.Length); UI.printInfo(UI.Module.LIGHT, " * Light samples: {0}", numLightSamples); UI.printInfo(UI.Module.LIGHT, " * Max raytrace depth:"); UI.printInfo(UI.Module.LIGHT, " - Diffuse {0}", maxDiffuseDepth); UI.printInfo(UI.Module.LIGHT, " - Reflection {0}", maxReflectionDepth); UI.printInfo(UI.Module.LIGHT, " - Refraction {0}", maxRefractionDepth); UI.printInfo(UI.Module.LIGHT, " * GI engine {0}", giEngineType == null ? "none" : giEngineType); UI.printInfo(UI.Module.LIGHT, " * Caustics: {0}", caustics == null ? "none" : caustics); UI.printInfo(UI.Module.LIGHT, " * Shader override: {0}", shaderOverride); UI.printInfo(UI.Module.LIGHT, " * Photon override: {0}", shaderOverridePhotons); UI.printInfo(UI.Module.LIGHT, " * Build time: {0}", t.ToString()); return(true); }
public void execute(BenchmarkTest test) { // clear previous results for (int i = 0; i < timers.Length; i++) timers[i] = null; // loop for the specified number of iterations or until the time limit long startTime = NanoTime.Now; for (int i = 0; i < timers.Length && ((NanoTime.Now - startTime) / 1000000000) < timeLimit; i++) { UI.printInfo(UI.Module.BENCH, "Running iteration {0}", (i + 1)); timers[i] = new Timer(); test.kernelBegin(); timers[i].start(); test.kernelMain(); timers[i].end(); test.kernelEnd(); } // report stats double avg = 0; double min = double.PositiveInfinity; double max = double.NegativeInfinity; int n = 0; foreach (Timer t in timers) { if (t == null) break; double s = t.seconds(); min = Math.Min(min, s); max = Math.Max(max, s); avg += s; n++; } if (n == 0) return; avg /= n; double stdDev = 0; foreach (Timer t in timers) { if (t == null) break; double s = t.seconds(); stdDev += (s - avg) * (s - avg); } stdDev = Math.Sqrt(stdDev / n); UI.printInfo(UI.Module.BENCH, "Benchmark results:"); UI.printInfo(UI.Module.BENCH, " * Iterations: {0}", n); UI.printInfo(UI.Module.BENCH, " * Average: {0}", Timer.tostring(avg)); UI.printInfo(UI.Module.BENCH, " * Fastest: {0}", Timer.tostring(min)); UI.printInfo(UI.Module.BENCH, " * Longest: {0}", Timer.tostring(max)); UI.printInfo(UI.Module.BENCH, " * Deviation: {0}", Timer.tostring(stdDev)); for (int i = 0; i < timers.Length && timers[i] != null; i++) UI.printDetailed(UI.Module.BENCH, " * Iteration {0}: {1}", i + 1, timers[i]); }
public void render(IDisplay display) { this.display = display; display.imageBegin(imageWidth, imageHeight, 0); // create first bucket SmallBucket b = new SmallBucket(); b.x = b.y = 0; int s = Math.Max(imageWidth, imageHeight); b.size = 1; while (b.size < s) { b.size <<= 1; } smallBucketQueue = new Queue <SmallBucket>();//PriorityBlockingQueue<SmallBucket>(); smallBucketQueue.Enqueue(b); UI.taskStart("Progressive Render", 0, imageWidth * imageHeight); SunflowSharp.Systems.Timer t = new SunflowSharp.Systems.Timer(); t.start(); counter = 0; counterMax = imageWidth * imageHeight; SmallBucketThread[] renderThreads = new SmallBucketThread[scene.getThreads()]; for (int i = 0; i < renderThreads.Length; i++) { renderThreads[i] = new SmallBucketThread(this); renderThreads[i].setPriority(scene.getThreadPriority()); renderThreads[i].start(); } for (int i = 0; i < renderThreads.Length; i++) { try { renderThreads[i].join(); } catch (Exception e) { UI.printError(UI.Module.IPR, "Thread {0} of {1} was interrupted", i + 1, renderThreads.Length); } finally { renderThreads[i].updateStats(); } } UI.taskStop(); t.end(); UI.printInfo(UI.Module.IPR, "Rendering time: {0}", t.ToString()); display.imageEnd(); }
public bool build(Options options) { // read options maxDiffuseDepth = options.getInt("depths.diffuse", maxDiffuseDepth); maxReflectionDepth = options.getInt("depths.reflection", maxReflectionDepth); maxRefractionDepth = options.getInt("depths.refraction", maxRefractionDepth); string giEngineType = options.getstring("gi.engine", null); giEngine = PluginRegistry.giEnginePlugins.createObject(giEngineType); string caustics = options.getstring("caustics", null); causticPhotonMap = PluginRegistry.causticPhotonMapPlugins.createObject(caustics); // validate options maxDiffuseDepth = Math.Max(0, maxDiffuseDepth); maxReflectionDepth = Math.Max(0, maxReflectionDepth); maxRefractionDepth = Math.Max(0, maxRefractionDepth); SunflowSharp.Systems.Timer t = new SunflowSharp.Systems.Timer(); t.start(); // count total number of light samples int numLightSamples = 0; for (int i = 0; i < lights.Length; i++) numLightSamples += lights[i].getNumSamples(); // initialize gi engine if (giEngine != null) { if (!giEngine.init(options, scene)) return false; } if (!calculatePhotons(causticPhotonMap, "caustic", 0, options)) return false; t.end(); UI.printInfo(UI.Module.LIGHT, "Light Server stats:"); UI.printInfo(UI.Module.LIGHT, " * Light sources found: {0}", lights.Length); UI.printInfo(UI.Module.LIGHT, " * Light samples: {0}", numLightSamples); UI.printInfo(UI.Module.LIGHT, " * Max raytrace depth:"); UI.printInfo(UI.Module.LIGHT, " - Diffuse {0}", maxDiffuseDepth); UI.printInfo(UI.Module.LIGHT, " - Reflection {0}", maxReflectionDepth); UI.printInfo(UI.Module.LIGHT, " - Refraction {0}", maxRefractionDepth); UI.printInfo(UI.Module.LIGHT, " * GI engine {0}", giEngineType == null ? "none" : giEngineType); UI.printInfo(UI.Module.LIGHT, " * Caustics: {0}", caustics == null ? "none" : caustics); UI.printInfo(UI.Module.LIGHT, " * Shader override: {0}", shaderOverride); UI.printInfo(UI.Module.LIGHT, " * Photon override: {0}", shaderOverridePhotons); UI.printInfo(UI.Module.LIGHT, " * Build time: {0}", t.ToString()); return true; }
/** * Compile the specified code string via Janino. The code must implement a * build method as described above. The build method is not called on the * output, it is up the caller to do so. * * @param code java code string * @return a valid SunflowAPI object upon succes, <code>null</code> * otherwise. */ public static SunflowAPI compile(string code) { try { Timer t = new Timer(); t.start(); SunflowAPI api = null;//(SunflowAPI) ClassBodyEvaluator.createFastClassBodyEvaluator(new Scanner(null, new stringReader(code)), SunflowAPI.class, (ClassLoader) null); //fixme: the dynamic loading t.end(); UI.printInfo(UI.Module.API, "Compile time: {0}", t.ToString()); return api; } catch (Exception e) { UI.printError(UI.Module.API, "{0}", e); return null; } }
public void build(PrimitiveList primitives) { Timer t = new Timer(); t.start(); this.primitives = primitives; int n = primitives.getNumPrimitives(); // compute bounds bounds = primitives.getWorldBounds(null); // create grid from number of objects bounds.enlargeUlps(); Vector3 w = bounds.getExtents(); double s = Math.Pow((w.x * w.y * w.z) / n, 1 / 3.0); nx = MathUtils.clamp((int)((w.x / s) + 0.5), 1, 128); ny = MathUtils.clamp((int)((w.y / s) + 0.5), 1, 128); nz = MathUtils.clamp((int)((w.z / s) + 0.5), 1, 128); voxelwx = w.x / nx; voxelwy = w.y / ny; voxelwz = w.z / nz; invVoxelwx = 1 / voxelwx; invVoxelwy = 1 / voxelwy; invVoxelwz = 1 / voxelwz; UI.printDetailed(UI.Module.ACCEL, "Creating grid: %dx%dx%d ...", nx, ny, nz); List<int>[] buildCells = new List<int>[nx * ny * nz]; // add all objects into the grid cells they overlap int[] imin = new int[3]; int[] imax = new int[3]; int numCellsPerObject = 0; for (int i = 0; i < n; i++) { getGridIndex(primitives.getPrimitiveBound(i, 0), primitives.getPrimitiveBound(i, 2), primitives.getPrimitiveBound(i, 4), imin); getGridIndex(primitives.getPrimitiveBound(i, 1), primitives.getPrimitiveBound(i, 3), primitives.getPrimitiveBound(i, 5), imax); for (int ix = imin[0]; ix <= imax[0]; ix++) { for (int iy = imin[1]; iy <= imax[1]; iy++) { for (int iz = imin[2]; iz <= imax[2]; iz++) { int idx = ix + (nx * iy) + (nx * ny * iz); if (buildCells[idx] == null) buildCells[idx] = new List<int>(); buildCells[idx].Add(i); numCellsPerObject++; } } } } UI.printDetailed(UI.Module.ACCEL, "Building cells ..."); int numEmpty = 0; int numInFull = 0; cells = new int[nx * ny * nz][]; //int i = 0; //foreach (List<int> cell in buildCells) for (int i = 0; i < buildCells.Length; i++) { if (buildCells[i] != null) { if (buildCells[i].Count == 0) { numEmpty++; buildCells[i] = null; } else { cells[i] = buildCells[i].ToArray(); numInFull += buildCells[i].Count; } } else numEmpty++; //i++; } t.end(); UI.printDetailed(UI.Module.ACCEL, "Uniform grid statistics:"); UI.printDetailed(UI.Module.ACCEL, " * Grid cells: {0}", cells.Length); UI.printDetailed(UI.Module.ACCEL, " * Used cells: {0}", cells.Length - numEmpty); UI.printDetailed(UI.Module.ACCEL, " * Empty cells: {0}", numEmpty); UI.printDetailed(UI.Module.ACCEL, " * Occupancy: {0}", 100.0 * (cells.Length - numEmpty) / cells.Length); UI.printDetailed(UI.Module.ACCEL, " * Objects/Cell: {0}", (double)numInFull / (double)cells.Length); UI.printDetailed(UI.Module.ACCEL, " * Objects/Used Cell: {0}", (double)numInFull / (double)(cells.Length - numEmpty)); UI.printDetailed(UI.Module.ACCEL, " * Cells/Object: {0}", (double)numCellsPerObject / (double)n); UI.printDetailed(UI.Module.ACCEL, " * Build time: {0}", t.ToString()); }
public bool calculatePhotons(PhotonStore map, string type, int seed, Options options) { if (map == null) return true; if (lights.Length == 0) { UI.printError(UI.Module.LIGHT, "Unable to trace {0} photons, no lights in scene", type); return false; } float[] histogram = new float[lights.Length]; histogram[0] = lights[0].getPower(); for (int i = 1; i < lights.Length; i++) histogram[i] = histogram[i - 1] + lights[i].getPower(); UI.printInfo(UI.Module.LIGHT, "Tracing {0} photons ...", type); map.prepare(options, scene.getBounds()); int numEmittedPhotons = map.numEmit(); if (numEmittedPhotons <= 0 || histogram[histogram.Length - 1] <= 0) { UI.printError(UI.Module.LIGHT, "Photon mapping enabled, but no {0} photons to emit", type); return false; } UI.taskStart("Tracing " + type + " photons", 0, numEmittedPhotons); Thread[] photonThreads = new Thread[scene.getThreads()]; float scale = 1.0f / numEmittedPhotons; int delta = numEmittedPhotons / photonThreads.Length; photonCounter = 0; SunflowSharp.Systems.Timer photonTimer = new SunflowSharp.Systems.Timer(); photonTimer.start(); for (int i = 0; i < photonThreads.Length; i++) { int threadID = i; int start = threadID * delta; int end = (threadID == (photonThreads.Length - 1)) ? numEmittedPhotons : (threadID + 1) * delta; photonThreads[i] = new Thread(new ThreadStart(new CalculatePhotons(start, end, this, seed, histogram, scale, map, lockObj).Run)); photonThreads[i].Priority = scene.getThreadPriority(); photonThreads[i].Start(); } for (int i = 0; i < photonThreads.Length; i++) { try { photonThreads[i].Join(); } catch (Exception e) { UI.printError(UI.Module.LIGHT, "Photon thread {0} of {1} was interrupted", i + 1, photonThreads.Length); return false; } } if (UI.taskCanceled()) { UI.taskStop(); // shut down task cleanly return false; } photonTimer.end(); UI.taskStop(); UI.printInfo(UI.Module.LIGHT, "Tracing time for {0} photons: {1}", type, photonTimer.ToString()); map.init(); return true; }
public static string tostring(double seconds) { Timer t = new Timer(); t.endTime = (long)(seconds * 1e9); return t.ToString(); }
public static string tostring(long nanos) { Timer t = new Timer(); t.endTime = nanos; return t.ToString(); }
public void init() { UI.printInfo(UI.Module.LIGHT, "Balancing caustics photon map ..."); Timer t = new Timer(); t.start(); balance(); t.end(); UI.printInfo(UI.Module.LIGHT, "Caustic photon map:"); UI.printInfo(UI.Module.LIGHT, " * Photons stored: %d", storedPhotons); UI.printInfo(UI.Module.LIGHT, " * Photons/estimate: %d", gatherNum); maxRadius = 1.4f * (float)Math.Sqrt(maxPower * gatherNum); UI.printInfo(UI.Module.LIGHT, " * Estimate radius: %.3f", gatherRadius); UI.printInfo(UI.Module.LIGHT, " * Maximum radius: %.3f", maxRadius); UI.printInfo(UI.Module.LIGHT, " * Balancing time: %s", t.ToString()); if (gatherRadius > maxRadius) gatherRadius = maxRadius; }
public void init() { UI.printInfo(UI.Module.LIGHT, "Balancing global photon map ..."); UI.taskStart("Balancing global photon map", 0, 1); Timer t = new Timer(); t.start(); balance(); t.end(); UI.taskStop(); UI.printInfo(UI.Module.LIGHT, "Global photon map:"); UI.printInfo(UI.Module.LIGHT, " * Photons stored: %d", storedPhotons); UI.printInfo(UI.Module.LIGHT, " * Photons/estimate: %d", numGather); UI.printInfo(UI.Module.LIGHT, " * Estimate radius: %.3f", gatherRadius); maxRadius = 1.4f * (float)Math.Sqrt(maxPower * numGather); UI.printInfo(UI.Module.LIGHT, " * Maximum radius: %.3f", maxRadius); UI.printInfo(UI.Module.LIGHT, " * Balancing time: %s", t.ToString()); if (gatherRadius > maxRadius) gatherRadius = maxRadius; t.start(); precomputeRadiance(); t.end(); UI.printInfo(UI.Module.LIGHT, " * Precompute time: %s", t.ToString()); UI.printInfo(UI.Module.LIGHT, " * Radiance photons: %d", storedPhotons); UI.printInfo(UI.Module.LIGHT, " * Search radius: %.3f", gatherRadius); }
public override bool parse(Stream stream, SunflowAPI api) { //string localDir = Path.GetFullPath(filename); numLightSamples = 1; Timer timer = new Timer(); timer.start(); UI.printInfo(UI.Module.API, "Parsing stream ..."); try { p = new Systems.Parser(stream); while (true) { string token = p.getNextToken(); if (token == null) break; if (token == "image") { UI.printInfo(UI.Module.API, "Reading image settings ..."); parseImageBlock(api); } else if (token == "background") { UI.printInfo(UI.Module.API, "Reading background ..."); parseBackgroundBlock(api); } else if (token == "accel") { UI.printInfo(UI.Module.API, "Reading accelerator type ..."); p.getNextToken(); UI.printWarning(UI.Module.API, "Setting accelerator type is not recommended - ignoring"); } else if (token == "filter") { UI.printInfo(UI.Module.API, "Reading image filter type ..."); parseFilter(api); } else if (token == "bucket") { UI.printInfo(UI.Module.API, "Reading bucket settings ..."); api.parameter("bucket.size", p.getNextInt()); api.parameter("bucket.order", p.getNextToken()); api.options(SunflowAPI.DEFAULT_OPTIONS); } else if (token == "photons") { UI.printInfo(UI.Module.API, "Reading photon settings ..."); parsePhotonBlock(api); } else if (token == "gi") { UI.printInfo(UI.Module.API, "Reading global illumination settings ..."); parseGIBlock(api); } else if (token == "lightserver") { UI.printInfo(UI.Module.API, "Reading light server settings ..."); parseLightserverBlock(api); } else if (token == "trace-depths") { UI.printInfo(UI.Module.API, "Reading trace depths ..."); parseTraceBlock(api); } else if (token == "camera") { parseCamera(api); } else if (token == "shader") { if (!parseShader(api)) return false; } else if (token == "modifier") { if (!parseModifier(api)) return false; } else if (token == "override") { api.parameter("override.shader", p.getNextToken()); api.parameter("override.photons", p.getNextbool()); api.options(SunflowAPI.DEFAULT_OPTIONS); } else if (token == "object") { parseObjectBlock(api); } else if (token == "instance") { parseInstanceBlock(api); } else if (token == "light") { parseLightBlock(api); } else if (token == "texturepath") { string path = p.getNextToken(); //if (!new File(path).isAbsolute()) // path = localDir + File.separator + path; api.searchpath("texture", Path.GetFullPath(path)); } else if (token == "includepath") { string path = p.getNextToken(); //if (!new File(path).isAbsolute()) // path = localDir + File.separator + path; api.searchpath("include", Path.GetFullPath(path)); } else if (token == "include") { string file = p.getNextToken(); UI.printInfo(UI.Module.API, "Including: \"{0}\" ...", file); api.include(file); } else UI.printWarning(UI.Module.API, "Unrecognized token {0}", token); } p.close(); } catch (Exception e) { UI.printError(UI.Module.API, "{0}", e); return false; } timer.end(); UI.printInfo(UI.Module.API, "Done parsing."); UI.printInfo(UI.Module.API, "Parsing time: {0}", timer.ToString()); return true; }
public bool build(Options options) { // read options maxDiffuseDepth = options.getInt("depths.diffuse", maxDiffuseDepth); maxReflectionDepth = options.getInt("depths.reflection", maxReflectionDepth); maxRefractionDepth = options.getInt("depths.refraction", maxRefractionDepth); giEngine = GIEngineFactory.create(options); string caustics = options.getstring("caustics", null); if (caustics == null || caustics == "none") causticPhotonMap = null; else if (caustics != null && caustics == "kd") causticPhotonMap = new CausticPhotonMap(options); else { UI.printWarning(UI.Module.LIGHT, "Unrecognized caustics photon map engine \"{0}\" - ignoring", caustics); causticPhotonMap = null; } // validate options maxDiffuseDepth = Math.Max(0, maxDiffuseDepth); maxReflectionDepth = Math.Max(0, maxReflectionDepth); maxRefractionDepth = Math.Max(0, maxRefractionDepth); SunflowSharp.Systems.Timer t = new SunflowSharp.Systems.Timer(); t.start(); // count total number of light samples int numLightSamples = 0; for (int i = 0; i < lights.Length; i++) numLightSamples += lights[i].getNumSamples(); // initialize gi engine if (giEngine != null) { if (!giEngine.init(scene)) return false; } if (!calculatePhotons(causticPhotonMap, "caustic", 0)) return false; t.end(); cacheLookups = 0; cacheHits = 0; cacheEmptyEntryMisses = 0; cacheWrongEntryMisses = 0; cacheEntryAdditions = 0; if (_shadingCache != null) { // clear shading cache for (int i = 0; i < _shadingCache.Length; i++) _shadingCache[i] = null; } UI.printInfo(UI.Module.LIGHT, "Light Server stats:"); UI.printInfo(UI.Module.LIGHT, " * Light sources found: {0}", lights.Length); UI.printInfo(UI.Module.LIGHT, " * Light samples: {0}", numLightSamples); UI.printInfo(UI.Module.LIGHT, " * Max raytrace depth:"); UI.printInfo(UI.Module.LIGHT, " - Diffuse {0}", maxDiffuseDepth); UI.printInfo(UI.Module.LIGHT, " - Reflection {0}", maxReflectionDepth); UI.printInfo(UI.Module.LIGHT, " - Refraction {0}", maxRefractionDepth); UI.printInfo(UI.Module.LIGHT, " * GI engine {0}", options.getstring("gi.engine", "none")); UI.printInfo(UI.Module.LIGHT, " * Caustics: {0}", caustics == null ? "none" : caustics); UI.printInfo(UI.Module.LIGHT, " * Shader override: {0}", shaderOverride); UI.printInfo(UI.Module.LIGHT, " * Photon override: {0}", shaderOverridePhotons); UI.printInfo(UI.Module.LIGHT, " * Shading cache: {0}", _shadingCache == null ? "off" : "on"); UI.printInfo(UI.Module.LIGHT, " * Build time: {0}", t.ToString()); return true; }
/** * Create an API object from the specified file. Java files are read by * Janino and are expected to implement a build method (they implement a * derived class of SunflowAPI. The build method is called if the code * compiles succesfully. Other files types are handled by the parse method. * * @param filename filename to load * @return a valid SunflowAPI object or <code>null</code> on failure */ public static SunflowAPI create(string filename, int frameNumber) { if (filename == null) return new SunflowAPI(); SunflowAPI api = null; if (filename.EndsWith(".java")) { Timer t = new Timer(); UI.printInfo(UI.Module.API, "Compiling \"" + filename + "\" ..."); t.start(); try { //FileInputStream stream = new FileInputStream(filename); api = null;//(SunflowAPI) ClassBodyEvaluator.createFastClassBodyEvaluator(new Scanner(filename, stream), SunflowAPI.class, ClassLoader.getSystemClassLoader()); //fixme: the dynamic loading //stream.close(); } catch (Exception e) { UI.printError(UI.Module.API, "Could not compile: \"{0}\"", filename); UI.printError(UI.Module.API, "{0}", e); return null; } t.end(); UI.printInfo(UI.Module.API, "Compile time: " + t.ToString()); if (api != null) { string currentFolder = Path.GetDirectoryName(filename);//new File(filename).getAbsoluteFile().getParentFile().getAbsolutePath(); api.includeSearchPath.addSearchPath(currentFolder); api.textureSearchPath.addSearchPath(currentFolder); } UI.printInfo(UI.Module.API, "Build script running ..."); t.start(); api.currentFrame = frameNumber; api.build(); t.end(); UI.printInfo(UI.Module.API, "Build script time: {0}", t.ToString()); } else { api = new SunflowAPI(); api = api.include(filename) ? api : null; } return api; }
public bool calculatePhotons(PhotonStore map, string type, int seed) { if (map == null) { return(true); } if (lights.Length == 0) { UI.printError(UI.Module.LIGHT, "Unable to trace {0} photons, no lights in scene", type); return(false); } float[] histogram = new float[lights.Length]; histogram[0] = lights[0].getPower(); for (int i = 1; i < lights.Length; i++) { histogram[i] = histogram[i - 1] + lights[i].getPower(); } UI.printInfo(UI.Module.LIGHT, "Tracing %s photons ...", type); int numEmittedPhotons = map.numEmit(); if (numEmittedPhotons <= 0 || histogram[histogram.Length - 1] <= 0) { UI.printError(UI.Module.LIGHT, "Photon mapping enabled, but no {0} photons to emit", type); return(false); } map.prepare(scene.getBounds()); UI.taskStart("Tracing " + type + " photons", 0, numEmittedPhotons); Thread[] photonThreads = new Thread[scene.getThreads()]; float scale = 1.0f / numEmittedPhotons; int delta = numEmittedPhotons / photonThreads.Length; photonCounter = 0; SunflowSharp.Systems.Timer photonTimer = new SunflowSharp.Systems.Timer(); photonTimer.start(); for (int i = 0; i < photonThreads.Length; i++) { int threadID = i; int start = threadID * delta; int end = (threadID == (photonThreads.Length - 1)) ? numEmittedPhotons : (threadID + 1) * delta; photonThreads[i] = new Thread(new ThreadStart(new CalculatePhotons(start, end, this, seed, histogram, scale, map, lockObj).Run)); photonThreads[i].Priority = scene.getThreadPriority(); photonThreads[i].Start(); } for (int i = 0; i < photonThreads.Length; i++) { try { photonThreads[i].Join(); } catch (Exception e) { UI.printError(UI.Module.LIGHT, "Photon thread {0} of {1} was interrupted", i + 1, photonThreads.Length); return(false); } } if (UI.taskCanceled()) { UI.taskStop(); // shut down task cleanly return(false); } photonTimer.end(); UI.taskStop(); UI.printInfo(UI.Module.LIGHT, "Tracing time for {0} photons: {1}", type, photonTimer.ToString()); map.init(); return(true); }
public void build(PrimitiveList primitives) { UI.printDetailed(UI.Module.ACCEL, "KDTree settings"); UI.printDetailed(UI.Module.ACCEL, " * Max Leaf Size: {0}", maxPrims); UI.printDetailed(UI.Module.ACCEL, " * Max Depth: {0}", MAX_DEPTH); UI.printDetailed(UI.Module.ACCEL, " * Traversal cost: {0}", TRAVERSAL_COST); UI.printDetailed(UI.Module.ACCEL, " * Intersect cost: {0}", INTERSECT_COST); UI.printDetailed(UI.Module.ACCEL, " * Empty bonus: {0}", EMPTY_BONUS); UI.printDetailed(UI.Module.ACCEL, " * Dump leaves: {0}", dump ? "enabled" : "disabled"); Timer total = new Timer(); total.start(); primitiveList = primitives; // get the object space bounds bounds = primitives.getWorldBounds(null); int nPrim = primitiveList.getNumPrimitives(), nSplits = 0; BuildTask task = new BuildTask(nPrim); Timer prepare = new Timer(); prepare.start(); for (int i = 0; i < nPrim; i++) { for (int axis = 0; axis < 3; axis++) { float ls = primitiveList.getPrimitiveBound(i, 2 * axis + 0); float rs = primitiveList.getPrimitiveBound(i, 2 * axis + 1); if (ls == rs) { // flat in this dimension task.splits[nSplits] = pack(ls, PLANAR, axis, i); nSplits++; } else { task.splits[nSplits + 0] = pack(ls, OPENED, axis, i); task.splits[nSplits + 1] = pack(rs, CLOSED, axis, i); nSplits += 2; } } } task.n = nSplits; prepare.end(); Timer t = new Timer(); List<int> tempTree = new List<int>(); List<int> tempList = new List<int>(); tempTree.Add(0); tempTree.Add(1); t.start(); // sort it Timer sorting = new Timer(); sorting.start(); radix12(task.splits, task.n); sorting.end(); // build the actual tree BuildStats stats = new BuildStats(); buildTree(bounds.getMinimum().x, bounds.getMaximum().x, bounds.getMinimum().y, bounds.getMaximum().y, bounds.getMinimum().z, bounds.getMaximum().z, task, 1, tempTree, 0, tempList, stats); t.end(); // write out arrays // free some memory task = null; tree = tempTree.ToArray(); tempTree = null; this.primitives = tempList.ToArray(); tempList = null; total.end(); // display some extra info stats.printStats(); UI.printDetailed(UI.Module.ACCEL, " * Node memory: {0}", Memory.SizeOf(tree)); UI.printDetailed(UI.Module.ACCEL, " * Object memory: {0}", Memory.SizeOf(this.primitives)); UI.printDetailed(UI.Module.ACCEL, " * Prepare time: {0}", prepare); UI.printDetailed(UI.Module.ACCEL, " * Sorting time: {0}", sorting); UI.printDetailed(UI.Module.ACCEL, " * Tree creation: {0}", t); UI.printDetailed(UI.Module.ACCEL, " * Build time: {0}", total); if (dump) { try { UI.printInfo(UI.Module.ACCEL, "Dumping mtls to {0}.mtl ...", dumpPrefix); StreamWriter mtlFile = new StreamWriter(dumpPrefix + ".mtl"); int maxN = stats.maxObjects; for (int n = 0; n <= maxN; n++) { float blend = (float)n / (float)maxN; Color nc; if (blend < 0.25) nc = Color.blend(Color.BLUE, Color.GREEN, blend / 0.25f); else if (blend < 0.5) nc = Color.blend(Color.GREEN, Color.YELLOW, (blend - 0.25f) / 0.25f); else if (blend < 0.75) nc = Color.blend(Color.YELLOW, Color.RED, (blend - 0.50f) / 0.25f); else nc = Color.MAGENTA; mtlFile.WriteLine(string.Format("newmtl mtl{0}", n)); float[] rgb = nc.getRGB(); mtlFile.WriteLine("Ka 0.1 0.1 0.1"); mtlFile.WriteLine(string.Format("Kd {0}g {1}g {2}g", rgb[0], rgb[1], rgb[2])); mtlFile.WriteLine("illum 1\n"); } StreamWriter objFile = new StreamWriter(dumpPrefix + ".obj"); UI.printInfo(UI.Module.ACCEL, "Dumping tree to {0}.obj ...", dumpPrefix); dumpObj(0, 0, maxN, new BoundingBox(bounds), objFile, mtlFile); objFile.Close(); mtlFile.Close(); } catch (Exception e) { Console.WriteLine(e); } } }
public bool build(Options options) { // read options maxDiffuseDepth = options.getInt("depths.diffuse", maxDiffuseDepth); maxReflectionDepth = options.getInt("depths.reflection", maxReflectionDepth); maxRefractionDepth = options.getInt("depths.refraction", maxRefractionDepth); giEngine = GIEngineFactory.create(options); string caustics = options.getstring("caustics", null); if (caustics == null || caustics == "none") { causticPhotonMap = null; } else if (caustics != null && caustics == "kd") { causticPhotonMap = new CausticPhotonMap(options); } else { UI.printWarning(UI.Module.LIGHT, "Unrecognized caustics photon map engine \"{0}\" - ignoring", caustics); causticPhotonMap = null; } // validate options maxDiffuseDepth = Math.Max(0, maxDiffuseDepth); maxReflectionDepth = Math.Max(0, maxReflectionDepth); maxRefractionDepth = Math.Max(0, maxRefractionDepth); SunflowSharp.Systems.Timer t = new SunflowSharp.Systems.Timer(); t.start(); // count total number of light samples int numLightSamples = 0; for (int i = 0; i < lights.Length; i++) { numLightSamples += lights[i].getNumSamples(); } // initialize gi engine if (giEngine != null) { if (!giEngine.init(scene)) { return(false); } } if (!calculatePhotons(causticPhotonMap, "caustic", 0)) { return(false); } t.end(); cacheLookups = 0; cacheHits = 0; cacheEmptyEntryMisses = 0; cacheWrongEntryMisses = 0; cacheEntryAdditions = 0; if (_shadingCache != null) { // clear shading cache for (int i = 0; i < _shadingCache.Length; i++) { _shadingCache[i] = null; } } UI.printInfo(UI.Module.LIGHT, "Light Server stats:"); UI.printInfo(UI.Module.LIGHT, " * Light sources found: {0}", lights.Length); UI.printInfo(UI.Module.LIGHT, " * Light samples: {0}", numLightSamples); UI.printInfo(UI.Module.LIGHT, " * Max raytrace depth:"); UI.printInfo(UI.Module.LIGHT, " - Diffuse {0}", maxDiffuseDepth); UI.printInfo(UI.Module.LIGHT, " - Reflection {0}", maxReflectionDepth); UI.printInfo(UI.Module.LIGHT, " - Refraction {0}", maxRefractionDepth); UI.printInfo(UI.Module.LIGHT, " * GI engine {0}", options.getstring("gi.engine", "none")); UI.printInfo(UI.Module.LIGHT, " * Caustics: {0}", caustics == null ? "none" : caustics); UI.printInfo(UI.Module.LIGHT, " * Shader override: {0}", shaderOverride); UI.printInfo(UI.Module.LIGHT, " * Photon override: {0}", shaderOverridePhotons); UI.printInfo(UI.Module.LIGHT, " * Shading cache: {0}", _shadingCache == null ? "off" : "on"); UI.printInfo(UI.Module.LIGHT, " * Build time: {0}", t.ToString()); return(true); }