public InstantGI(Options options) { numPhotons = options.getInt("gi.igi.samples", 64); numSets = options.getInt("gi.igi.sets", 1); c = options.getFloat("gi.igi.c", 0.00003f); numBias = options.getInt("gi.igi.bias_samples", 0); virtualLights = null; }
public FakeGIEngine(Options options) { up = options.getVector("gi.fake.up", new Vector3(0, 1, 0)).normalize(); sky = options.getColor("gi.fake.sky", Color.WHITE).copy(); ground = options.getColor("gi.fake.ground", Color.BLACK).copy(); sky.mul((float)Math.PI); ground.mul((float)Math.PI); }
public AmbientOcclusionGIEngine(Options options) { bright = options.getColor("gi.ambocc.bright", Color.WHITE); dark = options.getColor("gi.ambocc.dark", Color.BLACK); samples = options.getInt("gi.ambocc.samples", 32); maxDist = options.getFloat("gi.ambocc.maxdist", 0); maxDist = (maxDist <= 0) ? float.PositiveInfinity : maxDist; }
public bool init(Options options, Scene scene) { bright = options.getColor("gi.ambocc.bright", Color.WHITE); dark = options.getColor("gi.ambocc.dark", Color.BLACK); samples = options.getInt("gi.ambocc.samples", 32); maxDist = options.getFloat("gi.ambocc.maxdist", 0); maxDist = (maxDist <= 0) ? float.PositiveInfinity : maxDist; return true; }
public bool init(Options options, Scene scene) { up = options.getVector("gi.fake.up", new Vector3(0, 1, 0)).normalize(); sky = options.getColor("gi.fake.sky", Color.WHITE).copy(); ground = options.getColor("gi.fake.ground", Color.BLACK).copy(); sky.mul((float) Math.PI); ground.mul((float) Math.PI); return true; }
public CausticPhotonMap(Options options) { _numEmit = options.getInt("caustics.emit", 10000); gatherNum = options.getInt("caustics.gather", 50); gatherRadius = options.getFloat("caustics.radius", 0.5f); filterValue = options.getFloat("caustics.filter", 1.1f); bounds = new BoundingBox(); maxPower = 0; maxRadius = 0; }
public bool prepare(Options options, Scene scene, int w, int h) { this.scene = scene; imageWidth = w; imageHeight = h; numBucketsX = ((uint)imageWidth + 31) >> 5;//>>> numBucketsY = ((uint)imageHeight + 31) >> 5;//>>> numBuckets = numBucketsX * numBucketsY; 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 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 void prepare(Options options, BoundingBox sceneBounds) { }
public PathTracingGIEngine(Options options) { samples = options.getInt("gi.path.samples", 16); }
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 void put(string name, Options options) { renderObjects[name] = new RenderObjectHandle(options); }
public RenderObjectHandle(Options options) { obj = options; type = RenderObjectType.OPTIONS; }
public void prepare(Options options, BoundingBox sceneBounds) { // get settings _numEmit = options.getInt("gi.irr-cache.gmap.emit", 100000); numGather = options.getInt("gi.irr-cache.gmap.gather", 50); gatherRadius = options.getFloat("gi.irr-cache.gmap.radius", 0.5f); // init bounds = new BoundingBox(sceneBounds); bounds.enlargeUlps(); Vector3 w = bounds.getExtents(); nx = (int)Math.Max(((w.x / gatherRadius) + 0.5f), 1); ny = (int)Math.Max(((w.y / gatherRadius) + 0.5f), 1); nz = (int)Math.Max(((w.z / gatherRadius) + 0.5f), 1); int numCells = nx * ny * nz; UI.printInfo(UI.Module.LIGHT, "Initializing grid photon map:"); UI.printInfo(UI.Module.LIGHT, " * Resolution: {0}x{1}x{2}", nx, ny, nz); UI.printInfo(UI.Module.LIGHT, " * Total cells: {0}", numCells); for (hashPrime = 0; hashPrime < PRIMES.Length; hashPrime++) if (PRIMES[hashPrime] > (numCells / 5)) break; cellHash = new PhotonGroup[PRIMES[hashPrime]]; UI.printInfo(UI.Module.LIGHT, " * Initial hash size: {0}", cellHash.Length); }
/** * 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."); }
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 void prepare(Options options, BoundingBox sceneBounds) { // get settings _numEmit = options.getInt("gi.irr-cache.gmap.emit", 100000); numGather = options.getInt("gi.irr-cache.gmap.gather", 50); gatherRadius = options.getFloat("gi.irr-cache.gmap.radius", 0.5f); // init photonList = new List<Photon>(); photonList.Add(null); photons = null; storedPhotons = halfStoredPhotons = 0; }
/** * Render using the specified options and the specified display. If the * specified options do not exist - defaults will be used. * * @param optionsName name of the {@link RenderObject} which contains the * options * @param display display object */ public void render(string optionsName, IDisplay display) { if (string.IsNullOrEmpty(optionsName)) optionsName = "::options"; renderObjects.updateScene(scene); Options opt = lookupOptions(optionsName); if (opt == null) opt = new Options(); scene.setCamera(lookupCamera(opt.getstring("camera", null))); // shader override String shaderOverrideName = opt.getstring("override.shader", "none"); bool overridePhotons = opt.getbool("override.photons", false); if (shaderOverrideName.Equals("none")) scene.setShaderOverride(null, false); else { IShader shader = lookupShader(shaderOverrideName); if (shader == null) UI.printWarning(UI.Module.API, "Unable to find shader \"{0}\" for override, disabling", shaderOverrideName); scene.setShaderOverride(shader, overridePhotons); } // baking string bakingInstanceName = opt.getstring("baking.instance", null); if (bakingInstanceName != null) { Instance bakingInstance = lookupInstance(bakingInstanceName); if (bakingInstance == null) { UI.printError(UI.Module.API, "Unable to bake instance \"{0}\" - not found", bakingInstanceName); return; } scene.setBakingInstance(bakingInstance); } else scene.setBakingInstance(null); ImageSampler sampler = PluginRegistry.imageSamplerPlugins.createObject(opt.getstring("sampler", "bucket")); scene.render(opt, sampler, display); }
public void prepare(Options options, BoundingBox sceneBounds) { // get options _numEmit = options.getInt("caustics.emit", 10000); gatherNum = options.getInt("caustics.gather", 50); gatherRadius = options.getFloat("caustics.radius", 0.5f); filterValue = options.getFloat("caustics.filter", 1.1f); bounds = new BoundingBox(); // init maxPower = 0; maxRadius = 0; photonList = new List<Photon>(); photonList.Add(null); photons = null; storedPhotons = halfStoredPhotons = 0; }
public bool init(Options options, Scene scene) { numPhotons = options.getInt("gi.igi.samples", 64); numSets = options.getInt("gi.igi.sets", 1); c = options.getFloat("gi.igi.c", 0.00003f); numBias = options.getInt("gi.igi.bias_samples", 0); virtualLights = null; if (numSets < 1) numSets = 1; UI.printInfo(UI.Module.LIGHT, "Instant Global Illumination settings:"); UI.printInfo(UI.Module.LIGHT, " * Samples: {0}", numPhotons); UI.printInfo(UI.Module.LIGHT, " * Sets: {0}", numSets); UI.printInfo(UI.Module.LIGHT, " * Bias bound: {0}", c); UI.printInfo(UI.Module.LIGHT, " * Bias rays: {0}", numBias); virtualLights = new PointLight[numSets][]; if (numPhotons > 0) { for (int i = 0, seed = 0; i < virtualLights.Length; i++, seed += numPhotons) { PointLightStore map = new PointLightStore(this); if (!scene.calculatePhotons(map, "virtual", seed, options)) return false; virtualLights[i] = map.virtualLights.ToArray(); UI.printInfo(UI.Module.LIGHT, "Stored {0} virtual point lights for set {0} of {0}", virtualLights[i].Length, i + 1, numSets); } } else { // create an empty array for (int i = 0; i < virtualLights.Length; i++) virtualLights[i] = new PointLight[0]; } return true; }