Lightmapping Extended

From Unify Community Wiki
Revision as of 05:49, 5 December 2012 by Mstevenson (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Contents

Description

Lightmapping Extended is an editor tool that unlocks hidden features in Unity's lightmapping system.

Unity employ's Autodesk's Beast middleware for lightmapping, but Beast supports many more options than Unity exposes in its GUI. Lightmapping Extended enables additional features by creating a custom Beast configuration file that includes all documented options.

This code is maintained on GitHub: https://github.com/mstevenson/Lightmapping-Extended

Usage

Add both LMExtendedWindow.cs and ILConfig.cs to your project's Editor folder. The Lightmapping Extended editor window can be accessed from the menu Window > Lightmapping Extended.

Configuration options are scene-specific. If the current scene does not include a lightmap configuration file, the Lightmapping Extended editor window will provide an option to create one.


LMExtendedWindow.cs

using UnityEngine;
using UnityEditor;
using System.Collections;
using System.IO;
 
 
public class LMExtendedWindow : EditorWindow
{
	static LMExtendedWindow window;
 
	private ILConfig config;
 
	[MenuItem ("Window/Lightmapping Extended")]
	static void Init ()
	{
		window = (LMExtendedWindow)EditorWindow.GetWindow (typeof(LMExtendedWindow), false, "LM Extended");
		window.autoRepaintOnSceneChange = true;
	}
 
	public string ConfigFilePath {
		get {
			if (string.IsNullOrEmpty (EditorApplication.currentScene))
				return "";
			string root = Path.GetDirectoryName (EditorApplication.currentScene);
			string dir = Path.GetFileNameWithoutExtension (EditorApplication.currentScene);
			string path = Path.Combine (root, dir);
			path = Path.Combine (path, "BeastSettings.xml");
			return path;
		}
	}
 
 
	private int selected;
 
	[SerializeField]
	Vector2 scroll;
 
	void OnGUI ()
	{
		string path = ConfigFilePath;
		if (string.IsNullOrEmpty (path)) {
			GUILayout.Label ("Open a scene file to edit lightmap settings");
			return;
		}
 
		// Determine if config file exists
		bool haveConfigFile = false;
		if (config == null) {
			if (File.Exists (path)) {
				config = ILConfig.Load (path);
				haveConfigFile = true;
			}
		} else {
			haveConfigFile = true;
		}
 
		// Option to generate a config file
		if (!haveConfigFile) {
			EditorGUILayout.Space ();
			if (GUILayout.Button ("Generate Beast settings file for current scene")) {
				ILConfig newConfig = new ILConfig ();
				var dir = Path.GetDirectoryName (ConfigFilePath);
				if (!Directory.Exists (dir))
					Directory.CreateDirectory (dir);
				newConfig.Save (ConfigFilePath);
				config = ILConfig.Load (path);
				AssetDatabase.Refresh ();
				GUIUtility.ExitGUI ();
			}
			return;
		}
 
		selected = GUILayout.Toolbar (selected, new string[] {"Settings", "Global Illum", "Environment"});
		EditorGUILayout.Space ();
 
		scroll = EditorGUILayout.BeginScrollView (scroll);
 
		switch (selected) {
		case 0:
			PerformanceSettingsGUI ();
			TextureBakeGUI ();
			AASettingsGUI ();
			RenderSettingsGUI ();
			break;
		case 1:
			GlobalIlluminationGUI ();
			break;
		case 2:
			EnvironmentGUI ();
			break;
		}
 
		if (GUI.changed) {
			config.Save (ConfigFilePath);
		}
 
		EditorGUILayout.EndScrollView ();
 
		EditorGUILayout.Space ();
		GUILayout.BeginHorizontal ();
		{
			GUILayout.FlexibleSpace ();
			if (GUILayout.Button ("Clear", GUILayout.Width (120))) {
				Lightmapping.Clear ();
			}
			if (Lightmapping.isRunning) {
				if (GUILayout.Button ("Cancel", GUILayout.Width (120))) {
					Lightmapping.Cancel ();
				}
			} else {
				if (GUILayout.Button ("Bake Scene", GUILayout.Width (120))) {
					if (config.environmentSettings.giEnvironment == ILConfig.EnvironmentSettings.Environment.IBL && string.IsNullOrEmpty (config.environmentSettings.iblImageFile)) {
						EditorUtility.DisplayDialog ("Missing IBL image", "The lightmapping environment type is set to IBL, but no IBL image file is available. Either change the environment type or specify an HDR or EXR image file path.", "Ok");
						Debug.LogError ("Lightmapping cancelled, environment type set to IBL but no IBL image file was specified.");
					} else {
						Lightmapping.BakeAsync ();
					}
				}
			}
		}
		GUILayout.EndHorizontal ();
		EditorGUILayout.Space ();
	}
 
	void OnSelectionChange ()
	{
		if (!File.Exists (ConfigFilePath))
			config = null;
		Repaint ();
	}
 
	void OnFocus ()
	{
		if (!File.Exists (ConfigFilePath))
			config = null;
		Repaint ();
	}
 
	void OnProjectChange ()
	{
		if (!File.Exists (ConfigFilePath))
			config = null;
		Repaint ();
	}
 
 
	public enum ShadowDepth {
		PrimaryRays = 1,
		PrimaryAndSecondaryRays = 2
	}
 
	void PerformanceSettingsGUI ()
	{
		// Threads
		GUILayout.Label ("CPU", EditorStyles.boldLabel);
		EditorGUI.indentLevel++;
		Toggle ("Auto Threads", ref config.frameSettings.autoThreads, "If enabled, Beast will try to auto detect the CPU configuration and use one thread per core.");
		EditorGUI.indentLevel++;
		if (!config.frameSettings.autoThreads)
			GUI.enabled = false;
		IntField ("Subtract Threads", ref config.frameSettings.autoThreadsSubtract, "If autoThreads is enabled, this can be used to decrease the number of utilized cores, e.g. to leave one or two cores free to do other work.");
		GUI.enabled = true;
		if (config.frameSettings.autoThreads)
			GUI.enabled = false;
		IntField ("Render Threads", ref config.frameSettings.renderThreads, "If autoThreads is disabled, this will set the number of threads beast uses. One per core is a good start.");
		GUI.enabled = true;
		EditorGUI.indentLevel--;
		EditorGUI.indentLevel--;
 
//		GUILayout.Label ("Tiles", EditorStyles.boldLabel);
//		EditorGUI.indentLevel++;
//		config.frameSettings.tileScheme = (ILConfig.FrameSettings.TileScheme)EditorGUILayout.EnumPopup (new GUIContent ("Tile Scheme", "Different ways for Beast to distribute tiles over the image plane."), config.frameSettings.tileScheme);
//		IntField ("Tile Size", ref config.frameSettings.tileSize, "A smaller tile gives better ray tracing coherence. There is no 'best setting' for all scenes. Default value is 32, giving 32x32 pixel tiles. The largest allowed tile size is 128.");
//		EditorGUI.indentLevel--;
 
//		GUILayout.Label ("Output Verbosity");
//		EditorGUI.indentLevel++;
//		Toggle ("Debug File", ref config.frameSettings.outputVerbosity.debugFile, "Save all log messages to a file named debug.out.");
//		Toggle ("Debug Print", ref config.frameSettings.outputVerbosity.debugPrint, "Used for development purposes.");
//		Toggle ("Error Print", ref config.frameSettings.outputVerbosity.errorPrint, "");
//		Toggle ("Warning Print", ref config.frameSettings.outputVerbosity.warningPrint, "");
//		Toggle ("Benchmark Print", ref config.frameSettings.outputVerbosity.benchmarkPrint, "");
//		Toggle ("Progress Print", ref config.frameSettings.outputVerbosity.progressPrint, "");
//		Toggle ("Info Print", ref config.frameSettings.outputVerbosity.infoPrint, "");
//		Toggle ("Verbose Print", ref config.frameSettings.outputVerbosity.verbosePrint, "");
//		EditorGUI.indentLevel--;
	}
 
	void AASettingsGUI ()
	{
		GUILayout.Label ("Antialiasing", EditorStyles.boldLabel);
		EditorGUI.indentLevel++;
		config.aaSettings.samplingMode = (ILConfig.AASettings.SamplingMode)EditorGUILayout.EnumPopup (new GUIContent ("Sampling Mode", ""), config.aaSettings.samplingMode);
		EditorGUI.indentLevel++;
		IntField ("Min Sample Rate", ref config.aaSettings.minSampleRate, "Controls the minimum number of samples per pixel. The formula used is 4^maxSampleRate (1, 4, 16, 64, 256 samples per pixel)");
		IntField ("Max Sample Rate", ref config.aaSettings.maxSampleRate, "Controls the maximum number of samples per pixel. Values less than 0 allows using less than one sample per pixel (if AdaptiveSampling is used). The formula used is 4^maxSampleRate (1, 4, 16, 64, 256 samples per pixel)");
		EditorGUI.indentLevel--;
		FloatField ("Contrast", ref config.aaSettings.contrast, "If the contrast differs less than this threshold Beast will consider the sampling good enough. Default value is 0.1.");
		config.aaSettings.filter = (ILConfig.AASettings.Filter)EditorGUILayout.EnumPopup (new GUIContent ("Filter", "The sub-pixel filter to use."), config.aaSettings.filter);
		EditorGUILayout.PrefixLabel (new GUIContent ("Filter Size"));
		EditorGUI.indentLevel++;
		FloatField ("X", ref config.aaSettings.filterSize.x, "");
		FloatField ("Y", ref config.aaSettings.filterSize.y, "");
		EditorGUI.indentLevel--;
		EditorGUI.indentLevel--;
	}
 
	void RenderSettingsGUI ()
	{
		GUILayout.Label ("Rays", EditorStyles.boldLabel);
		EditorGUI.indentLevel++;
		IntField ("Max Bounces", ref config.renderSettings.maxRayDepth, "The maximum amount of 'bounces' a ray can have before being considered done. A bounce can be a reflection or refraction.");
		FloatField ("Bias", ref config.renderSettings.bias, "An error threshold to avoid double intersections. For example, a shadow ray should not intersect the same triangle as the primary ray did, but because of limited numerical precision this can happen. The bias value moves the intersection point to eliminate this problem. If set to zero this value is computed automatically depending on the scene size.");
		EditorGUI.indentLevel--;
 
		GUILayout.Label ("Reflections & Transparency", EditorStyles.boldLabel);
		EditorGUI.indentLevel++;
		IntField ("Max Reflection Bounces", ref config.renderSettings.reflectionDepth, "The maximum amount of reflections a ray can have before being considered done.");
		FloatField ("Reflection Threshold", ref config.renderSettings.reflectionThreshold, "If the intensity of the reflected contribution is less than the threshold, the ray will be terminated.");
		IntField ("GI Transparency Depth", ref config.renderSettings.giTransparencyDepth, "Controls the maximum transparency depth for Global Illumination rays. Used to speed up renderings with a lot of transparency (for example trees).");
		EditorGUI.indentLevel--;
 
		GUILayout.Label ("Shadows", EditorStyles.boldLabel);
		EditorGUI.indentLevel++;
		config.renderSettings.shadowDepth = (int)((ShadowDepth)EditorGUILayout.EnumPopup (new GUIContent ("Shadow Depth", "Controls which rays that spawn shadow rays."), (ShadowDepth)System.Enum.Parse (typeof(ShadowDepth), config.renderSettings.shadowDepth.ToString ())));
		IntField ("Min Shadow Rays", ref config.renderSettings.minShadowRays, "The minimum number of shadow rays that will be sent to determine if a point is lit by a specific light source. Use this value to ensure that you get enough quality in soft shadows at the price of render times. This will raise the minimum number of rays sent for any light sources that have a minShadowSamples setting lower than this value, but will not lower the number if minShadowSamples is set to a higher value. Setting this to a value higher than maxShadowRays will not send more rays than maxShadowRays.");
		IntField ("Max Shadow Rays", ref config.renderSettings.maxShadowRays, "The maximum number of shadow rays per point that will be used to generate a soft shadow for any light source. Use this to shorten render times at the price of soft shadow quality. This will lower the maximum number of rays sent for any light sources that have a shadow samples setting higher than this value, but will not raise the number if shadow samples is set to a lower value.");
		EditorGUI.indentLevel--;
 
		GUILayout.Label ("Geometry", EditorStyles.boldLabel);
		EditorGUI.indentLevel++;
		FloatField ("Vertex Merge Threshold", ref config.renderSettings.vertexMergeThreshold, "Triangle vertices that are closer together than this threshold will be merged into one (if possible depending on other vertex data).");
		Toggle ("Odd UV Flipping", ref config.renderSettings.tsOddUVFlipping, "Using this setting will force Beast to mirror tangent and binormal when UV has odd winding direction.");
		Toggle ("Vertex Orthogonalization", ref config.renderSettings.tsVertexOrthogonalization, "Orthogonalize tangent space basis vectors (tangent, binormal and normal) at every vertex.");
		Toggle ("Vertex Normalization", ref config.renderSettings.tsVertexNormalization, "Normalize tangent space basis vectors (tangent, binormal and normal) at every vertex.");
		Toggle ("Intersection Orthogonalization", ref config.renderSettings.tsIntersectionOrthogonalization, "Orthogonalize tangent space basis vectors (tangent, binormal and normal) at every intersection point.");
		Toggle ("Intersection Normalization", ref config.renderSettings.tsIntersectionNormalization, "Normalize tangent space basis vectors (tangent, binormal and normal) at every intersection point.");
		EditorGUI.indentLevel--;
	}
 
	void GlobalIlluminationGUI ()
	{
		Toggle ("Enable GI", ref config.giSettings.enableGI, "");
		if (!config.giSettings.enableGI)
			GUI.enabled = false;
 
		// Caustics are not available in Unity 4
		//Toggle ("Enable Caustics", ref config.giSettings.enableCaustics, "");
 
		EditorGUILayout.Space ();
 
		GUILayout.Label ("Primary Integrator", EditorStyles.boldLabel);
		IntegratorPopup (true);
		IntegratorSettings (config.giSettings.primaryIntegrator, true);
 
		EditorGUILayout.Space ();
 
		GUILayout.Label ("Secondary Integrator", EditorStyles.boldLabel);
		IntegratorPopup (false);
		IntegratorSettings (config.giSettings.secondaryIntegrator, false);
 
		if (config.giSettings.primaryIntegrator == ILConfig.GISettings.Integrator.FinalGather && config.giSettings.secondaryIntegrator == ILConfig.GISettings.Integrator.PathTracer) {
			EditorGUILayout.Space ();
			Toggle ("Light Leak Reduction", ref config.giSettings.fgLightLeakReduction, "This setting can be used to reduce light leakage through walls when using final gather as primary GI and path tracing as secondary GI. Leakage, which can happen when e.g. the path tracer filters in values on the other side of a wall, is reduced by using final gather as a secondary GI fallback when sampling close to walls or corners. When this is enabled a final gather depth of 3 will be used automatically, but the higher depths will only be used close to walls or corners. Note that this is only used when path tracing is set as secondary GI.");
			if (!config.giSettings.fgLightLeakReduction)
				GUI.enabled = false;
			FloatField ("Light Leak Radius", ref config.giSettings.fgLightLeakRadius, "Controls how far away from walls the final gather will be called again, instead of the secondary GI. If 0.0 is used a value will be calculated by Beast depending on the secondary GI used. The calculated value is printed in the output window. If you still get leakage you can adjust this by manually typing in a higher value.");
			if (config.giSettings.enableGI)
				GUI.enabled = true;
		}
 
		GUI.enabled = true;
	}
 
	void IntegratorPopup (bool isPrimary)
	{
		if (isPrimary) {
			config.giSettings.primaryIntegrator = (ILConfig.GISettings.Integrator)EditorGUILayout.EnumPopup (config.giSettings.primaryIntegrator);
		}
		else {
			config.giSettings.secondaryIntegrator = (ILConfig.GISettings.Integrator)EditorGUILayout.EnumPopup (config.giSettings.secondaryIntegrator);
		}
	}
 
	void IntegratorSettings (ILConfig.GISettings.Integrator integrator, bool isPrimary)
	{
		EditorGUI.indentLevel++;
 
		if (integrator != ILConfig.GISettings.Integrator.None) {
			if (isPrimary) {
				FloatField ("Intensity", ref config.giSettings.primaryIntensity, "Tweak the amount of illumination from the primary and secondary GI integrators. This lets you boost or reduce the amount of indirect light easily.");
				FloatField ("Saturation", ref config.giSettings.primarySaturation, "Lets you tweak the amount of color in the primary and secondary GI integrators. This lets you boost or reduce the perceived saturation of the bounced light.");
			} else {
				FloatField ("Intensity", ref config.giSettings.secondaryIntensity, "Tweak the amount of illumination from the primary and secondary GI integrators. This lets you boost or reduce the amount of indirect light easily.");
				FloatField ("Saturation", ref config.giSettings.secondarySaturation, "Lets you tweak the amount of color in the primary and secondary GI integrators. This lets you boost or reduce the perceived saturation of the bounced light.");
			}
		}
 
		switch (integrator) {
		case ILConfig.GISettings.Integrator.None:
			if (isPrimary && config.giSettings.primaryIntegrator != ILConfig.GISettings.Integrator.None)
				config.giSettings.primaryIntegrator = ILConfig.GISettings.Integrator.None;
			else if (!isPrimary && config.giSettings.secondaryIntegrator != ILConfig.GISettings.Integrator.None)
				config.giSettings.secondaryIntegrator = ILConfig.GISettings.Integrator.None;
			break;
		case ILConfig.GISettings.Integrator.FinalGather:
			FinalGatherSettings (isPrimary);
			break;
		case ILConfig.GISettings.Integrator.PathTracer:
			PathTracerSettings (isPrimary);
			break;
		case ILConfig.GISettings.Integrator.MonteCarlo:
			MonteCarloSettings (isPrimary);
			break;
		}
		EditorGUI.indentLevel--;
	}
 
 
	void FinalGatherSettings (bool isPrimaryIntegrator)
	{
		if (isPrimaryIntegrator && config.giSettings.primaryIntegrator != ILConfig.GISettings.Integrator.FinalGather)
			config.giSettings.primaryIntegrator = ILConfig.GISettings.Integrator.FinalGather;
		else if (!isPrimaryIntegrator && config.giSettings.secondaryIntegrator != ILConfig.GISettings.Integrator.FinalGather)
			config.giSettings.secondaryIntegrator = ILConfig.GISettings.Integrator.FinalGather;
 
		// Bounces
 
		GUILayout.Label ("Bounces", EditorStyles.boldLabel);
		EditorGUI.indentLevel++;
		IntSlider ("Bounces", ref config.giSettings.fgDepth, 1, 10, "Sets the number of indirect light bounces calculated by final gather. A value higher than 1 will produce more global illumination effects, but note that it can be quite slow since the number of rays will increase exponentially with the depth. It's often better to use a fast method for secondary GI. If a secondary GI is used the number of set final gather bounces will be calculated first, before the secondary GI is called. So in most cases the depth should be set to 1 if a secondary GI is used.");
		FloatField ("Bounce Boost", ref config.giSettings.diffuseBoost, "This setting can be used to exaggerate light bouncing in dark scenes. Setting it to a value larger than 1 will push the diffuse color of materials towards 1 for GI computations. The typical use case is scenes authored with dark materials, this happens easily when doing only direct lighting since it's easy to compensate dark materials with strong light sources. Indirect light will be very subtle in these scenes since the bounced light will fade out quickly. Setting a diffuse boost will compensate for this. Note that values between 0 and 1 will decrease the diffuse setting in a similar way making light bounce less than the materials says, values below 0 is invalid. The actual computation taking place is a per component pow(colorComponent, (1.0 / diffuseBoost)).");
		EditorGUI.indentLevel--;
 
		// Rays
 
		GUILayout.Label ("Rays", EditorStyles.boldLabel);
		EditorGUI.indentLevel++;
		IntField ("Rays", ref config.giSettings.fgRays, "Sets the maximum number of rays to use for each Final Gather sample point. A higher number gives higher quality, but longer rendering time.");
		FloatField ("Max Ray Length", ref config.giSettings.fgMaxRayLength, "The max distance a ray can be traced before it's considered to be a 'miss'. This can improve performance in very large scenes. If the value is set to 0.0 the entire scene will be used.");
		MinMaxField ("Attenuation Range", ref config.giSettings.fgAttenuationStart, ref config.giSettings.fgAttenuationStop, "The distance between which attenuation begins and fades to zero. There is no attenuation before this range, and no intensity beyond it. If zero, there will be no attenuation.");
		EditorGUI.indentLevel++;
		if (config.giSettings.fgAttenuationStop == 0)
			GUI.enabled = false;
		FloatField ("Falloff Exponent", ref config.giSettings.fgFalloffExponent, "This can be used to adjust the rate by which lighting falls off by distance. A higher exponent gives a faster falloff. Note that fgAttenuationStop must be set higher than 0.0 to enable attenuation.");
		if (config.giSettings.enableGI)
			GUI.enabled = true;
		EditorGUI.indentLevel--;
		EditorGUI.indentLevel--;
 
		// Points
 
		GUILayout.Label ("Points", EditorStyles.boldLabel);
		EditorGUI.indentLevel++;
		IntSlider ("Interpolation Points", ref config.giSettings.fgInterpolationPoints, 1, 40, "Sets the number of final gather points to interpolate between. A higher value will give a smoother result, but can also smooth out details. If light leakage is introduced through walls when this value is increased, checking the sample visibility solves that problem, see fgCheckVisibility below.");
		IntSlider ("Estimate Points", ref config.giSettings.fgEstimatePoints, 1, 40, "Sets the minimum number of points that should be used when estimating final gather in the pre calculation pass. The impact is that a higher value will create more points all over the scene. The default value 15 rarely needs to be adjusted.");
		Toggle ("Check Visibility", ref config.giSettings.fgCheckVisibility, "Turn this on to reduce light leakage through walls. When points are collected to interpolate between, some of them can be located on the other side of geometry. As a result light will bleed through the geometry. So to prevent this Beast can reject points that are not visible.");
		FloatField ("Contrast Threshold", ref config.giSettings.fgContrastThreshold, "Controls how sensitive the final gather should be for contrast differences between the points during pre calculation. If the contrast difference is above this threshold for neighbouring points, more points will be created in that area. This tells the algorithm to place points where they are really needed, e.g. at shadow boundaries or in areas where the indirect light changes quickly. Hence this threshold controls the number of points created in the scene adaptively. Note that if a low number of final gather rays are used, the points will have high variance and hence a high contrast difference, so in that case you might need to increase the contrast threshold to prevent points from clumping together.");
		FloatField ("Gradient Threshold", ref config.giSettings.fgGradientThreshold, "Controls how the irradiance gradient is used in the interpolation. Each point stores it's irradiance gradient which can be used to improve the interpolation. However in some situations using the gradient can result in white 'halos' and other artifacts. This threshold can be used to reduce those artifacts.");
		FloatField ("Normal Threshold", ref config.giSettings.fgNormalThreshold, "Controls how sensitive the final gather should be for differences in the points normals. A lower value will give more points in areas of high curvature.");
		Toggle ("Clamp Radiance", ref config.giSettings.fgClampRadiance, "Turn this on to clamp the sampled values to [0, 1]. This will reduce high frequency noise when Final Gather is used together with other Global Illumination algorithms.");
		EditorGUI.indentLevel--;
 
		// Ambient Occlusion
 
		GUILayout.Label ("Ambient Occlusion", EditorStyles.boldLabel);
		EditorGUI.indentLevel++;
		// Not used by Unity
//		Toggle ("Visualize AO", ref config.giSettings.fgAOVisualize, "Visualize just the ambient occlusion values. Useful when tweaking the occlusion sampling options.");
		Slider ("Influence", ref config.giSettings.fgAOInfluence, 0, 1, "Controls a scaling of Final Gather with Ambient Occlusion which can be used to boost shadowing and get more contrast in you lighting. The value controls how much Ambient Occlusion to blend into the Final Gather solution.");
		LightmapEditorSettings.aoAmount = config.giSettings.fgAOInfluence;
		if (config.giSettings.fgAOInfluence <= 0)
			GUI.enabled = false;
		Slider ("Contrast", ref config.giSettings.fgAOContrast, 0, 2, "Can be used to adjust the contrast for ambient occlusion.");
		LightmapEditorSettings.aoContrast = config.giSettings.fgAOContrast;
		FloatField ("Max Distance", ref config.giSettings.fgAOMaxDistance, "Max distance for the occlusion. Beyond this distance a ray is considered to be visible. Can be used to avoid full occlusion for closed scenes.");
		LightmapEditorSettings.aoMaxDistance = config.giSettings.fgAOMaxDistance;
		FloatField ("Scale", ref config.giSettings.fgAOScale, "A scaling of the occlusion values. Can be used to increase or decrease the shadowing effect.");
		if (config.giSettings.enableGI)
			GUI.enabled = true;
 
		// Performance
 
		GUILayout.Label ("Performance", EditorStyles.boldLabel);
		Toggle ("Fast Preview", ref config.giSettings.fgPreview, "Turn this on to visualize the final gather prepass. Using the Preview Calculation Pass enables a quick preview of the final image lighting, reducing lighting setup time.");
		config.giSettings.fgUseCache = (ILConfig.GISettings.Cache)EditorGUILayout.EnumPopup (new GUIContent ("Use Cache", "Selects what caching method to use for final gathering."), config.giSettings.fgUseCache);
		Toggle ("Cache Direct Light", ref config.giSettings.fgCacheDirectLight, "When this is enabled final gather will also cache lighting from light sources. This increases performance since fewer direct light calculations are needed. It gives an approximate result, and hence can affect the quality of the lighting. For instance indirect light bounces from specular highlights might be lost. However this caching is only done for depths higher than 1, so the quality of direct light and shadows in the light map will not be reduced.");
	}
 
	void PathTracerSettings (bool isPrimaryIntegrator)
	{
		if (isPrimaryIntegrator && config.giSettings.primaryIntegrator != ILConfig.GISettings.Integrator.PathTracer)
			config.giSettings.primaryIntegrator = ILConfig.GISettings.Integrator.PathTracer;
		else if (!isPrimaryIntegrator && config.giSettings.secondaryIntegrator != ILConfig.GISettings.Integrator.PathTracer)
			config.giSettings.secondaryIntegrator = ILConfig.GISettings.Integrator.PathTracer;
 
		IntSlider ("Bounces", ref config.giSettings.ptDepth, 0, 20, "");
		FloatField ("Accuracy", ref config.giSettings.ptAccuracy, "Sets the number of paths that are traced for each sample element (pixel, texel or vertex). For preview renderings, you can use a low value like 0.5 or 0.1, which means that half of the pixels or 1/10 of the pixels will generate a path. For production renderings you can use values above 1.0, if needed to get good quality.");
		// Not certain what this does
//		LMColorPicker ("Default Color", ref config.giSettings.ptDefaultColor, "");
 
		// Points
 
		GUILayout.Label ("Points", EditorStyles.boldLabel);
		FloatField ("Point Size", ref config.giSettings.ptPointSize, "Sets the maximum distance between the points in the path tracer cache. If set to 0 a value will be calculated automatically based on the size of the scene. The automatic value will be printed out during rendering, which is a good starting value if the point spacing needs to be adjusted.");
		FloatField ("Normal Threshold", ref config.giSettings.ptNormalThreshold, "Sets the amount of normal deviation that is allowed during cache point filtering.");
		config.giSettings.ptFilterType = (ILConfig.GISettings.PTFilterType)EditorGUILayout.EnumPopup (new GUIContent ("Filter Type", "Selects the filter to use when querying the cache during rendering. None will return the closest cache point (unfiltered)."), config.giSettings.ptFilterType);
		FloatField ("Filter Size", ref config.giSettings.ptFilterSize, "Sets the size of the filter as a multiplier of the Cache Point Spacing value. For example; a value of 3.0 will use a filter that is three times larges then the cache point spacing. If this value is below 1.0 there is no guarantee that any cache point is found. If no cache point is found the Default Color will be returned instead for that query.");
		Toggle ("Check Visibility", ref config.giSettings.ptCheckVisibility, "Turn this on to reduce light leakage through walls. When points are collected to interpolate between, some of them can be located on the other side of geometry. As a result light will bleed through the geometry. So to prevent this Beast can reject points that are not visible.");
 
		// Performance
 
		GUILayout.Label ("Performance", EditorStyles.boldLabel);
		Toggle ("Fast Preview", ref config.giSettings.ptPreview, "If enabled the pre-render pass will be visible in the render view.");
		Toggle ("Cache Direct Light", ref config.giSettings.ptCacheDirectLight, "When this is enabled the path tracer will also cache lighting from light sources. This increases performance since fewer direct light calculations are needed. It gives an approximate result, and hence can affect the quality of the lighting. For instance indirect light bounces from specular highlights might be lost.");
		Toggle ("Precalc Irradiance", ref config.giSettings.ptPrecalcIrradiance, "If enabled the cache points will be pre-filtered before the final pass starts. This increases the performance using the final render pass.");
	}
 
	void MonteCarloSettings (bool isPrimaryIntegrator)
	{
		if (isPrimaryIntegrator && config.giSettings.primaryIntegrator != ILConfig.GISettings.Integrator.MonteCarlo)
			config.giSettings.primaryIntegrator = ILConfig.GISettings.Integrator.MonteCarlo;
		else if (!isPrimaryIntegrator && config.giSettings.secondaryIntegrator != ILConfig.GISettings.Integrator.MonteCarlo)
			config.giSettings.secondaryIntegrator = ILConfig.GISettings.Integrator.MonteCarlo;
 
		IntSlider ("Bounces", ref config.giSettings.mcDepth, 1, 20, "Sets the number of indirect light bounces calculated by monte carlo.");
		IntField ("Rays", ref config.giSettings.mcRays, "Sets the number of rays to use for each calculation. A higher number gives higher quality, but longer rendering time.");
		FloatField ("Ray Length", ref config.giSettings.mcMaxRayLength, "The max distance a ray can be traced before it's considered to be a 'miss'. This can improve performance in very large scenes. If the value is set to 0.0 the entire scene will be used.");
	}
 
	void EnvironmentGUI ()
	{
		config.environmentSettings.giEnvironment = (ILConfig.EnvironmentSettings.Environment)EditorGUILayout.EnumPopup ("Environment Type", config.environmentSettings.giEnvironment);
		if (config.environmentSettings.giEnvironment == ILConfig.EnvironmentSettings.Environment.None) {
			GUI.enabled = false;
		} else {
			GUI.enabled = true;
		}
 
		EditorGUI.indentLevel++;
 
		FloatField ("Intensity", ref config.environmentSettings.giEnvironmentIntensity, "");
 
		if (config.environmentSettings.giEnvironment == ILConfig.EnvironmentSettings.Environment.SkyLight) {
			LMColorPicker ("Sky Light Color", ref config.environmentSettings.skyLightColor, "It is often a good idea to keep the color below 1.0 in intensity to avoid boosting by gamma correction. Boost the intensity instead with the giEnvironmentIntensity setting.");
		} else if (config.environmentSettings.giEnvironment == ILConfig.EnvironmentSettings.Environment.IBL) {
			GUILayout.Label ("IBL Image", EditorStyles.boldLabel);
			EditorGUILayout.PrefixLabel (new GUIContent ("Image Path", "The absolute image file path to use for IBL. Accepts hdr or OpenEXR format. The file should be long-lat. Use giEnvironmentIntensity to boost the intensity of the image."));
			GUILayout.BeginHorizontal ();
			{
				GUILayout.Space (22);
				config.environmentSettings.iblImageFile = EditorGUILayout.TextField (config.environmentSettings.iblImageFile);
				if (GUILayout.Button ("Choose", GUILayout.Width (54))) {
					string file = EditorUtility.OpenFilePanel ("Select EXR or HDR file", "", "");
					string ext = Path.GetExtension (file);
					if (!string.IsNullOrEmpty (file)) {
						if (ext == ".exr" || ext == ".hdr") {
							config.environmentSettings.iblImageFile = file;
							GUI.changed = true;
							Repaint ();
						} else {
							Debug.LogError ("IBL image files must use the extension .exr or .hdr");
						}
					}
				}
			}
			GUILayout.EndHorizontal ();
			Toggle ("Swap Y/Z", ref config.environmentSettings.iblSwapYZ, "Swap the Up Axis. Default value is false, meaning that Y is up.");
			Slider ("Dome Rotation", ref config.environmentSettings.iblTurnDome, 0, 360, "The sphere that the image is projected on can be rotated around the up axis. The amount of rotation is given in degrees. Default value is 0.0.");
			FloatField ("Blur", ref config.environmentSettings.iblGIEnvBlur, "Pre-blur the environment image for Global Illumination calculations. Can help to reduce noise and flicker in images rendered with Final Gather. May increase render time as it is blurred at render time. It is always cheaper to pre-blur the image itself in an external application before loading it into Beast.");
 
			GUILayout.Label ("IBL Light", EditorStyles.boldLabel);
 
			Toggle ("Emit Light", ref config.environmentSettings.iblEmitLight, "Turns on the expensive IBL implementation. This will generate a number of (iblSamples) directional lights from the image.");
			if (config.environmentSettings.iblEmitLight)
				EditorGUILayout.HelpBox ("The scene will be lit by a number of directional lights with colors sampled from the IBL image. Very expensive.", MessageType.None);
			else
				EditorGUILayout.HelpBox ("The scene will be lit with Global Illumination using the IBL image as a simple environment.", MessageType.None);
 
			if (!config.environmentSettings.iblEmitLight)
				GUI.enabled = false;
			{
				IntField ("Samples", ref config.environmentSettings.iblSamples, "The number of samples to be taken from the image. This will affect how soft the shadows will be, as well as the general lighting. The higher number of samples, the better the shadows and lighting.");
				FloatField ("IBL Intensity", ref config.environmentSettings.iblIntensity, "Sets the intensity of the lighting.");
				Toggle ("Diffuse", ref config.environmentSettings.iblEmitDiffuse, "To remove diffuse lighting from IBL, set this to false. To get the diffuse lighting Final Gather could be used instead.");
				Toggle ("Specular", ref config.environmentSettings.iblEmitSpecular, "To remove specular highlights from IBL, set this to false.");
				EditorGUI.indentLevel++;
				{
					if (!config.environmentSettings.iblEmitSpecular)
						GUI.enabled = false;
					FloatField ("Specular Boost", ref config.environmentSettings.iblSpecularBoost, "Further tweak the intensity by boosting the specular component.");
					if (config.environmentSettings.iblEmitLight)
						GUI.enabled = true;
				}
				EditorGUI.indentLevel--;
				Toggle ("Shadows", ref config.environmentSettings.iblShadows, "Controls whether shadows should be created from IBL when this is used.");
				{
					EditorGUI.indentLevel++;
					if (!config.environmentSettings.iblShadows)
						GUI.enabled = false;
					FloatField ("Shadow Noise", ref config.environmentSettings.iblBandingVsNoise, "Controls the appearance of the shadows, banded shadows look more aliased, but noisy shadows flicker more in animations.");
					if (config.environmentSettings.iblEmitLight)
						GUI.enabled = true;
				}
				EditorGUI.indentLevel--;
			}
			GUI.enabled = true;
 
			EditorGUILayout.Space ();
		}
		EditorGUI.indentLevel--;
 
		GUI.enabled = true;
	}
 
 
	void TextureBakeGUI ()
	{
		GUILayout.Label ("Texture", EditorStyles.boldLabel);
		EditorGUI.indentLevel++;
 
		// FIXME The following have no effect in Unity 4.0:
 
		//LMColorPicker ("Background Color", ref config.textureBakeSettings.bgColor, "");
		//IntField ("Edge Dilation", ref config.textureBakeSettings.edgeDilation, "Expands the lightmap with the number of pixels specified to avoid black borders.");
		//Toggle ("Premultiply", ref config.frameSettings.premultiply, "If this box is checked the alpha channel value is pre multiplied into the color channel of the pixel. Note that disabling premultiply alpha gives poor result if used with environment maps and other non constant camera backgrounds. Disabling premultiply alpha can be convenient when composing images in post.");
		//EditorGUI.indentLevel++;
		//if (!config.frameSettings.premultiply) {
		//	GUI.enabled = false;
		//}
		//FloatField ("Premultiply Threshold", ref config.frameSettings.premultiplyThreshold, "This is the alpha threshold for pixels to be considered opaque enough to be 'un multiplied' when using premultiply alpha.");
		//EditorGUI.indentLevel--;
		//GUI.enabled = true;
 
		Toggle ("Bilinear Filter", ref config.textureBakeSettings.bilinearFilter, "Counteract unwanted light seams for tightly packed UV patches.");
		Toggle ("Conservative Rasterization", ref config.textureBakeSettings.conservativeRasterization, "Find pixels which are only partially covered by the UV map.");
 
		EditorGUI.indentLevel--;
	}
 
 
 
	private void LMColorPicker (string name, ref ILConfig.LMColor color, string tooltip)
	{
		Color c = EditorGUILayout.ColorField (new GUIContent (name, tooltip), new Color (color.r, color.g, color.b, color.a));
		color = new ILConfig.LMColor (c.r, c.g, c.b, c.a);
	}
 
	private void Slider (string name, ref float val, float min, float max, string tooltip)
	{
		val = EditorGUILayout.Slider (new GUIContent (name, tooltip), val, min, max);
	}
 
	private void Toggle (string name, ref bool val, string tooltip)
	{
		val = EditorGUILayout.Toggle (new GUIContent (name, tooltip), val);
	}
 
	private void FloatField (string name, ref float val, string tooltip)
	{
		val = EditorGUILayout.FloatField (new GUIContent (name, tooltip), val);
	}
 
	private void IntField (string name, ref int val, string tooltip)
	{
		val = EditorGUILayout.IntField (new GUIContent (name, tooltip), val);
	}
 
	private void IntSlider (string name, ref int val, int min, int max, string tooltip)
	{
		val = EditorGUILayout.IntSlider (new GUIContent (name, tooltip), val, min, max);
	}
 
	private void MinMaxField (string name, ref float min, ref float max, string tooltip) {
		GUILayout.BeginHorizontal ();
		GUILayout.Space (15 * EditorGUI.indentLevel);
		GUILayout.Label (new GUIContent (name, tooltip));
		min = EditorGUILayout.FloatField (min);
		if (min < 0)
			min = 0;
		if (min > max)
			max = min;
		max = EditorGUILayout.FloatField (max);
		if (max < 0)
			max = 0;
		if (max < min)
			min = max;
		GUILayout.EndHorizontal ();
	}
}

ILConfig.cs

using UnityEngine;
using System.Collections;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
 
 
[System.Serializable]
public class ILConfig
{
	#region Data types
 
	[System.Serializable]
	public class LMVec2
	{
		public float x;
		public float y;
 
		public LMVec2 ()
		{
			x = 0;
			y = 0;
		}
 
		public LMVec2 (float x, float y)
		{
			this.x = x;
			this.y = y;
		}
	}
 
	[System.Serializable]
	public class LMColor
	{
		public float r;
		public float g;
		public float b;
		public float a;
 
		public LMColor ()
		{
			this.r = 1;
			this.g = 1;
			this.b = 1;
			this.a = 1;
		}
 
		public LMColor (float r, float g, float b, float a)
		{
			this.r = r;
			this.g = g;
			this.b = b;
			this.a = a;
		}
	}
 
	#endregion
 
	[XmlElement(ElementName = "AASettings")]
	public AASettings aaSettings = new AASettings ();
	[XmlElement(ElementName = "RenderSettings")]
	public RenderSettings renderSettings = new RenderSettings ();
	[XmlElement(ElementName = "EnvironmentSettings")]
	public EnvironmentSettings environmentSettings = new EnvironmentSettings ();
	[XmlElement(ElementName = "FrameSettings")]
	public FrameSettings frameSettings = new FrameSettings ();
	[XmlElement(ElementName = "GISettings")]
	public GISettings giSettings = new GISettings ();
	[XmlElement(ElementName = "SurfaceTransferSettings")]
	public SurfaceTransferSettings surfaceTransferSettings = new SurfaceTransferSettings ();
	[XmlElement(ElementName = "TextureBakeSettings")]
	public TextureBakeSettings textureBakeSettings = new TextureBakeSettings ();
 
 
	public static ILConfig Load (string path)
	{
		FileInfo info = new FileInfo (path);
		if (!info.Exists) {
			return null;
		}
 
		XmlSerializer serializer = new XmlSerializer (typeof(ILConfig));
		FileStream stream = new FileStream (path, FileMode.Open);
 
		ILConfig config = (ILConfig)serializer.Deserialize (stream);
		stream.Close ();
 
		return config;
	}
 
	public void Save (string path)
	{	
		using (XmlTextWriter writer = new XmlTextWriter (path, System.Text.Encoding.GetEncoding ("ISO-8859-1"))) {
			XmlSerializerNamespaces ns = new XmlSerializerNamespaces ();
			ns.Add (string.Empty, string.Empty);
			writer.Formatting = Formatting.Indented;
			XmlSerializer serializer = new XmlSerializer (typeof(ILConfig));
			serializer.Serialize (writer, this, ns);
		}
	}
 
 
 
	[System.Serializable]
	public class FrameSettings
	{
		/// <summary>
		/// Different ways for Beast to distribute tiles over the image plane.
		/// </summary>
//		public enum TileScheme
//		{
//			/// <summary>
//			/// Render from left to right.
//			/// </summary>
//			LeftToRight,
//			/// <summary>
//			/// A way for Beast to achieve maximum coherence, e.g., the fastest rendering time possible.
//			/// </summary>
//			Hilbert,
//			/// <summary>
//			/// A good way to get an early feel for the whole picture without rendering everything.
//			/// </summary>
//			Random,
//			/// <summary>
//			/// Starts in the middle and renders outward in a spiral.
//			/// </summary>
//			Concentric
//		}
 
		public enum ColorCorrection
		{
			None,
			Gamma,
			SRGB
		}
 
		[System.Serializable]
		public class OutputVerbosity
		{
			public bool errorPrint = true;
			public bool warningPrint = true;
			public bool benchmarkPrint = false;
			public bool progressPrint = true;
			public bool infoPrint = false;
			public bool verbosePrint = false;
			/// <summary>
			/// Used for development purposes.
			/// </summary>
			public bool debugPrint = false;
			/// <summary>
			/// Save all log messages to a file named debug.out.
			/// </summary>
			public bool debugFile = false;
		}
 
		[System.Serializable]
		public class OutputCorrection
		{
			/// <summary>
			/// Set the mode of output color correction to None, Gamma or SRGB.
			/// The Beast API assumes this is set to Gamma.
			/// </summary>
			public ColorCorrection colorCorrection = ColorCorrection.None;
			/// <summary>
			/// A float value specifying what gamma the output data should have.
			/// The Beast API assumes this is set to 2.2.
			/// </summary>
			public float gamma = 1;
		}
 
		/// <summary>
		/// If enabled, Beast will try to auto detect the CPU configuration and use one thread per core.
		/// </summary>
		public bool autoThreads = true;
		/// <summary>
		/// If autoThreads is enabled, this can be used to decrease the number of utilized cores,
		/// e.g. to leave one or two cores free to do other work.
		/// </summary>
		public int autoThreadsSubtract = 0;
		/// <summary>
		/// If autoThreads is disabled, this will set the number of threads beast uses. One per core is a good start.
		/// </summary>
		public int renderThreads = 2;
		/// <summary>
		/// If the output is LDR, and dither is true, the resulting image will be dithered. Default is true.
		/// </summary>
		public bool dither = true;
		/// <summary>
		/// A float value specifying what gamma the input data has. Always set this to 1.0 / 2.2 = 0.454545,
		/// which is the gamma the Beast API assumes is used.
		/// </summary>
		public float inputGamma = 1.0f;
		public OutputCorrection outputCorrection = new OutputCorrection ();
		/// <summary>
		/// Different ways for Beast to distribute tiles over the image plane.
		/// </summary>
//		public TileScheme tileScheme = TileScheme.Hilbert;
		/// <summary>
		/// A smaller tile gives better ray tracing coherence. There is no “best setting” for all scenes.
		/// Default value is 32, giving 32x32 pixel tiles. The largest allowed tile size is 128.
		/// </summary>
//		public int tileSize = 32;
		/// <summary>
		/// If this box is checked the alpha channel value is pre multiplied into the color channel of the pixel.
		/// Note that disabling premultiply alpha gives poor result if used with environment maps and other
		/// non constant camera backgrounds. Disabling premultiply alpha can be convenient when composing
		/// images in post.
		/// </summary>
		public bool premultiply = true;
		/// <summary>
		/// This is the alpha threshold for pixels to be considered opaque enough to be “un multiplied”
		/// when using premultiply alpha.
		/// </summary>
		public float premultiplyThreshold = 0.0f;
		/// <summary>
		/// Different levels of textual output that Beast can produce.
		/// </summary>
		public OutputVerbosity outputVerbosity = new OutputVerbosity ();
	}
 
 
 
	[System.Serializable]
	public class RenderSettings
	{
		/// <summary>
		/// An error threshold to avoid double intersections.
		/// For example, a shadow ray should not intersect the same triangle as the primary ray did,
		/// but because of limited numerical precision this can happen. The bias value moves the
		/// intersection point to eliminate this problem. If set to zero this value is computed
		/// automatically depending on the scene size.
		/// </summary>
		public float bias = 0.005f;
		/// <summary>
		/// Controls the maximum transparency depth for Global Illumination rays.
		/// Used to speed up renderings with a lot of transparency (for example trees).
		/// </summary>
		public int giTransparencyDepth = 2;
		/// <summary>
		/// If true, light-links will be ignored and all available light sources will be used.
		/// </summary>
		public bool ignoreLightLinks = false;
		/// <summary>
		/// The maximum amount of "bounces" a ray can have before being considered done.
		/// A bounce can be a reflection or refraction.
		/// </summary>
		public int maxRayDepth = 6;
		/// <summary>
		/// The maximum number of shadow rays per point that will be used to generate a soft shadow
		/// for any light source. Use this to shorten render times at the price of soft shadow quality.
		/// This will lower the maximum number of rays sent for any light sources that have a shadow
		/// samples setting higher than this value, but will not raise the number if shadow samples
		/// is set to a lower value.
		/// </summary>
		public int maxShadowRays = 10000;
		/// <summary>
		/// The minimum number of shadow rays that will be sent to determine if a point is lit by a
		/// specific light source. Use this value to ensure that you get enough quality in soft shadows
		/// at the price of render times. This will raise the minimum number of rays sent for any light
		/// sources that have a minShadowSamples setting lower than this value, but will not lower the
		/// number if minShadowSamples is set to a higher value. Setting this to a value higher than
		/// maxShadowRays will not send more rays than maxShadowRays.
		/// </summary>
		public int minShadowRays = 0;
		/// <summary>
		/// The maximum amount of reflections a ray can have before being considered done.
		/// </summary>
		public int reflectionDepth = 2;
		/// <summary>
		/// If the intensity of the reflected contribution is less than the threshold, the ray will be terminated.
		/// </summary>
		public float reflectionThreshold = 0.001f;
		/// <summary>
		/// Controls which rays that spawn shadow rays. If set to 1, only primary rays spawn shadow rays.
		/// If set to 2, the first secondary ray spawns a shadow ray as well.
		/// </summary>
		public int shadowDepth = 2;
		/// <summary>
		/// Make objects cast shadows from all light sources, not only the light-linked light sources.
		/// </summary>
		public bool shadowsIgnoreLightLinks = false;
		public int transparencyDepth = 50;
		/// <summary>
		/// Normalize tangent space basis vectors (tangent, binormal and normal) at every intersection point.
		/// </summary>
		public bool tsIntersectionNormalization = true;
		/// <summary>
		/// Orthogonalize tangent space basis vectors (tangent, binormal and normal) at every intersection point.
		/// </summary>
		public bool tsIntersectionOrthogonalization = true;
		/// <summary>
		/// Using this setting will force Beast to mirror tangent and binormal when UV has odd winding direction.
		/// </summary>
		public bool tsOddUVFlipping = true;
		/// <summary>
		/// Normalize tangent space basis vectors (tangent, binormal and normal) at every vertex.
		/// </summary>
		public bool tsVertexNormalization = true;
		/// <summary>
		/// Orthogonalize tangent space basis vectors (tangent, binormal and normal) at every vertex.
		/// </summary>
		public bool tsVertexOrthogonalization = true;
		/// <summary>
		/// Triangle vertices that are closer together than this threshold will be merged into one
		/// (if possible depending on other vertex data).
		/// </summary>
		public float vertexMergeThreshold = 0.001f;
	}
 
 
 
	[System.Serializable]
	public class AASettings
	{
		public enum SamplingMode {
			/// <summary>
			/// Anti-aliasing scheme for under/over sampling (from 1/256 up to 256 samples per pixel)
			/// </summary>
			Adaptive,
			/// <summary>
			/// Anti-aliasing scheme for super sampling (from 1 up to 128 samples per pixel)
			/// </summary>
			SuperSampling
		}
 
		public enum Filter {
			/// <summary>
			/// Each sample is treated as equally important. The fastest filter to execute but it gives blurry results.
			/// </summary>
			Box,
			CatmullRom,
			Cubic,
			/// <summary>
			/// Removes noise, preserves details.
			/// </summary>
			Gauss,
			Lanczos,
			Mitchell,
			/// <summary>
			/// Distant samples are considered less important.
			/// </summary>
			Triangle,
		}
 
		/// <summary>
		/// Controls the minimum number of samples per pixel. Values less than 0 allows using less than one
		/// sample per pixel (if AdaptiveSampling is used). Default value is 0.
		/// </summary>
		public int minSampleRate = 0;
		/// <summary>
		/// Controls the maximum number of samples per pixel. Default value is 0.
		/// </summary>
		public int maxSampleRate = 2;
		/// <summary>
		/// If the contrast differs less than this threshold Beast will consider the sampling good enough.
		/// Default value is 0.1.
		/// </summary>
		public float contrast = 0.1f;
		/// <summary>
		/// Enable this to diagnose the sampling. The brighter a pixel is, the more samples were taken at that position.
		/// </summary>
		public bool diagnose = false;
		/// <summary>
		/// To work efficiently on LDR images, the sampling algorithm can clamp the intensity of the image
		/// samples to the [minValue..maxValue] range. When rendering in HDR this is not desired.
		/// Clamp should then be disabled.
		/// </summary>
		public bool clamp = false;
		public SamplingMode samplingMode = SamplingMode.Adaptive;
		/// <summary>
		/// The sub-pixel filter to use. The following filters are available (default value is Box):
		/// </summary>
		public Filter filter = Filter.Gauss;
		/// <summary>
		/// The width and height of the filter kernel in pixels, given by setting the sub elements x and y (float).
		/// Default value is 1.0 for both x and y.
		/// </summary>
		public LMVec2 filterSize = new LMVec2 (2.2f, 2.2f);
	}
 
 
	[System.Serializable]
	/// <summary>
	/// Environment settings control what happens if a ray misses all geometry in the scene. 
	/// </summary>
	/// <remarks>
	/// Defining an environment is usually a very good way to get very pleasing outdoor illumination results,
	/// but might also increase bake times.
	/// 
	/// Note that environments should only be used for effects that can be considered to be infinitely far away,
	/// meaning that only the directional component matters.
	/// </remarks>
	public class EnvironmentSettings
	{
		public enum Environment {
			None,
			/// <summary>
			/// A constant color.
			/// </summary>
			SkyLight,
			/// <summary>
			/// An HDR image.
			/// </summary>
			IBL
		}
 
		/// <summary>
		/// The type of Environment: None, Skylight or IBL.
		/// </summary>
		public Environment giEnvironment = Environment.None;
		/// <summary>
		/// A constant environment color. In Unity: "Sky Light Color"
		/// </summary>
		/// <remarks>
		/// Used if type is Skylight. It is often a good idea to keep the color below 1.0 in intensity
		/// to avoid boosting by gamma correction. Boost the intensity instead with the giEnvironmentIntensity setting.
		/// </remarks>
		public LMColor skyLightColor = new LMColor (0.86f, 0.93f, 1, 1);
		/// <summary>
		/// A scale factor for Global Illumination intensity. In Unity: "Sky Light Intensity"
		/// </summary>
		/// <remarks>
		/// Used for avoiding gamma correction errors and to scale HDR textures to something that fits your scene.
		/// </remarks>
		public float giEnvironmentIntensity = 0.2f;
		/// <summary>
		/// The image file to use for IBL, using an absolute path.
		/// </summary>
		/// <remarks>
		/// Accepts hdr or OpenEXR format. The file should be long-lat. Use giEnvironmentIntensity to boost
		/// the intensity of the image.
		/// </remarks>
		public string iblImageFile = "";
		/// <summary>
		/// Controls the appearance of the shadows, banded shadows look more aliased, but noisy shadows
		/// flicker more in animations.
		/// </summary>
		public float iblBandingVsNoise = 1;
		/// <summary>
		/// To remove diffuse lighting from IBL, set this to false. To get the diffuse lighting
		/// Final Gather could be used instead.
		/// </summary>
		public bool iblEmitDiffuse = true;
		/// <summary>
		/// Turns on the expensive IBL implementation. This will generate a number of (iblSamples)
		/// directional lights from the image.
		/// </summary>
		public bool iblEmitLight = false;
		/// <summary>
		/// To remove specular highlights from IBL, set this to false.
		/// </summary>
		public bool iblEmitSpecular = false;
		/// <summary>
		/// Pre-blur the environment image for Global Illumination calculations. Can help to reduce noise and flicker
		/// in images rendered with Final Gather. May increase render time as it is blurred at render time. It is
		/// always cheaper to pre-blur the image itself in an external application before loading it into Beast.
		/// </summary>
		public float iblGIEnvBlur = 0.05f;
		/// <summary>
		/// Sets the intensity of the lighting.
		/// </summary>
		public float iblIntensity = 1;
		/// <summary>
		/// The number of samples to be taken from the image. This will affect how soft the shadows will be,
		/// as well as the general lighting. The higher number of samples, the better the shadows and lighting.
		/// </summary>
		public int iblSamples = 300;
		/// <summary>
		/// Controls whether shadows should be created from IBL when this is used.
		/// </summary>
		public bool iblShadows = true;
		/// <summary>
		/// Further tweak the intensity by boosting the specular component.
		/// </summary>
		public float iblSpecularBoost = 1;
		/// <summary>
		/// Swap the Up Axis. Default value is false, meaning that Y is up.
		/// </summary>
		public bool iblSwapYZ = false;
		/// <summary>
		/// The sphere that the image is projected on can be rotated around the up axis.
		/// The amount of rotation is given in degrees. Default value is 0.0.
		/// </summary>
		public float iblTurnDome = 0;
	}
 
 
	[System.Serializable]
	public class GISettings
	{
		public enum ClampMaterials {
			/// <summary>
			/// No clamping at all
			/// </summary>
			None,
			/// <summary>
			/// clamps each color component (R, G, B) individually.
			/// </summary>
			Component,
			/// <summary>
			/// clamps the intensity of the color to 1. This can be useful to make sure the color of
			/// a surface is preserved when clamping. If using component clamp on a color like (3, 1, 1) will
			/// give the color (1, 1, 1) which means that all color bleeding is lost.
			/// </summary>
			Intensity,
		}
 
		public enum Integrator {
			None = 0,
			FinalGather = 1,
			/// <summary>
			/// Used if many indirect bounces are needed and Final Gather-only solution with acceptable
			/// quality would take to much time to render.
			/// </summary>
			PathTracer = 2,
			MonteCarlo = 3
		}
 
 
		// Global Illumination
 
		/// <summary>
		/// This setting controls if the materials should be clamped in any way for GI purposes.
		/// Typically you can use this to avoid problems with non physical materials making your scene
		/// extremely bright. This affects both the specular and diffuse components of materials.
		/// </summary>
		public ClampMaterials clampMaterials = ClampMaterials.None;
		/// <summary>
		/// This setting can be used to exaggerate light bouncing in dark scenes. Setting it to a value larger
		/// than 1 will push the diffuse color of materials towards 1 for GI computations. The typical use case
		/// is scenes authored with dark materials, this happens easily when doing only direct lighting since it’s
		/// easy to compensate dark materials with strong light sources. Indirect light will be very subtle in
		/// these scenes since the bounced light will fade out quickly. Setting a diffuse boost will compensate
		/// for this. Note that values between 0 and 1 will decrease the diffuse setting in a similar way making
		/// light bounce less than the materials says, values below 0 is invalid. The actual computation taking
		/// place is a per component pow(colorComponent, (1.0 / diffuseBoost)).
		/// </summary>
		public float diffuseBoost = 1;
		/// <summary>
		/// This setting globally scales all materials emissive components by the specified value when
		/// they are used by the GI.
		/// </summary>
		public float emissiveScale = 1;
		public bool enableCaustics = false;
		public bool enableGI = true;
		public bool ignoreNonDiffuse = true;
		/// <summary>
		/// Sets the sample rate used during the GI precalculation pass. The prepass is progressive,
		/// rendering from a low resolution up to a high resolution in multiple passes. The prepassMinSampleRate
		/// sets the initial resolution, where a negative value means a lower resolution than the original
		/// image (in powers of two), e.g. -4 gives the original resolution divided by 16. The
		/// prepassMaxSampleRate sets the resolution of the final prepass, e.g 0 giving the same resolution
		/// as the original resolution. The default values are -4/0.
		/// </summary>
		public int prepassMaxSampleRate = 0;
		/// <summary>
		/// Sets the sample rate used during the GI precalculation pass. The prepass is progressive,
		/// rendering from a low resolution up to a high resolution in multiple passes. The prepassMinSampleRate
		/// sets the initial resolution, where a negative value means a lower resolution than the original
		/// image (in powers of two), e.g. -4 gives the original resolution divided by 16. The
		/// prepassMaxSampleRate sets the resolution of the final prepass, e.g 0 giving the same resolution
		/// as the original resolution. The default values are -4/0.
		/// </summary>
		public int prepassMinSampleRate = -4;
		/// <summary>
		/// The Global Illumination system allows you to use two separate algorithms to calculate indirect lighting.
		/// You can for instance calculate multiple levels of light bounces with a fast algorithm like the
		/// Path Tracer, and still calculate the final bounce with Final Gather to get a fast high-quality
		/// global illumination render. Both subsystems have individual control of Intensity and Saturation
		/// to boost the effects if necessary.
		/// </summary>
		public Integrator primaryIntegrator = Integrator.FinalGather;
		/// <summary>
		/// Tweak the amount of illumination from the primary and secondary GI integrators. This lets you boost
		/// or reduce the amount of indirect light easily.
		/// </summary>
		public float primaryIntensity = 1;
		/// <summary>
		/// Lets you tweak the amount of color in the primary and secondary GI integrators. This lets you boost
		/// or reduce the perceived saturation of the bounced light.
		/// </summary>
		public float primarySaturation = 1;
		/// <summary>
		/// The Global Illumination system allows you to use two separate algorithms to calculate indirect lighting.
		/// You can for instance calculate multiple levels of light bounces with a fast algorithm like the
		/// Path Tracer, and still calculate the final bounce with Final Gather to get a fast high-quality
		/// global illumination render. Both subsystems have individual control of Intensity and Saturation
		/// to boost the effects if necessary.
		/// </summary>
		public Integrator secondaryIntegrator = Integrator.None;
		/// <summary>
		/// Lets you tweak the amount of color in the primary and secondary GI integrators. This lets you boost
		/// or reduce the perceived saturation of the bounced light.
		/// </summary>
		public float secondaryIntensity = 1;
		/// <summary>
		/// Lets you tweak the amount of color in the primary and secondary GI integrators. This lets you boost
		/// or reduce the perceived saturation of the bounced light.
		/// </summary>
		public float secondarySaturation = 1;
		/// <summary>
		/// This setting can be used to exaggerate or decrease specular light effects. All materials specular
		/// color is multiplied by this factor when they are used by the GI.
		/// </summary>
		public float specularScale = 1;
 
 
		// Final Gather
 
		public enum Cache {
			/// <summary>
			/// (Brute Force) disables caching and performs a final gathering for every shading point
			/// (same as Monte Carlo).
			/// </summary>
			Off,
			/// <summary>
			/// caches the irradiance at selected points in the scene and uses interpolation in between the points.
			/// This is the default method.
			/// </summary>
			Irradiance,
			/// <summary>
			/// caches radiance SH functions at selected points in the scene and uses interpolation in
			/// between the points. The radiance cache is very useful in some advanced baking passes
			/// (e.g. Radiosity Normal Maps), where directional indirect lighting is needed.
			/// </summary>
			RadianceSH
		}
 
		/// <summary>
		/// Can be used to adjust the contrast for ambient occlusion.
		/// </summary>
		public float fgAOContrast = 1;
		/// <summary>
		/// Controls a scaling of Final Gather with Ambient Occlusion which can be used to boost shadowing and get
		/// more contrast in you lighting. The value controls how much Ambient Occlusion to blend into the
		/// Final Gather solution.
		/// </summary>
		public float fgAOInfluence = 0;
		/// <summary>
		/// Max distance for the occlusion. Beyond this distance a ray is considered to be visible.
		/// Can be used to avoid full occlusion for closed scenes.
		/// </summary>
		public float fgAOMaxDistance = 0.3f;
		/// <summary>
		/// A scaling of the occlusion values. Can be used to increase or decrease the shadowing effect.
		/// </summary>
		public float fgAOScale = 2;
		/// <summary>
		/// Visualize just the ambient occlusion values. Useful when tweaking the occlusion sampling options.
		/// </summary>
		public bool fgAOVisualize = false;
		/// <summary>
		/// The distance where attenuation is started. There is no attenuation before this distance.
		/// Note that fgAttenuationStop must be set higher than 0.0 to enable attenuation.
		/// </summary>
		public float fgAttenuationStart = 0;
		/// <summary>
		/// Sets the distance where attenuation is stopped (fades to zero). There is zero intensity beyond this
		/// distance. To enable attenuation set this value higher than 0.0. The default value is 0.0.
		/// </summary>
		public float fgAttenuationStop = 0;
		/// <summary>
		/// When this is enabled final gather will also cache lighting from light sources. This increases performance
		/// since fewer direct light calculations are needed. It gives an approximate result, and hence can affect
		/// the quality of the lighting. For instance indirect light bounces from specular highlights might be lost.
		/// However this caching is only done for depths higher than 1, so the quality of direct light and shadows
		/// in the light map will not be reduced.
		/// </summary>
		public bool fgCacheDirectLight = false;
		/// <summary>
		/// Turn this on to reduce light leakage through walls. When points are collected to interpolate between,
		/// some of them can be located on the other side of geometry.
		/// As a result light will bleed through the geometry. So to prevent this Beast can reject points
		/// that are not visible.
		/// </summary>
		public bool fgCheckVisibility = true;
		public float fgCheckVisibilityDepth = 1;
		/// <summary>
		/// Turn this on to clamp the sampled values to [0, 1]. This will reduce high frequency noise when
		/// Final Gather is used together with other Global Illumination algorithms.
		/// </summary>
		public bool fgClampRadiance = false;
		/// <summary>
		/// Controls how sensitive the final gather should be for contrast differences between the points
		/// during pre calculation. If the contrast difference is above this threshold for neighbouring points,
		/// more points will be created in that area. This tells the algorithm to place points where they are really
		/// needed, e.g. at shadow boundaries or in areas where the indirect light changes quickly. Hence this
		/// threshold controls the number of points created in the scene adaptively. Note that if a low number of
		/// final gather rays are used, the points will have high variance and hence a high contrast difference,
		/// so in that case you might need to increase the contrast threshold to prevent points from clumping together.
		/// </summary>
		public float fgContrastThreshold = 0.05f;
		/// <summary>
		/// Sets the number of indirect light bounces calculated by final gather. A value higher than 1 will produce
		/// more global illumination effects, but note that it can be quite slow since the number of rays will increase
		/// exponentially with the depth. It’s often better to use a fast method for secondary GI. If a secondary GI is
		/// used the number of set final gather bounces will be calculated first, before the secondary GI is called.
		/// So in most cases the depth should be set to 1 if a secondary GI is used.
		/// </summary>
		public int fgDepth = 1;
		/// <summary>
		/// Sets the minimum number of points that should be used when estimating final gather in the pre calculation
		/// pass. The impact is that a higher value will create more points all over the scene. The default value 15
		/// rarely needs to be adjusted.
		/// </summary>
		public int fgEstimatePoints = 15;
		public bool fgExploitFrameCoherence = false;
		/// <summary>
		/// This can be used to adjust the rate by which lighting falls off by distance. A higher exponent gives a
		/// faster falloff. Note that fgAttenuationStop must be set higher than 0.0 to enable attenuation.
		/// </summary>
		public float fgFalloffExponent = 0;
		/// <summary>
		/// Controls how the irradiance gradient is used in the interpolation. Each point stores it’s irradiance
		/// gradient which can be used to improve the interpolation. However in some situations using the gradient
		/// can result in white ”halos” and other artifacts. This threshold can be used to reduce those artifacts.
		/// </summary>
		public float fgGradientThreshold = 0.5f;
		/// <summary>
		/// Sets the number of final gather points to interpolate between. A higher value will give a smoother result,
		/// but can also smooth out details. If light leakage is introduced through walls when this value is increased,
		/// checking the sample visibility solves that problem, see fgCheckVisibility below.
		/// </summary>
		public int fgInterpolationPoints = 15;
		/// <summary>
		/// Controls how far away from walls the final gather will be called again, instead of the secondary GI.
		/// If 0.0 is used a value will be calculated by Beast depending on the secondary GI used. The calculated
		/// value is printed in the output window. If you still get leakage you can adjust this by manually typing
		/// in a higher value.
		/// </summary>
		public float fgLightLeakRadius = 0;
		/// <summary>
		/// This setting can be used to reduce light leakage through walls when using final gather as primary GI and
		/// path tracing as secondary GI. Leakage, which can happen when e.g. the path tracer filters in values on the
		/// other side of a wall, is reduced by using final gather as a secondary GI fallback when sampling close to
		/// walls or corners. When this is enabled a final gather depth of 3 will be used automatically, but the higher
		/// depths will only be used close to walls or corners. Note that this is only used when path tracing is set
		/// as secondary GI.
		/// </summary>
		public bool fgLightLeakReduction = false;
		/// <summary>
		/// The max distance a ray can be traced before it’s considered to be a “miss”.
		/// This can improve performance in very large scenes. If the value is set to 0.0 the entire scene will be used.
		/// </summary>
		public float fgMaxRayLength = 0;
		/// <summary>
		/// Controls how sensitive the final gather should be for differences in the points normals.
		/// A lower value will give more points in areas of high curvature.
		/// </summary>
		public float fgNormalThreshold = 0.2f;
		/// <summary>
		/// Turn this on to visualize the final gather prepass. Using the Preview Calculation Pass enables a quick
		/// preview of the final image lighting, reducing lighting setup time.
		/// </summary>
		public bool fgPreview = false;
		/// <summary>
		/// Sets the maximum number of rays to use for each Final Gather sample point.
		/// A higher number gives higher quality, but longer rendering time.
		/// </summary>
		public int fgRays = 1000;
		/// <summary>
		/// Selects what caching method to use for final gathering.
		/// </summary>
		public Cache fgUseCache = Cache.Irradiance;
 
 
		// PathTracer
 
		/// <summary>
		/// Selects the filter to use when querying the cache during rendering. None will return the closest
		/// cache point (unfiltered). The filter type can be set to None, Box, Gauss or Triangle.
		/// </summary>
		public enum PTFilterType {
			None,
			Box,
			Gauss,
			Triangle
		}
 
		/// <summary>
		/// Sets the number of paths that are traced for each sample element (pixel, texel or vertex).
		/// For preview renderings, you can use a low value like 0.5 or 0.1, which means 
		/// that half of the pixels or 1/10 of the pixels will generate a path. For production renderings
		/// you can use values above 1.0, if needed to get good quality.
		/// </summary>
		public float ptAccuracy = 1;
		/// <summary>
		/// When this is enabled the path tracer will also cache lighting from light sources. This increases
		/// performance since fewer direct light calculations are needed. It gives an approximate result, and
		/// hence can affect the quality of the lighting. For instance indirect light bounces from specular
		/// highlights might be lost.
		/// </summary>
		public bool ptCacheDirectLight = false;
		/// <summary>
		/// Turn this on to reduce light leakage through walls. When points are collected to interpolate between,
		/// some of them can be located on the other side of geometry. As a result light will bleed through the
		/// geometry. So to prevent this Beast can reject points that are not visible.
		/// </summary>
		public bool ptCheckVisibility = true;
		public float ptConservativeEnergyLimit = 0.95f;
		public LMColor ptDefaultColor = new LMColor (0, 0, 0, 1);
		public int ptDepth = 5;
		public bool ptDiffuseIllum = true;
		public string ptFile = "";
		/// <summary>
		/// Sets the size of the filter as a multiplier of the Cache Point Spacing value. For example;
		/// a value of 3.0 will use a filter that is three times larges then the cache point spacing.
		/// If this value is below 1.0 there is no guarantee that any cache point is found. If no cache
		/// point is found the Default Color will be returned instead for that query.
		/// </summary>
		public float ptFilterSize = 3;
		/// <summary>
		/// Selects the filter to use when querying the cache during rendering. None will return the closest
		/// cache point (unfiltered). The filter type can be set to None, Box, Gauss or Triangle.
		/// </summary>
		public PTFilterType ptFilterType = PTFilterType.Gauss;
		/// <summary>
		/// Sets the amount of normal deviation that is allowed during cache point filtering. ptFilterType
		/// Selects the filter to use when querying the cache during rendering. None will return the closest
		/// cache point (unfiltered). The filter type can be set to None, Box, Gauss or Triangle.
		/// </summary>
		public float ptNormalThreshold = 0.7f;
		/// <summary>
		/// Sets the maximum distance between the points in the path tracer cache. If set to 0 a value will be
		/// calculated automatically based on the size of the scene. The automatic value will be printed out
		/// during rendering, which is a good starting value if the point spacing needs to be adjusted.
		/// </summary>
		public float ptPointSize = 0;
		/// <summary>
		/// If enabled the cache points will be pre-filtered before the final pass starts. This increases the
		/// performance using the final render pass.
		/// </summary>
		public bool ptPrecalcIrradiance = true;
		/// <summary>
		/// If enabled the pre-render pass will be visible in the render view.
		/// </summary>
		public bool ptPreview = false;
		public bool ptSpecularIllum = true;
		public bool ptTransmissiveIllum = true;
 
 
		// Monte Carlo
 
		/// <summary>
		/// Sets the number of indirect light bounces calculated by monte carlo.
		/// </summary>
		public int mcDepth = 2;
		/// <summary>
		/// The max distance a ray can be traced before it’s considered to be a “miss”. This can improve
		/// performance in very large scenes. If the value is set to 0.0 the entire scene will be used.
		/// </summary>
    	public float mcMaxRayLength = 0;
		/// <summary>
		/// Sets the number of rays to use for each calculation. A higher number gives higher quality,
		/// but longer rendering time.
		/// </summary>
    	public int mcRays = 16;
	}
 
 
	[System.Serializable]
	public class ADSSettings
	{
		public enum Instancing {
			/// <summary>
			/// Never use instancing while rendering.
			/// </summary>
			Never,
			/// <summary>
			/// Use instancing whenever a shape is used more than once (default).
			/// </summary>
			AutoDetect
		}
 
		public int gridDensity = 1;
		/// <summary>
		/// Decides how deep the Acceleration Data Structure can subdivide.
		/// </summary>
	    public int gridMaxDepth = 4;
		/// <summary>
		/// Decides how many triangles that can reside in a leaf before it is split up. The Recursion Depth
		/// has precedence over the threshold. A leaf at max depth will never be split. The Recursion Depth
		/// and Recursion Threshold are advanced settings that shouldn't be altered unless Acceleration Data
		/// Structures are second nature to you.
		/// </summary>
	    public int gridThreshold = 25;
		/// <summary>
		/// Specifies the minimum number of triangles that an instance is allowed to have in order
		/// for geometry instancing to be used.
		/// </summary>
	    public int instancingThreshold = 500;
		/// <summary>
		/// This tag lets the user control if instances should be used or not during rendering.
		/// Instancing allows the user to place a single shape in several different places, each with an
		/// individual transform. This preserves disk space and will lower memory consumption when rendering,
		/// but might increase render times quite a bit if there are many large instances.
		/// </summary>
	    public Instancing useInstancing = Instancing.AutoDetect;
		/// <summary>
		/// Beast uses specialized vector instructions to speed up the rendering. The cost is higher memory usage.
		/// Turn off SSE if Beast starts swapping.
		/// </summary>
	    public bool useSSE = true;
	}
 
 
	[System.Serializable]
	public class SurfaceTransferSettings
	{
		public enum SelectionMode {
			Normal
		}
 
		public float frontRange = 0;
		public float frontBias = 0;
		public float backRange = 2;
		public float backBias = -1;
		public SelectionMode selectionMode = SelectionMode.Normal;
	}
 
 
	[System.Serializable]
	public class TextureBakeSettings
	{
		public LMColor bgColor = new LMColor (1, 1, 1, 1);
		/// <summary>
		/// Counteract unwanted light seams for tightly packed UV patches.
		/// </summary>
		public bool bilinearFilter = true;
		/// <summary>
		/// Find pixels which are only partially covered by the UV map.
		/// </summary>
		public bool conservativeRasterization = true;
		/// <summary>
		/// Expands the lightmap with the number of pixels specified to avoid black borders.
		/// </summary>
		public int edgeDilation = 3;
	}
}
Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox