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 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 static GIEngine create(Options options) { string type = options.getstring("gi.engine", null); if (type == null || type == "null" || type == "none") return null; else if (type == "ambocc") return new AmbientOcclusionGIEngine(options); else if (type == "fake") return new FakeGIEngine(options); else if (type == "igi") return new InstantGI(options); else if (type == "irr-cache") return new IrradianceCacheGIEngine(options); else if (type == "path") return new PathTracingGIEngine(options); else { UI.printWarning(UI.Module.LIGHT, "Unrecognized GI engine type \"{0}\" - ignoring", type); return null; } }
public IrradianceCacheGIEngine(Options options) { samples = options.getInt("gi.irr-cache.samples", 256); tolerance = options.getFloat("gi.irr-cache.tolerance", 0.05f); invTolerance = 1.0f / tolerance; minSpacing = options.getFloat("gi.irr-cache.min_spacing", 0.05f); maxSpacing = options.getFloat("gi.irr-cache.max_spacing", 5.00f); root = null; //rwl = new ReentrantReadWriteLock(); globalPhotonMap = null; string gmap = options.getstring("gi.irr-cache.gmap", null); if (gmap == null || gmap == "none") return; int numEmit = options.getInt("gi.irr-cache.gmap.emit", 100000); int gather = options.getInt("gi.irr-cache.gmap.gather", 50); float radius = options.getFloat("gi.irr-cache.gmap.radius", 0.5f); if (gmap == "kd") globalPhotonMap = new GlobalPhotonMap(numEmit, gather, radius); else if (gmap == "grid") globalPhotonMap = new GridPhotonMap(numEmit, gather, radius); else UI.printWarning(UI.Module.LIGHT, "Unrecognized global photon map type \"%s\" - ignoring", gmap); }
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); }
public bool prepare(Options options, Scene scene, int w, int h) { this.scene = scene; imageWidth = w; imageHeight = h; // fetch options bucketSize = options.getInt("bucket.size", bucketSize); bucketOrderName = options.getstring("bucket.order", bucketOrderName); minAADepth = options.getInt("aa.min", minAADepth); maxAADepth = options.getInt("aa.max", maxAADepth); superSampling = options.getInt("aa.samples", superSampling); displayAA = options.getbool("aa.display", displayAA); jitter = options.getbool("aa.jitter", jitter); contrastThreshold = options.getFloat("aa.contrast", contrastThreshold); // limit bucket size and compute number of buckets in each direction bucketSize = MathUtils.clamp(bucketSize, 16, 512); int numBucketsX = (imageWidth + bucketSize - 1) / bucketSize; int numBucketsY = (imageHeight + bucketSize - 1) / bucketSize; bucketOrder = BucketOrderFactory.create(bucketOrderName); bucketCoords = bucketOrder.getBucketSequence(numBucketsX, numBucketsY); // validate AA options minAADepth = MathUtils.clamp(minAADepth, -4, 5); maxAADepth = MathUtils.clamp(maxAADepth, minAADepth, 5); superSampling = MathUtils.clamp(superSampling, 1, 256); invSuperSampling = 1.0 / superSampling; // compute AA stepping sizes subPixelSize = (maxAADepth > 0) ? (1 << maxAADepth) : 1; minStepSize = maxAADepth >= 0 ? 1 : 1 << (-maxAADepth); if (minAADepth == maxAADepth) maxStepSize = minStepSize; else maxStepSize = minAADepth > 0 ? 1 << minAADepth : subPixelSize << (-minAADepth); useJitter = jitter && maxAADepth > 0; // compute anti-aliasing contrast thresholds contrastThreshold = MathUtils.clamp(contrastThreshold, 0, 1); thresh = contrastThreshold * (float)Math.Pow(2.0f, minAADepth); // read filter settings from scene filterName = options.getstring("filter", filterName); filter = PluginRegistry.filterPlugins.createObject(filterName); // adjust filter if (filter == null) { UI.printWarning(UI.Module.BCKT, "Unrecognized filter type: \"{0}\" - defaulting to box", filterName); filter = new BoxFilter(); filterName = "box"; } fhs = filter.getSize() * 0.5f; fs = (int)Math.Ceiling(subPixelSize * (fhs - 0.5f)); // prepare QMC sampling sigmaOrder = Math.Min(QMC.MAX_SIGMA_ORDER, Math.Max(0, maxAADepth) + 13); // FIXME: how big should the table be? sigmaLength = 1 << sigmaOrder; UI.printInfo(UI.Module.BCKT, "Bucket renderer settings:"); UI.printInfo(UI.Module.BCKT, " * Resolution: {0}x{1}", imageWidth, imageHeight); UI.printInfo(UI.Module.BCKT, " * Bucket size: {0}", bucketSize); UI.printInfo(UI.Module.BCKT, " * Number of buckets: {0}x{1}", numBucketsX, numBucketsY); if (minAADepth != maxAADepth) UI.printInfo(UI.Module.BCKT, " * Anti-aliasing: {0} -> {1} (adaptive)", aaDepthTostring(minAADepth), aaDepthTostring(maxAADepth)); else UI.printInfo(UI.Module.BCKT, " * Anti-aliasing: {0} (fixed)", aaDepthTostring(minAADepth)); UI.printInfo(UI.Module.BCKT, " * Rays per sample: {0}", superSampling); UI.printInfo(UI.Module.BCKT, " * Subpixel jitter: {0}", useJitter ? "on" : (jitter ? "auto-off" : "off")); UI.printInfo(UI.Module.BCKT, " * Contrast threshold: {0}", contrastThreshold); UI.printInfo(UI.Module.BCKT, " * Filter type: {0}", filterName); UI.printInfo(UI.Module.BCKT, " * Filter size: {0} pixels", filter.getSize()); 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; }
/** * Render the scene using the specified options, image sampler and display. * * @param options rendering options object * @param sampler image sampler * @param display display to send the image to, a default display will * be created if <code>null</code> */ public void render(Options options, ImageSampler sampler, IDisplay display) { if (display == null) display = null;// new FrameDisplay(); if (bakingInstance != null) { UI.printDetailed(UI.Module.SCENE, "Creating primitives for lightmapping ..."); bakingPrimitives = bakingInstance.getBakingPrimitives(); if (bakingPrimitives == null) { UI.printError(UI.Module.SCENE, "Lightmap baking is not supported for the given instance."); return; } int n = bakingPrimitives.getNumPrimitives(); UI.printInfo(UI.Module.SCENE, "Building acceleration structure for lightmapping ({0} num primitives) ...", n); bakingAccel = AccelerationStructureFactory.create("auto", n, true); bakingAccel.build(bakingPrimitives); } else { bakingPrimitives = null; bakingAccel = null; } bakingViewDependent = options.getbool("baking.viewdep", bakingViewDependent); if ((bakingInstance != null && bakingViewDependent && camera == null) || (bakingInstance == null && camera == null)) { UI.printError(UI.Module.SCENE, "No camera found"); return; } // read from options threads = options.getInt("threads", 0); lowPriority = options.getbool("threads.lowPriority", true); imageWidth = options.getInt("resolutionX", 640); imageHeight = options.getInt("resolutionY", 480); // limit resolution to 16k imageWidth = MathUtils.clamp(imageWidth, 1, 1 << 14); imageHeight = MathUtils.clamp(imageHeight, 1, 1 << 14); // get acceleration structure info // count scene primitives long numPrimitives = 0; for (int i = 0; i < instanceList.getNumPrimitives(); i++) numPrimitives += instanceList.getNumPrimitives(i); UI.printInfo(UI.Module.SCENE, "Scene stats:"); UI.printInfo(UI.Module.SCENE, " * Infinite instances: {0}", infiniteInstanceList.getNumPrimitives()); UI.printInfo(UI.Module.SCENE, " * Instances: {0}", instanceList.getNumPrimitives()); UI.printInfo(UI.Module.SCENE, " * Primitives: {0}", numPrimitives); string accelName = options.getstring("accel", null); if (accelName != null) { rebuildAccel = rebuildAccel || acceltype != accelName; acceltype = accelName; } UI.printInfo(UI.Module.SCENE, " * Instance accel: {0}", acceltype); if (rebuildAccel) { intAccel = AccelerationStructureFactory.create(acceltype, instanceList.getNumPrimitives(), false); intAccel.build(instanceList); rebuildAccel = false; } UI.printInfo(UI.Module.SCENE, " * Scene bounds: {0}", getBounds()); UI.printInfo(UI.Module.SCENE, " * Scene center: {0}", getBounds().getCenter()); UI.printInfo(UI.Module.SCENE, " * Scene diameter: {0}", getBounds().getExtents().Length()); UI.printInfo(UI.Module.SCENE, " * Lightmap bake: {0}", bakingInstance != null ? (bakingViewDependent ? "view" : "ortho") : "off"); if (sampler == null) return; if (!lightServer.build(options)) return; // render UI.printInfo(UI.Module.SCENE, "Rendering ..."); sampler.prepare(options, this, imageWidth, imageHeight); sampler.render(display); lightServer.showStats(); // discard baking tesselation/accel structure bakingPrimitives = null; bakingAccel = null; UI.printInfo(UI.Module.SCENE, "Done."); }
/** * Render the scene using the specified options, image sampler and display. * * @param options rendering options object * @param sampler image sampler * @param display display to send the image to, a default display will * be created if <code>null</code> */ public void render(Options options, ImageSampler sampler, IDisplay display) { stats.reset(); if (display == null) { display = null;// new FrameDisplay(); } if (bakingInstance != null) { UI.printDetailed(UI.Module.SCENE, "Creating primitives for lightmapping ..."); bakingPrimitives = bakingInstance.getBakingPrimitives(); if (bakingPrimitives == null) { UI.printError(UI.Module.SCENE, "Lightmap baking is not supported for the given instance."); return; } int n = bakingPrimitives.getNumPrimitives(); UI.printInfo(UI.Module.SCENE, "Building acceleration structure for lightmapping ({0} num primitives) ...", n); bakingAccel = AccelerationStructureFactory.create("auto", n, true); bakingAccel.build(bakingPrimitives); } else { bakingPrimitives = null; bakingAccel = null; } bakingViewDependent = options.getbool("baking.viewdep", bakingViewDependent); if ((bakingInstance != null && bakingViewDependent && camera == null) || (bakingInstance == null && camera == null)) { UI.printError(UI.Module.SCENE, "No camera found"); return; } // read from options threads = options.getInt("threads", 0); lowPriority = options.getbool("threads.lowPriority", true); imageWidth = options.getInt("resolutionX", 640); imageHeight = options.getInt("resolutionY", 480); // limit resolution to 16k imageWidth = MathUtils.clamp(imageWidth, 1, 1 << 14); imageHeight = MathUtils.clamp(imageHeight, 1, 1 << 14); // prepare lights createAreaLightInstances(); // get acceleration structure info // count scene primitives long numPrimitives = 0; for (int i = 0; i < instanceList.getNumPrimitives(); i++) { numPrimitives += instanceList.getNumPrimitives(i); } UI.printInfo(UI.Module.SCENE, "Scene stats:"); UI.printInfo(UI.Module.SCENE, " * Infinite instances: {0}", infiniteInstanceList.getNumPrimitives()); UI.printInfo(UI.Module.SCENE, " * Instances: {0}", instanceList.getNumPrimitives()); UI.printInfo(UI.Module.SCENE, " * Primitives: {0}", numPrimitives); string accelName = options.getstring("accel", null); if (accelName != null) { rebuildAccel = rebuildAccel || acceltype != accelName; acceltype = accelName; } UI.printInfo(UI.Module.SCENE, " * Instance accel: {0}", acceltype); if (rebuildAccel) { intAccel = AccelerationStructureFactory.create(acceltype, instanceList.getNumPrimitives(), false); intAccel.build(instanceList); rebuildAccel = false; } UI.printInfo(UI.Module.SCENE, " * Scene bounds: {0}", getBounds()); UI.printInfo(UI.Module.SCENE, " * Scene center: {0}", getBounds().getCenter()); UI.printInfo(UI.Module.SCENE, " * Scene diameter: {0}", getBounds().getExtents().Length()); UI.printInfo(UI.Module.SCENE, " * Lightmap bake: {0}", bakingInstance != null ? (bakingViewDependent ? "view" : "ortho") : "off"); if (sampler == null) { return; } if (!lightServer.build(options)) { return; } // render UI.printInfo(UI.Module.SCENE, "Rendering ..."); stats.setResolution(imageWidth, imageHeight); sampler.prepare(options, this, imageWidth, imageHeight); sampler.render(display); // show statistics stats.displayStats(); lightServer.showStats(); // discard area lights removeAreaLightInstances(); // discard baking tesselation/accel structure bakingPrimitives = null; bakingAccel = null; UI.printInfo(UI.Module.SCENE, "Done."); }