Files
2025-06-04 09:09:39 +08:00

838 lines
34 KiB
C#

//////////////////////////////////////////////////////
// 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<StreamEmitter>();
}
[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<StreamCollider>();
}
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<DefineFeature, string> sFeatureNames = new Dictionary<DefineFeature, string>();
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<string> features = new List<string>();
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<TextAsset>(p);
}
if (p.EndsWith("microsplat_properties_puddles.txt"))
{
puddleProps = AssetDatabase.LoadAssetAtPath<TextAsset>(p);
}
if (p.EndsWith("microsplat_properties_streams.txt"))
{
streamProps = AssetDatabase.LoadAssetAtPath<TextAsset>(p);
}
if (p.EndsWith("microsplat_properties_lava.txt"))
{
lavaProps = AssetDatabase.LoadAssetAtPath<TextAsset>(p);
}
if (p.EndsWith("microsplat_func_stream_shared.txt"))
{
funcShared = AssetDatabase.LoadAssetAtPath<TextAsset>(p);
}
if (p.EndsWith("microsplat_cbuffer_stream_shared.txt"))
{
cbufferShared = AssetDatabase.LoadAssetAtPath<TextAsset>(p);
}
if (p.EndsWith("microsplat_properties_raindrops.txt"))
{
rainProps = AssetDatabase.LoadAssetAtPath<TextAsset>(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
}