////////////////////////////////////////////////////// // MicroSplat // Copyright (c) Jason Booth ////////////////////////////////////////////////////// using UnityEngine; using System.Collections; using UnityEditor; using UnityEditor.Callbacks; using System.Collections.Generic; namespace JBooth.MicroSplat { #if __MICROSPLAT__ [InitializeOnLoad] public class MicroSplatStreams : FeatureDescriptor { [MenuItem("Window/MicroSplat/Create Stream Emitter")] static void AddEmitter() { GameObject go = new GameObject("MicroSplat Emitter"); go.transform.localScale = new Vector3(10, 10, 10); go.AddComponent(); } [MenuItem("Window/MicroSplat/Create Stream Collider")] static void AddCollider() { GameObject go = new GameObject("MicroSplat Collider"); go.transform.localScale = new Vector3(5, 5, 5); go.AddComponent(); } const string sDefine = "__MICROSPLAT_STREAMS__"; static MicroSplatStreams() { MicroSplatDefines.InitDefine(sDefine); } [PostProcessSceneAttribute(0)] public static void OnPostprocessScene() { MicroSplatDefines.InitDefine(sDefine); } public override string ModuleName() { return "Streams"; } public override string GetHelpPath () { return "https://docs.google.com/document/d/1EAOIWr_qJ4aE3WZbDxfPRRBBzGh7fbyyQmHMFCBbQHI/edit?usp=sharing"; } public enum DefineFeature { _WETNESS, _PUDDLES, _STREAMS, _LAVA, #if __MICROSPLAT_TEXTURECLUSTERS__ _LAVASTOCHASTIC, #endif _PERTEXPOROSITY, _PERTEXFOAM, _DYNAMICFLOWS, _WETNESSMASKSNOW, _HEIGHTWETNESS, _DISTANCEWETNESS, _RAINDROPS, _GLOBALWETNESS, _GLOBALPUDDLES, _GLOBALRAIN, _GLOBALSTREAMS, _STREAMHEIGHTFILTER, _LAVAHEIGHTFILTER, _SPECULARFADE, kNumFeatures, } public enum RainMode { None = 0, StreamsOnly, StreamsAndWetness, } static TextAsset wetnessProps; static TextAsset puddleProps; static TextAsset streamProps; static TextAsset lavaProps; static TextAsset rainProps; static TextAsset funcShared; static TextAsset cbufferShared; public bool wetness; public bool puddles; public bool streams; public bool lava; public bool perTexPorosity; public bool perTexFoam; public bool dynamicFlows; public bool wetnessMaskSnow; public bool heightWetness; public bool rainDrops; public bool globalWetness; public bool globalRain; public bool globalStreams; public bool globalPuddles; public bool heightDampStreams; public bool heightDampLava; public bool specularFade; public bool distanceWetness; #if __MICROSPLAT_TEXTURECLUSTERS__ public bool lavaStochastic; #endif GUIContent CWetness = new GUIContent("Wetness", "Paintable Wetness"); GUIContent CPuddles = new GUIContent("Puddles", "Paintable Puddles"); GUIContent CStreams = new GUIContent("Streams", "Paintable Streams"); GUIContent CLava = new GUIContent("Lava", "Paintable Lava"); GUIContent CDynamicFlows = new GUIContent("Dynamic Flows", "Allow for dynamic flows of water and lava over the terrain from emitter objects"); GUIContent CPerTexPorosity = new GUIContent("Porosity", "Porosity of the surface; higher porosities will absorb more water, darkening albedo and causing more reflection"); GUIContent CPerTexFoam = new GUIContent("Foam", "Control amount of water foam over each texture"); GUIContent CMaxStream = new GUIContent("Max Stream", "Global adjustment for stream strength"); GUIContent CWetnessMaskSnow = new GUIContent("Wetness Masks Snow", "When enabled, snow will be removed from areas which are not wet. This can be used with raycast wetness to remove snow from areas under coverage"); GUIContent CHeightWetness = new GUIContent("Wetness Height", "Enable wetness based on terrain height, useful for shorelines"); GUIContent CDistanceWetness = new GUIContent("Wetness Distance Fade", "Fade wetness based on distance from camera"); GUIContent CRainDrops = new GUIContent("Rain Drops", "Enables rain effects on water areas"); GUIContent CHeightDampStreams = new GUIContent("Stream Height Filter", "Adjust stream strength based on height. Filter below sea level, for instance"); GUIContent CHeightDampLava = new GUIContent("Lava Height Filter", "Adjust stream strength based on height. Filter below sea level, for instance"); GUIContent CSpecularFade = new GUIContent("Specular Fade", "Fade specular response below a certain height"); GUIContent CEmissionMult = new GUIContent("Emission Multiplier", "Increase emission value of lava"); #if __MICROSPLAT_TEXTURECLUSTERS__ GUIContent CLavaStochastic = new GUIContent("Stochastic Sample Lava", "Use Stochastic Sampling on lava to break up tiling"); #endif GUIContent CStreamTint = new GUIContent("Tint", "Tint color of the stream"); // Can we template these somehow? static Dictionary sFeatureNames = new Dictionary(); public static string GetFeatureName(DefineFeature feature) { string ret; if (sFeatureNames.TryGetValue(feature, out ret)) { return ret; } string fn = System.Enum.GetName(typeof(DefineFeature), feature); sFeatureNames[feature] = fn; return fn; } public static bool HasFeature(string[] keywords, DefineFeature feature) { string f = GetFeatureName(feature); for (int i = 0; i < keywords.Length; ++i) { if (keywords[i] == f) return true; } return false; } public override string GetVersion() { return "3.9"; } public override void DrawFeatureGUI(MicroSplatKeywords keywords) { wetness = EditorGUILayout.Toggle(CWetness, wetness); if (wetness) { EditorGUI.indentLevel++; heightWetness = EditorGUILayout.Toggle(CHeightWetness, heightWetness); distanceWetness = EditorGUILayout.Toggle(CDistanceWetness, distanceWetness); EditorGUI.indentLevel--; } puddles = EditorGUILayout.Toggle(CPuddles, puddles); if (puddles) { EditorGUI.indentLevel++; rainDrops = EditorGUILayout.Toggle(CRainDrops, rainDrops); EditorGUI.indentLevel--; } streams = EditorGUILayout.Toggle(CStreams, streams); if (streams) { EditorGUI.indentLevel++; heightDampStreams = EditorGUILayout.Toggle(CHeightDampStreams, heightDampStreams); EditorGUI.indentLevel--; } lava = EditorGUILayout.Toggle(CLava, lava); if (lava) { EditorGUI.indentLevel++; heightDampLava = EditorGUILayout.Toggle(CHeightDampLava, heightDampLava); #if __MICROSPLAT_TEXTURECLUSTERS__ lavaStochastic = EditorGUILayout.Toggle (CLavaStochastic, lavaStochastic); #endif EditorGUI.indentLevel--; } if ((streams || lava) && !keywords.IsKeywordEnabled("_MICROMESH")) { dynamicFlows = EditorGUILayout.Toggle(CDynamicFlows, dynamicFlows); } else { dynamicFlows = false; } if (keywords.IsKeywordEnabled("_SNOW")) { wetnessMaskSnow = EditorGUILayout.Toggle(CWetnessMaskSnow, wetnessMaskSnow); } else { wetnessMaskSnow = false; } specularFade = EditorGUILayout.Toggle(CSpecularFade, specularFade); } //static GUIContent CControl = new GUIContent("Control Texture", "Texture used to store control data"); static GUIContent CPuddleBlend = new GUIContent("Puddle Blend", "Blend sharpness for puddles"); static GUIContent CPuddleMax = new GUIContent("Puddle Max", "Maximum amount of puddles allowed in the scene, useful to ramp pre-painted puddles in and out with rain"); static GUIContent CLavaDiffuse = new GUIContent("Lava Texture", "Normal (RG), Height (B), Hardening(A)"); static GUIContent CLavaBlend = new GUIContent("Blend Width", "Blend border for lava"); static GUIContent CLavaMax = new GUIContent("Max", "Maximum amount of lava allowed."); static GUIContent CLavaSpeed = new GUIContent("Speed", "Speed of lava flow"); static GUIContent CLavaIntensity = new GUIContent("Intensity", "Intensity of Lava flow"); static GUIContent CLavaDistSize = new GUIContent("Distortion Size", "Size of distortion waves"); static GUIContent CLavaDistRate = new GUIContent("Distortion Rate", "Rate of distortion motion"); static GUIContent CLavaDistScale = new GUIContent("Distortion Scale", "UV scale of distortion"); static GUIContent CLavaColor = new GUIContent("Color", "Central color for lava"); static GUIContent CLavaEdgeColor = new GUIContent("Edge Color", "Color for glow around edges"); static GUIContent CLavaHighlightColor = new GUIContent("Highlight Color", "Color for highlights on lava"); static GUIContent CLavaUVScale = new GUIContent("UV Scale", "Scale of lava texture"); static GUIContent CLavaDarkening = new GUIContent("Drying", "Controls amount of drying lava to appear in flow"); static GUIContent CLavaDisplacementScale = new GUIContent("Displacement Scale", "How thick lava is when displacing via tessellation"); static GUIContent CStreamFoamTex = new GUIContent("Foam Texture", "Normal map in RG, Foam noise in B"); static GUIContent CStreamNormalBlend = new GUIContent("Normal Blend", "Controls how dampened the lighting normals are below the surface of the water"); static GUIContent CStreamBlend = new GUIContent("Edge Blend", "Controls the sharpness of the blend around stream edges"); static GUIContent CStreamFoamStr = new GUIContent("Foam Strength", "How much foam to add"); static GUIContent CStreamDepthDampen = new GUIContent("Depth Calm", "Causes deeper parts of the stream to have calmer water"); static GUIContent CStreamUVScale = new GUIContent("UV Scale", "UV Scale for normal/foam texture"); static GUIContent CStreamRefractionStrength = new GUIContent("Refraction Strength", "How much should the surface under the stream be distorted by the water"); static GUIContent CStreamFlowSpeed = new GUIContent("Flow Speed", "Overall speed of flow mapping"); static GUIContent CStreamFlowCycle = new GUIContent("Flow Cycle", "How long it takes the flow map to loop"); static GUIContent CHeightWetnessHeight = new GUIContent("Height", "Height at which terrain should be wet below"); static GUIContent CHeightWetnessContrast = new GUIContent("Contrast", "Blend width for height based wetness"); static GUIContent CHeightWetnessFrequency = new GUIContent("Frequency", "Frequency at which wetness height is varied"); static GUIContent CHeightWetnessAmplitude = new GUIContent("Amplitude", "Amplitude of wetness height motion"); static GUIContent CDistanceWetnessFade = new GUIContent("Distance Fade", "X: Distance to begin fade, Y: Weight at begin, Z: Fade Range, W: Weight at end"); static GUIContent CMinMaxWetness = new GUIContent("Wetness Range", "Minimum/Maximum wetness for the entire scene"); static GUIContent CRainIntensity = new GUIContent("Intensity", "How strong the rain drop effect is"); static GUIContent CRainUVScales = new GUIContent("Drop Size", "How big the effect is"); static GUIContent CHeightDamp = new GUIContent("Height Filtering", "World Height to start effect, be full effect, end full effect, and fade out effect"); static GUIContent CSpecularHeights = new GUIContent("Specular Fade Heights", "Height range to ramp in specular"); #if __MICROSPLAT_TEXTURECLUSTERS__ static GUIContent CLavaStochasticContrast = new GUIContent ("Stochastic Contrast", "Contrast for stochastic sampling of lava"); static GUIContent ClavaStochasticSize = new GUIContent ("Stochastic Size", "Size of stochastic areas"); #endif public override void DrawShaderGUI(MicroSplatShaderGUI shaderGUI, MicroSplatKeywords keywords, Material mat, MaterialEditor materialEditor, MaterialProperty[] props) { if (specularFade) { if (MicroSplatUtilities.DrawRollup("Specular Height Fade") && mat.HasProperty("_SpecularFades")) { Vector4 sf = mat.GetVector("_SpecularFades"); EditorGUI.BeginChangeCheck(); Vector2 vals = new Vector2(sf.x, sf.y); vals = EditorGUILayout.Vector2Field(CSpecularHeights, vals); sf.x = vals.x; sf.y = vals.y; if (EditorGUI.EndChangeCheck()) { mat.SetVector("_SpecularFades", sf); EditorUtility.SetDirty(mat); } } } if (wetness || puddles || streams || lava) { if (MicroSplatUtilities.DrawRollup("Streams & Lava")) { if (mat.HasProperty("_GlobalPorosity") && !keywords.IsKeywordEnabled("_PERTEXPOROSITY")) { materialEditor.ShaderProperty(shaderGUI.FindProp("_GlobalPorosity", props), "Default Porosity"); } if (wetness && mat.HasProperty("_WetnessParams")) { Vector4 wet = mat.GetVector("_WetnessParams"); EditorGUI.BeginChangeCheck(); EditorGUILayout.BeginHorizontal(); var oldEnabled = GUI.enabled; if (globalWetness) GUI.enabled = false; EditorGUILayout.MinMaxSlider(CMinMaxWetness, ref wet.x, ref wet.y, 0, 1); GUI.enabled = oldEnabled; globalWetness = DrawGlobalToggle(GetFeatureName(DefineFeature._GLOBALWETNESS), keywords); EditorGUILayout.EndHorizontal(); if (EditorGUI.EndChangeCheck()) { mat.SetVector("_WetnessParams", wet); EditorUtility.SetDirty(mat); } } if (heightWetness && mat.HasProperty("_HeightWetness")) { Vector4 wet = mat.GetVector("_HeightWetness"); EditorGUI.BeginChangeCheck(); wet.x = EditorGUILayout.FloatField(CHeightWetnessHeight, wet.x); wet.y = EditorGUILayout.FloatField(CHeightWetnessContrast, wet.y); wet.z = EditorGUILayout.FloatField(CHeightWetnessFrequency, wet.z); wet.w = EditorGUILayout.FloatField(CHeightWetnessAmplitude, wet.w); if (EditorGUI.EndChangeCheck()) { mat.SetVector("_HeightWetness", wet); EditorUtility.SetDirty(mat); } } if (distanceWetness && mat.HasProperty("_DistanceWetness")) { materialEditor.ShaderProperty(shaderGUI.FindProp("_DistanceWetness", props), CDistanceWetnessFade); } // PUDDLES if (puddles && mat.HasProperty("_PuddleParams") && MicroSplatUtilities.DrawRollup("Puddles", true, true)) { Vector4 pudV = mat.GetVector("_PuddleParams"); EditorGUI.BeginChangeCheck(); pudV.x = EditorGUILayout.Slider(CPuddleBlend, pudV.x, 0.01f, 60.0f); EditorGUILayout.BeginHorizontal(); var oldEnabled = GUI.enabled; if (globalPuddles) GUI.enabled = false; pudV.y = EditorGUILayout.Slider(CPuddleMax, pudV.y, 0.01f, 1.0f); GUI.enabled = oldEnabled; globalPuddles = DrawGlobalToggle(GetFeatureName(DefineFeature._GLOBALPUDDLES), keywords); EditorGUILayout.EndHorizontal(); if (EditorGUI.EndChangeCheck()) { mat.SetVector("_PuddleParams", pudV); EditorUtility.SetDirty(mat); } } if (rainDrops && mat.HasProperty("_RainDropTexture") && MicroSplatUtilities.DrawRollup("Rain Drops", true, true)) { MicroSplatUtilities.EnforceDefaultTexture(shaderGUI.FindProp("_RainDropTexture", props), "microsplat_def_raindrops"); EditorGUI.BeginChangeCheck(); var rainParams = shaderGUI.FindProp("_RainIntensityScale", props); Vector4 v = rainParams.vectorValue; EditorGUILayout.BeginHorizontal(); var oldEnabled = GUI.enabled; if (globalRain) GUI.enabled = false; v.x = EditorGUILayout.Slider(CRainIntensity, v.x, 0, 1); GUI.enabled = oldEnabled; globalRain = DrawGlobalToggle(GetFeatureName(DefineFeature._GLOBALRAIN), keywords); EditorGUILayout.EndHorizontal(); v.y = EditorGUILayout.FloatField(CRainUVScales, v.y); if (EditorGUI.EndChangeCheck()) { rainParams.vectorValue = v; } } // Streams if (streams && mat.HasProperty("_StreamBlend") && MicroSplatUtilities.DrawRollup("Streams", true, true)) { materialEditor.TexturePropertySingleLine(CStreamFoamTex, shaderGUI.FindProp("_StreamNormal", props)); MicroSplatUtilities.EnforceDefaultTexture(shaderGUI.FindProp("_StreamNormal", props), "microsplat_def_streamfoam"); materialEditor.ShaderProperty(shaderGUI.FindProp("_StreamBlend", props), CStreamBlend); EditorGUILayout.BeginHorizontal(); var oldEnabled = GUI.enabled; if (globalStreams) GUI.enabled = false; materialEditor.ShaderProperty(shaderGUI.FindProp("_StreamMax", props), CMaxStream); GUI.enabled = oldEnabled; globalStreams = DrawGlobalToggle(GetFeatureName(DefineFeature._GLOBALSTREAMS), keywords); EditorGUILayout.EndHorizontal(); Vector4 pudNF = mat.GetVector("_StreamNormalFoam"); EditorGUI.BeginChangeCheck(); pudNF.x = EditorGUILayout.Slider(CStreamNormalBlend, pudNF.x, 0, 1.0f); pudNF.y = EditorGUILayout.Slider(CStreamFoamStr, pudNF.y, 0.0f, 35.0f); if (EditorGUI.EndChangeCheck()) { mat.SetVector("_StreamNormalFoam", pudNF); EditorUtility.SetDirty(mat); } if (mat.HasProperty("_StreamTint")) { materialEditor.ShaderProperty(shaderGUI.FindProp("_StreamTint", props), CStreamTint); } if (mat.HasProperty("_StreamFlowParams")) { EditorGUI.BeginChangeCheck(); Vector4 pudp = mat.GetVector("_StreamFlowParams"); Vector4 pudUV = mat.GetVector("_StreamUVScales"); Vector2 puv = new Vector2(pudUV.x, pudUV.y); puv = EditorGUILayout.Vector2Field(CStreamUVScale, puv); pudp.x = EditorGUILayout.Slider(CStreamRefractionStrength, pudp.x, 0.0f, 0.5f); pudp.w = EditorGUILayout.Slider(CStreamDepthDampen, pudp.w, 0.0f, 1.0f); pudp.y = EditorGUILayout.FloatField(CStreamFlowSpeed, pudp.y); pudp.z = EditorGUILayout.FloatField(CStreamFlowCycle, pudp.z); if (EditorGUI.EndChangeCheck()) { mat.SetVector("_StreamFlowParams", pudp); mat.SetVector("_StreamUVScales", new Vector4(puv.x, puv.y, 0, 0)); EditorUtility.SetDirty(mat); } } if (heightDampStreams && mat.HasProperty("_StreamFades")) { materialEditor.ShaderProperty(shaderGUI.FindProp("_StreamFades", props), CHeightDamp); } } if (lava && mat.HasProperty("_LavaParams2") && MicroSplatUtilities.DrawRollup("Lava", true, true)) { materialEditor.TexturePropertySingleLine(CLavaDiffuse, shaderGUI.FindProp("_LavaDiffuse", props)); MicroSplatUtilities.EnforceDefaultTexture(shaderGUI.FindProp("_LavaDiffuse", props), "microsplat_def_lava_01"); EditorGUI.BeginChangeCheck(); Vector4 lavaUVs = mat.GetVector("_LavaUVScale"); Vector2 luv = new Vector2(lavaUVs.x, lavaUVs.y); luv = EditorGUILayout.Vector2Field(CLavaUVScale, luv); lavaUVs.x = luv.x; lavaUVs.y = luv.y; Vector4 lavaParams = mat.GetVector("_LavaParams"); lavaParams.x = EditorGUILayout.Slider(CLavaBlend, lavaParams.x, 2.0f, 40.0f); lavaParams.y = EditorGUILayout.Slider(CLavaMax, lavaParams.y, 0.0f, 1.0f); lavaParams.z = EditorGUILayout.FloatField(CLavaSpeed, lavaParams.z); lavaParams.w = EditorGUILayout.FloatField(CLavaIntensity, lavaParams.w); Vector4 lavaParams2 = mat.GetVector("_LavaParams2"); lavaParams2.w = EditorGUILayout.Slider(CLavaDarkening, lavaParams2.w, 0.0f, 6.0f); lavaParams2.x = EditorGUILayout.Slider(CLavaDistSize, lavaParams2.x, 0.0f, 0.3f); lavaParams2.y = EditorGUILayout.Slider(CLavaDistRate, lavaParams2.y, 0.0f, 0.08f); lavaParams2.z = EditorGUILayout.Slider(CLavaDistScale, lavaParams2.z, 0.02f, 1.0f); if (EditorGUI.EndChangeCheck()) { mat.SetVector("_LavaParams", lavaParams); mat.SetVector("_LavaParams2", lavaParams2); mat.SetVector("_LavaUVScale", lavaUVs); EditorUtility.SetDirty(mat); } materialEditor.ShaderProperty(shaderGUI.FindProp("_LavaColorLow", props), CLavaColor); materialEditor.ShaderProperty(shaderGUI.FindProp("_LavaColorHighlight", props), CLavaHighlightColor); materialEditor.ShaderProperty(shaderGUI.FindProp("_LavaEdgeColor", props), CLavaEdgeColor); if (mat.HasProperty ("_LavaEmissiveMult")) { materialEditor.ShaderProperty (shaderGUI.FindProp ("_LavaEmissiveMult", props), CEmissionMult); } if (keywords.IsKeywordEnabled("_TESSDISTANCE") && mat.HasProperty("_LavaDislacementScale")) { materialEditor.ShaderProperty(shaderGUI.FindProp("_LavaDislacementScale", props), CLavaDisplacementScale); } if (heightDampLava && mat.HasProperty("_LavaFades")) { materialEditor.ShaderProperty(shaderGUI.FindProp("_LavaFades", props), CHeightDamp); } #if __MICROSPLAT_TEXTURECLUSTERS__ if (lavaStochastic && mat.HasProperty("_LavaStochasticContrast")) { materialEditor.ShaderProperty (shaderGUI.FindProp ("_LavaStochasticContrast", props), CLavaStochasticContrast); materialEditor.ShaderProperty (shaderGUI.FindProp ("_LavaStochasticSize", props), ClavaStochasticSize); } #endif } } } } public override string[] Pack() { List features = new List(); if (specularFade) { features.Add(GetFeatureName(DefineFeature._SPECULARFADE)); } if (wetness) { features.Add(GetFeatureName(DefineFeature._WETNESS)); if (heightWetness) { features.Add(GetFeatureName(DefineFeature._HEIGHTWETNESS)); } if (distanceWetness) { features.Add(GetFeatureName(DefineFeature._DISTANCEWETNESS)); } } if (puddles) { features.Add(GetFeatureName(DefineFeature._PUDDLES)); } if (streams) { features.Add(GetFeatureName(DefineFeature._STREAMS)); if (heightDampStreams) { features.Add(GetFeatureName(DefineFeature._STREAMHEIGHTFILTER)); } } if (lava) { features.Add(GetFeatureName(DefineFeature._LAVA)); if (heightDampLava) { features.Add(GetFeatureName(DefineFeature._LAVAHEIGHTFILTER)); } #if __MICROSPLAT_TEXTURECLUSTERS__ if (lavaStochastic) { features.Add (GetFeatureName (DefineFeature._LAVASTOCHASTIC)); } #endif } if (perTexFoam) { features.Add(GetFeatureName(DefineFeature._PERTEXFOAM)); } if (perTexPorosity) { features.Add(GetFeatureName(DefineFeature._PERTEXPOROSITY)); } if (dynamicFlows) { features.Add(GetFeatureName(DefineFeature._DYNAMICFLOWS)); } if (wetnessMaskSnow) { features.Add(GetFeatureName(DefineFeature._WETNESSMASKSNOW)); } if (puddles && rainDrops) { features.Add(GetFeatureName(DefineFeature._RAINDROPS)); } if (globalWetness && wetness) { features.Add(GetFeatureName(DefineFeature._GLOBALWETNESS)); } if (globalStreams && streams) { features.Add(GetFeatureName(DefineFeature._GLOBALSTREAMS)); } if (globalPuddles && puddles) { features.Add(GetFeatureName(DefineFeature._GLOBALPUDDLES)); } if (globalRain && puddles) { features.Add(GetFeatureName(DefineFeature._GLOBALRAIN)); } return features.ToArray(); } public override void Unpack(string[] keywords) { wetness = HasFeature(keywords, DefineFeature._WETNESS); heightWetness = wetness && HasFeature(keywords, DefineFeature._HEIGHTWETNESS); distanceWetness = wetness && HasFeature(keywords, DefineFeature._DISTANCEWETNESS); puddles = HasFeature(keywords, DefineFeature._PUDDLES); streams = HasFeature(keywords, DefineFeature._STREAMS); lava = HasFeature(keywords, DefineFeature._LAVA); dynamicFlows = HasFeature(keywords, DefineFeature._DYNAMICFLOWS); perTexFoam = HasFeature(keywords, DefineFeature._PERTEXFOAM); perTexPorosity = HasFeature(keywords, DefineFeature._PERTEXPOROSITY); wetnessMaskSnow = HasFeature(keywords, DefineFeature._WETNESSMASKSNOW); rainDrops = HasFeature(keywords, DefineFeature._RAINDROPS); globalWetness = HasFeature(keywords, DefineFeature._GLOBALWETNESS); globalStreams = HasFeature(keywords, DefineFeature._GLOBALSTREAMS); globalPuddles = HasFeature(keywords, DefineFeature._GLOBALPUDDLES); globalRain = HasFeature(keywords, DefineFeature._GLOBALRAIN); heightDampStreams = HasFeature(keywords, DefineFeature._STREAMHEIGHTFILTER); heightDampLava = HasFeature(keywords, DefineFeature._LAVAHEIGHTFILTER); specularFade = HasFeature(keywords, DefineFeature._SPECULARFADE); #if __MICROSPLAT_TEXTURECLUSTERS__ lavaStochastic = HasFeature (keywords, DefineFeature._LAVASTOCHASTIC); #endif } public override void InitCompiler(string[] paths) { for (int i = 0; i < paths.Length; ++i) { string p = paths[i]; if (p.EndsWith("microsplat_properties_wetness.txt")) { wetnessProps = AssetDatabase.LoadAssetAtPath(p); } if (p.EndsWith("microsplat_properties_puddles.txt")) { puddleProps = AssetDatabase.LoadAssetAtPath(p); } if (p.EndsWith("microsplat_properties_streams.txt")) { streamProps = AssetDatabase.LoadAssetAtPath(p); } if (p.EndsWith("microsplat_properties_lava.txt")) { lavaProps = AssetDatabase.LoadAssetAtPath(p); } if (p.EndsWith("microsplat_func_stream_shared.txt")) { funcShared = AssetDatabase.LoadAssetAtPath(p); } if (p.EndsWith("microsplat_cbuffer_stream_shared.txt")) { cbufferShared = AssetDatabase.LoadAssetAtPath(p); } if (p.EndsWith("microsplat_properties_raindrops.txt")) { rainProps = AssetDatabase.LoadAssetAtPath(p); } } } public override void WriteProperties(string[] features, System.Text.StringBuilder sb) { if (wetness || puddles || streams || lava) { #if __MICROSPLAT_TRAX__ sb.AppendLine (" _TraxFXThresholds(\"Trax FX Thresholds\", Vector) = (0,0,0,0)"); #endif sb.AppendLine(" _StreamControl(\"Stream Control\", 2D) = \"black\" {}"); if (dynamicFlows) { sb.AppendLine(" _DynamicStreamControl(\"Stream Control\", 2D) = \"black\" {}"); } } if (specularFade) { sb.AppendLine(" _SpecularFades(\"Specular Heights\", Vector) = (0, 100, 0, 0)"); } if (wetness || puddles || streams) { sb.AppendLine(" _GlobalPorosity(\"Porosity\", Range(0.0, 1.0)) = 0.4"); } if (wetness) { sb.AppendLine(wetnessProps.text); if (heightWetness) { sb.AppendLine(" _HeightWetness(\"Height Wetness Params\", Vector) = (1, 0.1, 1, 1)"); } if (distanceWetness) { sb.AppendLine(" _DistanceWetness(\"Distance Wetness Fade\", Vector) = (100, 1, 200, 0)"); } } if (puddles) { sb.AppendLine(puddleProps.text); } if (streams) { sb.AppendLine(streamProps.text); if (heightDampStreams) { sb.AppendLine(" _StreamFades(\"Stream Height Fades\", Vector) = (0, 10, 1000, 1500)"); } } if (lava) { sb.AppendLine(lavaProps.text); if (heightDampLava) { sb.AppendLine(" _LavaFades(\"Lava Height Fades\", Vector) = (0, 10, 1000, 1500)"); } #if __MICROSPLAT_TEXTURECLUSTERS__ if (lavaStochastic) { sb.AppendLine (" _LavaStochasticContrast(\"Stochastic Contrast\", Range(0.001, 0.999)) = 0.5"); sb.AppendLine (" _LavaStochasticSize(\"Stochastic Size\", Range(0.5, 1.5)) = 1"); } #endif } if (puddles && rainDrops) { sb.AppendLine(rainProps.text); } } public override void WritePerMaterialCBuffer (string[] features, System.Text.StringBuilder sb) { if (specularFade) { sb.AppendLine(" float2 _SpecularFades;"); } if (wetness || puddles || streams || lava) { sb.AppendLine(cbufferShared.text); #if __MICROSPLAT_TRAX__ sb.AppendLine (" half4 _TraxFXThresholds;"); #endif } } public override void WriteFunctions(string [] features, System.Text.StringBuilder sb) { if (wetness || puddles || streams || lava) { sb.AppendLine(funcShared.text); } } public override void DrawPerTextureGUI(int index, MicroSplatKeywords keywords, Material mat, MicroSplatPropData propData) { if (wetness || streams) { perTexPorosity = DrawPerTexFloatSlider(index, 3, GetFeatureName(DefineFeature._PERTEXPOROSITY), keywords, propData, Channel.B, CPerTexPorosity, 0.0f, 1.0f); } if (streams) { perTexFoam = DrawPerTexFloatSlider(index, 3, GetFeatureName(DefineFeature._PERTEXFOAM), keywords, propData, Channel.A, CPerTexFoam, 0.0f, 2.0f); } } public override void ComputeSampleCounts(string[] features, ref int arraySampleCount, ref int textureSampleCount, ref int maxSamples, ref int tessellationSamples, ref int depTexReadLevel) { if (wetness || puddles || streams || lava) { textureSampleCount++; } if (streams) { textureSampleCount += 4; if (System.Array.Exists(features, e => e == "_MAX2LAYER")) { arraySampleCount += 2; } else if (System.Array.Exists(features, e => e == "_MAX3LAYER")) { arraySampleCount += 3; } else { arraySampleCount += 4; } } if (lava) { textureSampleCount += 4; #if __MICROSPLAT_TEXTURECLUSTERS__ if (lavaStochastic) { textureSampleCount += 8; } #endif } if (rainDrops) { textureSampleCount += 4; } } } #endif }