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

780 lines
32 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 MicroSplatMeshModule : FeatureDescriptor
{
const string sDefine = "__MICROSPLAT_MESH__";
static MicroSplatMeshModule()
{
MicroSplatDefines.InitDefine(sDefine);
}
[PostProcessSceneAttribute (0)]
public static void OnPostprocessScene()
{
MicroSplatDefines.InitDefine(sDefine);
}
public override int DisplaySortOrder()
{
return -999;
}
public override string ModuleName()
{
return "Mesh";
}
public override bool HideModule ()
{
return meshWorkflow == DataSource.None;
}
public override string GetHelpPath ()
{
return "https://docs.google.com/document/d/14HjHRydayz0zr96tEqeQbfcZHhmA3yNIhdKeD9W1tPA/edit?usp=sharing";
}
public enum DefineFeature
{
_MESHOVERLAYSPLATS,
_MESHCOMBINED,
_MESHCOMBINEDEMISSION,
_MESHCOMBINEDSMOOTHMETAL,
_MESHCOMBINEDHEIGHT,
_MESHCOMBINEDOCCLUSION,
_MESHCOMBINEDPACKEDMAP,
_MESHCOMBINEDSPECULARMAP,
_MESHCOMBINENORMALREPLACE,
_MESHCOMBINEDDETAILALBEDO,
_MESHCOMBINEDDETAILNORMAL,
_MESHCOMBINEDSSSMAP,
_MESHCOMBINEDUSESSS,
_MESHSUBARRAY,
_MESHUV2,
_FORCELOCALSPACE,
_DISABLESPLATMAPS,
_MESHCOMBINEDPERTEXNORMALBLEND,
_DISPLACEMENTDAMPENING,
kNumFeatures,
}
public enum PBRMapPacking
{
Packed,
Separate
}
public enum ShaderType
{
SplatMap,
Overlay,
Combined
}
public enum UVSource
{
TextureUV,
LightmapUV,
}
public enum SSSMode
{
None,
Value,
Texture
}
public enum DataSource
{
None,
Texture,
Vertex
}
public ShaderType shaderType = ShaderType.SplatMap;
public bool combinedEmission;
public bool combinedSmoothMetal;
public bool combinedHeight;
public bool combinedOcclusion;
public bool combinedDetailAlbedo;
public bool combinedDetailNormal;
public bool combinedSpecular;
public SSSMode sssMode = SSSMode.None;
public bool subArray;
public bool forceLocalSpace;
public bool disableSplatMaps;
public UVSource uvSource = UVSource.TextureUV;
public DataSource meshWorkflow = DataSource.None;
public PBRMapPacking PBRPacking = PBRMapPacking.Packed;
public bool perTexNormalBlend;
#if __MICROSPLAT_TESSELLATION__
public bool displacementDampening;
#endif
GUIContent CShaderType = new GUIContent("Mesh Shader Mode", "SplatMap : Traditional Splat map shader\nOverlay : Allows you to blend textures onto existing materials\nCombined : A combined shader, with options for regular textures");
GUIContent CSubArray = new GUIContent("Use Sub Array", "Use 4 textures from a texture array to reduce the number of control maps needed.");
GUIContent CUVSource = new GUIContent("Source UVs", "Source UVs for mesh, should be unique, non-overlapping UVs in 0 to 1 space");
GUIContent CForceLocalSpace = new GUIContent("Force Local Space", "Forces world position and world normal into local space for all calculations");
GUIContent CDisableSplatMaps = new GUIContent ("Disable Splat Maps", "Disable Splat maps, for when we want the combined or overlay shader but only want effects to show on it, no splat mapping");
#if __MICROSPLAT_TESSELLATION__
GUIContent CDisplacementDampening = new GUIContent ("Displacement Dampening", "Allows you to paint where displacement should be removed to avoid cracking");
#endif
// Can we template these somehow?
public static string GetFeatureName(DefineFeature feature)
{
return System.Enum.GetName(typeof(DefineFeature), feature);
}
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 static bool HasFeature(string[] keywords, string f)
{
for (int i = 0; i < keywords.Length; ++i)
{
if (keywords[i] == f)
return true;
}
return false;
}
public override string GetVersion()
{
return "3.9";
}
static GUIContent CPBRPacking = new GUIContent ("Packing Mode", "Should we expect separate maps, or a map with PBR inputs pack together");
static GUIContent CCombinedSmoothMetal = new GUIContent("Enabled Smooth/Metal Map", "Use texture data for smoothness, and metal maps");
static GUIContent CCombinedEmission = new GUIContent("Enable Emission Map", "Enable a texture based emission map");
static GUIContent CCombinedHeight = new GUIContent("Enable Height Map", "Enable a height map texture");
static GUIContent CCombinedOcclusion = new GUIContent ("Enable Occlusion Map", "Enable an occlusion map texture");
static GUIContent CCombinedDetailAlbedo = new GUIContent ("Enable Detail Albedo", "Detail Map for Albedo");
static GUIContent CCombinedDetailNormal = new GUIContent ("Enable Detail Normal", "Detail Map for Normals");
static GUIContent CCombinedSSS = new GUIContent ("Subsurface Scattering Mode", "Do you want subsurface scattering? And do you want a consistent thickness or to provide a thickness map?");
static GUIContent CCombinedSpecular = new GUIContent ("Enabled Specular Map", "Use a specular map");
public override void DrawFeatureGUI(MicroSplatKeywords keywords)
{
if (meshWorkflow == DataSource.None)
return;
{
if (meshWorkflow == DataSource.Texture)
{
uvSource = (UVSource)EditorGUILayout.EnumPopup (CUVSource, uvSource);
}
shaderType = (ShaderType)EditorGUILayout.EnumPopup(CShaderType, shaderType);
forceLocalSpace = EditorGUILayout.Toggle(CForceLocalSpace, forceLocalSpace);
if (shaderType == ShaderType.Combined)
{
EditorGUI.indentLevel++;
PBRPacking = (PBRMapPacking)EditorGUILayout.EnumPopup(CPBRPacking, PBRPacking);
if (PBRPacking == PBRMapPacking.Separate)
{
combinedSmoothMetal = EditorGUILayout.Toggle (CCombinedSmoothMetal, combinedSmoothMetal);
combinedHeight = EditorGUILayout.Toggle (CCombinedHeight, combinedHeight);
combinedOcclusion = EditorGUILayout.Toggle (CCombinedOcclusion, combinedOcclusion);
}
if (keywords.IsKeywordEnabled("_USESPECULARWORKFLOW"))
{
combinedSpecular = EditorGUILayout.Toggle (CCombinedSpecular, combinedSpecular);
}
combinedEmission = EditorGUILayout.Toggle(CCombinedEmission, combinedEmission);
combinedDetailAlbedo = EditorGUILayout.Toggle (CCombinedDetailAlbedo, combinedDetailAlbedo);
combinedDetailNormal = EditorGUILayout.Toggle (CCombinedDetailNormal, combinedDetailNormal);
sssMode = (SSSMode)EditorGUILayout.EnumPopup (CCombinedSSS, sssMode);
disableSplatMaps = EditorGUILayout.Toggle (CDisableSplatMaps, disableSplatMaps);
EditorGUI.indentLevel--;
}
if (meshWorkflow == DataSource.Texture)
{
subArray = EditorGUILayout.Toggle (CSubArray, subArray);
#if __MICROSPLAT_TESSELLATION__
displacementDampening = EditorGUILayout.Toggle (CDisplacementDampening, displacementDampening);
#endif
}
}
}
static TextAsset combinedFunc;
static TextAsset vertexFunc;
static TextAsset combinedCBuffer;
public override string[] Pack()
{
List<string> features = new List<string>();
if (meshWorkflow != DataSource.None)
{
if (meshWorkflow == DataSource.Texture)
{
if (uvSource == UVSource.LightmapUV)
{
features.Add (GetFeatureName (DefineFeature._MESHUV2));
}
if (subArray)
{
features.Add (GetFeatureName (DefineFeature._MESHSUBARRAY));
}
#if __MICROSPLAT_TESSELLATION__
if (displacementDampening)
{
features.Add (GetFeatureName (DefineFeature._DISPLACEMENTDAMPENING));
}
#endif
}
if (forceLocalSpace)
{
features.Add (GetFeatureName (DefineFeature._FORCELOCALSPACE));
}
if (shaderType == ShaderType.Overlay)
{
features.Add(GetFeatureName(DefineFeature._MESHOVERLAYSPLATS));
}
if (shaderType == ShaderType.Combined)
{
features.Add(GetFeatureName(DefineFeature._MESHCOMBINED));
if (PBRPacking == PBRMapPacking.Separate)
{
if (combinedSmoothMetal)
{
features.Add (GetFeatureName (DefineFeature._MESHCOMBINEDSMOOTHMETAL));
}
if (combinedHeight)
{
features.Add (GetFeatureName (DefineFeature._MESHCOMBINEDHEIGHT));
}
if (combinedOcclusion)
{
features.Add (GetFeatureName (DefineFeature._MESHCOMBINEDOCCLUSION));
}
if (perTexNormalBlend)
{
features.Add (GetFeatureName (DefineFeature._MESHCOMBINEDPERTEXNORMALBLEND));
}
}
else
{
features.Add (GetFeatureName (DefineFeature._MESHCOMBINEDPACKEDMAP));
}
if (combinedSpecular)
{
features.Add (GetFeatureName (DefineFeature._MESHCOMBINEDSPECULARMAP));
}
if (combinedEmission)
{
features.Add(GetFeatureName(DefineFeature._MESHCOMBINEDEMISSION));
}
if (combinedDetailAlbedo)
{
features.Add (GetFeatureName (DefineFeature._MESHCOMBINEDDETAILALBEDO));
}
if (combinedDetailNormal)
{
features.Add (GetFeatureName (DefineFeature._MESHCOMBINEDDETAILNORMAL));
}
if (sssMode == SSSMode.Value || sssMode == SSSMode.Texture)
{
features.Add (GetFeatureName (DefineFeature._MESHCOMBINEDUSESSS));
if (sssMode == SSSMode.Texture)
{
features.Add (GetFeatureName (DefineFeature._MESHCOMBINEDSSSMAP));
}
}
if (disableSplatMaps)
{
features.Add(GetFeatureName (DefineFeature._DISABLESPLATMAPS));
}
}
}
return features.ToArray();
}
public override void Unpack(string[] keywords)
{
meshWorkflow = DataSource.None;
if (HasFeature (keywords, MicroSplatBaseFeatures.GetFeatureName (MicroSplatBaseFeatures.DefineFeature._MICROMESH)))
{
meshWorkflow = DataSource.Texture;
}
if (HasFeature (keywords, MicroSplatBaseFeatures.GetFeatureName (MicroSplatBaseFeatures.DefineFeature._MICROVERTEXMESH)))
{
meshWorkflow = DataSource.Vertex;
}
shaderType = (HasFeature(keywords, DefineFeature._MESHOVERLAYSPLATS)) ? ShaderType.Overlay : ShaderType.SplatMap;
if (HasFeature(keywords, DefineFeature._MESHCOMBINED))
{
shaderType = ShaderType.Combined;
perTexNormalBlend = HasFeature (keywords, DefineFeature._MESHCOMBINEDPERTEXNORMALBLEND);
}
if (HasFeature (keywords, DefineFeature._MESHCOMBINEDPACKEDMAP))
{
PBRPacking = PBRMapPacking.Packed;
}
else
{
PBRPacking = PBRMapPacking.Separate;
combinedSmoothMetal = HasFeature (keywords, DefineFeature._MESHCOMBINEDSMOOTHMETAL);
combinedHeight = HasFeature (keywords, DefineFeature._MESHCOMBINEDHEIGHT);
combinedOcclusion = HasFeature (keywords, DefineFeature._MESHCOMBINEDOCCLUSION);
}
combinedSpecular = HasFeature (keywords, DefineFeature._MESHCOMBINEDSPECULARMAP);
combinedEmission = HasFeature (keywords, DefineFeature._MESHCOMBINEDEMISSION);
combinedDetailAlbedo = HasFeature (keywords, DefineFeature._MESHCOMBINEDDETAILALBEDO);
combinedDetailNormal = HasFeature (keywords, DefineFeature._MESHCOMBINEDDETAILNORMAL);
sssMode = SSSMode.None;
if (HasFeature(keywords, DefineFeature._MESHCOMBINEDUSESSS))
{
sssMode = SSSMode.Value;
if (HasFeature(keywords, DefineFeature._MESHCOMBINEDSSSMAP))
{
sssMode = SSSMode.Texture;
}
}
subArray = HasFeature(keywords, DefineFeature._MESHSUBARRAY);
uvSource = HasFeature(keywords, DefineFeature._MESHUV2) ? UVSource.LightmapUV : UVSource.TextureUV;
forceLocalSpace = HasFeature(keywords, DefineFeature._FORCELOCALSPACE);
disableSplatMaps = HasFeature(keywords, DefineFeature._DISABLESPLATMAPS) && shaderType == ShaderType.Combined;
#if __MICROSPLAT_TESSELLATION__
displacementDampening = HasFeature(keywords, DefineFeature._DISPLACEMENTDAMPENING);
#endif
}
public override void InitCompiler(string[] paths)
{
for (int i = 0; i < paths.Length; ++i)
{
string p = paths[i];
if (p.EndsWith("microsplat_meshcombined_func.txt"))
{
combinedFunc = AssetDatabase.LoadAssetAtPath<TextAsset>(p);
}
if (p.EndsWith ("microsplat_meshcombined_cbuffer.txt"))
{
combinedCBuffer = AssetDatabase.LoadAssetAtPath<TextAsset> (p);
}
if (p.EndsWith ("microsplat_vertexmodule_func.txt"))
{
vertexFunc = AssetDatabase.LoadAssetAtPath<TextAsset> (p);
}
}
}
static GUIContent CStandardDiffuse = new GUIContent("Albedo", "Albedo texture");
static GUIContent CStandardNormal = new GUIContent("Normal", "Normal Map");
static GUIContent CStandardSmoothMetal = new GUIContent("Smoothness/Metal", "Smoothness Metal texture");
static GUIContent CStandardEmission = new GUIContent("Emission", "Emissive texture");
static GUIContent CStandardOcclusion = new GUIContent("Occlusion", "Occlusion texture");
static GUIContent CStandardHeight = new GUIContent("Height", "Height texture");
static GUIContent CStandardSpecular = new GUIContent ("Specular", "Specular Texture");
static GUIContent CStandardPackedMap = new GUIContent ("Packed Map", "(R) Metallic, (G) Smoothness, (B) Height (A) Occlusion");
static GUIContent CStandardSSS = new GUIContent ("Subsurface Scattering", "Subsurface Scattering map (G) thickness");
static GUIContent CStandardDetailAlbedo = new GUIContent ("Detail Albedo x2", "Albedo texture");
static GUIContent CStandardDetailNormal = new GUIContent ("Detail Normal", "Normal texture");
static GUIContent CStandardDetailUVScale = new GUIContent ("Detail UV Scale/Offset", "Scale and offset for UVs on the detail textures");
static GUIContent CStandardDetailNormalScale = new GUIContent ("Detail Normal Strength", "Strength of detail normal");
#if __MICROSPLAT_TESSELLATION__
static GUIContent CTessellationBlend = new GUIContent("Tessellation Blend", "Blend between base map and splat map tessellation. 0 is just the base map, 0.5 is mixed, 1 is just splats");
static GUIContent CTessellationOffset = new GUIContent("Tessellation Offset", "Center point for tessellation displacement, use the center button to compute the ideal offset");
#endif
public override void DrawShaderGUI(MicroSplatShaderGUI shaderGUI, MicroSplatKeywords keywords, Material mat, MaterialEditor materialEditor, MaterialProperty[] props)
{
if (keywords.IsKeywordEnabled ("_MICROMESH"))
{
if (keywords.IsKeywordEnabled ("_MESHOVERLAYSPLATS"))
{
if (MicroSplatUtilities.DrawRollup ("Mesh Overlay"))
{
if (mat.HasProperty ("_MeshAlphaIndex"))
{
materialEditor.ShaderProperty (shaderGUI.FindProp ("_MeshAlphaIndex", props), "Mesh Alpha Index");
}
}
}
}
if (keywords.IsKeywordEnabled ("_MESHCOMBINED"))
{
if (MicroSplatUtilities.DrawRollup ("Mesh Combined"))
{
if (disableSplatMaps)
{
// make sure alpha index is 0 in no splat case
if (mat.HasProperty ("_MeshAlphaIndex"))
{
if (mat.GetInt ("_MeshAlphaIndex") != 0)
{
mat.SetInt ("_MeshAlphaIndex", 0);
EditorUtility.SetDirty (mat);
}
}
}
else
{
if (mat.HasProperty ("_MeshAlphaIndex"))
{
materialEditor.ShaderProperty (shaderGUI.FindProp ("_MeshAlphaIndex", props), "Mesh Alpha Index");
}
}
if (mat.HasProperty ("_StandardDiffuse"))
{
EditorGUILayout.BeginHorizontal ();
materialEditor.TexturePropertySingleLine (CStandardDiffuse, shaderGUI.FindProp ("_StandardDiffuse", props));
var colorProp = shaderGUI.FindProp ("_StandardDiffuseTint", props);
var c = colorProp.colorValue;
var nc = EditorGUILayout.ColorField (c, GUILayout.Width (60));
if (c != nc)
{
colorProp.colorValue = nc;
}
EditorGUILayout.EndHorizontal ();
materialEditor.TexturePropertySingleLine (CStandardNormal, shaderGUI.FindProp ("_StandardNormal", props));
}
if (mat.HasProperty ("_StandardSmoothMetal"))
{
materialEditor.TexturePropertySingleLine (CStandardSmoothMetal, shaderGUI.FindProp ("_StandardSmoothMetal", props));
}
if (mat.HasProperty ("_StandardSmoothness"))
{
materialEditor.ShaderProperty (shaderGUI.FindProp ("_StandardSmoothness", props), "Smoothness");
materialEditor.ShaderProperty (shaderGUI.FindProp ("_StandardMetal", props), "Metallic");
}
if (mat.HasProperty ("_StandardHeight"))
{
materialEditor.TexturePropertySingleLine (CStandardHeight, shaderGUI.FindProp ("_StandardHeight", props));
}
if (mat.HasProperty ("_StandardSpecular"))
{
materialEditor.TexturePropertySingleLine (CStandardSpecular, shaderGUI.FindProp ("_StandardSpecular", props));
}
if (mat.HasProperty ("_StandardEmission"))
{
materialEditor.TexturePropertySingleLine (CStandardEmission, shaderGUI.FindProp ("_StandardEmission", props));
}
if (mat.HasProperty ("_StandardOcclusion"))
{
materialEditor.TexturePropertySingleLine (CStandardOcclusion, shaderGUI.FindProp ("_StandardOcclusion", props));
}
if (mat.HasProperty ("_StandardPackedMap"))
{
materialEditor.TexturePropertySingleLine (CStandardPackedMap, shaderGUI.FindProp ("_StandardPackedMap", props));
}
if (mat.HasProperty ("_StandardSSSMap"))
{
materialEditor.TexturePropertySingleLine (CStandardSSS, shaderGUI.FindProp ("_StandardSSSMap", props));
}
if (mat.HasProperty ("_StandardSSSValue"))
{
materialEditor.RangeProperty (shaderGUI.FindProp ("_StandardSSSValue", props), "Subsurface Thickness");
}
if (mat.HasProperty ("_StandardSSSTint"))
{
materialEditor.ColorProperty (shaderGUI.FindProp ("_StandardSSSTint", props), "Subsurface Tint");
}
if (mat.HasProperty ("_StandardSSSBlend"))
{
materialEditor.RangeProperty (shaderGUI.FindProp ("_StandardSSSBlend", props), "Subsurface Blend");
}
if (mat.HasProperty ("_StandardDetailAlbedo"))
{
materialEditor.TexturePropertySingleLine (CStandardDetailAlbedo, shaderGUI.FindProp ("_StandardDetailAlbedo", props));
}
if (mat.HasProperty ("_StandardDetailNormal"))
{
materialEditor.TexturePropertySingleLine (CStandardDetailNormal, shaderGUI.FindProp ("_StandardDetailNormal", props));
}
if (mat.HasProperty ("_StandardDetailUVScaleOffset"))
{
materialEditor.ShaderProperty (shaderGUI.FindProp ("_StandardDetailUVScaleOffset", props), CStandardDetailUVScale);
}
if (mat.HasProperty ("_StandardDetailNormalScale"))
{
materialEditor.ShaderProperty (shaderGUI.FindProp ("_StandardDetailNormalScale", props), CStandardDetailNormalScale);
}
if (!perTexNormalBlend && mat.HasProperty ("_CombinedMeshNormalBlend"))
{
materialEditor.ShaderProperty (shaderGUI.FindProp ("_CombinedMeshNormalBlend", props), "Normal Blend");
}
#if __MICROSPLAT_TESSELLATION__
if (mat.HasProperty ("_MeshCombineTessBlend"))
{
materialEditor.ShaderProperty (shaderGUI.FindProp ("_MeshCombineTessBlend", props), CTessellationBlend);
}
if (mat.HasProperty ("_MeshCombineTessOffset") && (mat.HasProperty ("_StandardPackedMap") || mat.HasProperty ("_StandardHeight")))
{
Texture2D tex = null;
if (mat.HasProperty ("_StandardPackedMap"))
{
tex = mat.GetTexture ("_StandardPackedMap") as Texture2D;
}
else
{
tex = mat.GetTexture ("_StandardHeight") as Texture2D;
}
if (tex != null)
{
EditorGUILayout.BeginHorizontal ();
materialEditor.ShaderProperty (shaderGUI.FindProp ("_MeshCombineTessOffset", props), CTessellationOffset);
if (GUILayout.Button ("Center", GUILayout.Width (54)))
{
float offset = MicroSplatTessellation.IdealOffset (tex, mat.HasProperty ("_StandardPackedMap") ? 3 : 1);
mat.SetFloat ("_MeshCombineTessOffset", offset);
}
EditorGUILayout.EndHorizontal ();
}
}
#endif
materialEditor.ShaderProperty (shaderGUI.FindProp ("_StandardUVScaleOffset", props), "UV Scale/Offset");
}
}
if (keywords.IsKeywordEnabled ("_MICROMESH"))
{
// TODO: instancing just seems to turn the material black in HDRP, disable for now..
if (keywords.IsKeywordEnabled ("_MSRENDERLOOP_UNITYHD") || keywords.IsKeywordEnabled("_MSRENDERLOOP_UNITYHDRP2020"))
{
mat.enableInstancing = false;
}
else
{
materialEditor.EnableInstancingField ();
}
}
//materialEditor.DoubleSidedGIField();
}
public override void WriteProperties (string [] features, System.Text.StringBuilder sb)
{
if (meshWorkflow == DataSource.None)
return;
if (meshWorkflow == DataSource.Texture)
{
sb.AppendLine (" _UVMeshRange(\"Mesh UV Range\", Vector) = (0,0,1,1)");
}
if (shaderType == ShaderType.Overlay)
{
sb.AppendLine (" _MeshAlphaIndex(\"MeshAlphaIndex\", Int) = 0");
}
else if (shaderType == ShaderType.Combined)
{
sb.AppendLine (" _MeshAlphaIndex(\"MeshAlphaIndex\", Int) = 0");
sb.AppendLine (" _StandardDiffuse(\"Diffuse/AO\", 2D) = \"white\" { }");
sb.AppendLine (" _StandardDiffuseTint(\"Tint\", Color) = (1,1,1,1)");
sb.AppendLine (" _StandardNormal(\"Normal\", 2D) = \"bump\" { }");
sb.AppendLine (" _CombinedMeshNormalBlend(\"Normal Blend\", Range(0, 1.5)) = 1");
if (PBRPacking == PBRMapPacking.Packed)
{
sb.AppendLine (" _StandardPackedMap(\"Smoothness / Metal\", 2D) = \"black\" { }");
}
else
{
if (combinedSmoothMetal)
{
sb.AppendLine (" _StandardSmoothMetal(\"Smoothness / Metal\", 2D) = \"black\" { }");
}
else
{
sb.AppendLine (" _StandardSmoothness(\"Smoothness\", Range(0, 1)) = 0");
sb.AppendLine (" _StandardMetal(\"Metallic\", Range(0, 1)) = 0");
}
if (combinedHeight)
{
sb.AppendLine (" _StandardHeight(\"Height\", 2D) = \"grey\" { }");
}
if (combinedOcclusion)
{
sb.AppendLine (" _StandardOcclusion(\"Occlusion\", 2D) = \"white\" { }");
}
if (HasFeature (features, "_TESSDISTANCE") && (combinedHeight || PBRPacking == PBRMapPacking.Packed))
{
sb.AppendLine (" _MeshCombineTessBlend(\"Tess Blend\", Range(0, 1)) = 0.5");
sb.AppendLine (" _MeshCombineTessOffset(\"Tess Offset\", Range(-1, 1)) = 0");
}
}
if (combinedSpecular)
{
sb.AppendLine (" _StandardSpecular(\"Specular\", 2D) = \"black\" { }");
}
if (combinedEmission)
{
sb.AppendLine (" _StandardEmission(\"Emission\", 2D) = \"black\" { }");
}
if (sssMode == SSSMode.Texture)
{
sb.AppendLine (" _StandardSSSMap(\"Subsurface\", 2D) = \"black\" { }");
}
else if (sssMode == SSSMode.Value)
{
sb.AppendLine (" _StandardSSSValue(\"Subsurface\", Range(0,1)) = 0.5");
}
if (sssMode != SSSMode.None)
{
sb.AppendLine (" _StandardSSSTint(\"Subsurface Tint\", Color) = (1, 1, 1, 1)");
sb.AppendLine (" _StandardSSSBlend(\"Subsurface Blend\", Range(0,1)) = 0.5");
}
if (combinedDetailAlbedo)
{
sb.AppendLine (" _StandardDetailAlbedo(\"DetailAlbedo\", 2D) = \"white\" {}");
}
if (combinedDetailNormal)
{
sb.AppendLine (" _StandardDetailNormal(\"DetailNormal\", 2D) = \"white\" {}");
sb.AppendLine (" _StandardDetailNormalScale(\"DetailNormalStrength\", Range(0, 2)) = 1");
}
if (combinedDetailNormal || combinedDetailAlbedo)
{
sb.AppendLine (" _StandardDetailUVScaleOffset(\"Detail UV Scale\", Vector) = (5,5,0,0)");
}
sb.AppendLine (" _StandardUVScaleOffset(\"UV Scale and Offset\", Vector) = (1, 1, 0, 0)");
}
if (meshWorkflow == DataSource.Texture)
{
if (subArray)
{
sb.AppendLine (" _MeshSubArrayIndexes(\"SubArray\", Vector) = (0,1,2,3)");
}
#if __MICROSPLAT_TESSELLATION__
if (displacementDampening)
{
sb.AppendLine (" _DisplacementDampening(\"Displacement Dampening\", 2D) = \"white\" {}");
}
#endif
}
}
public override void WritePerMaterialCBuffer (string[] features, System.Text.StringBuilder sb)
{
if (meshWorkflow == DataSource.None)
return;
if (meshWorkflow == DataSource.Texture)
{
sb.AppendLine (" float4 _UVMeshRange;");
}
if (shaderType != ShaderType.SplatMap)
{
sb.AppendLine(" int _MeshAlphaIndex;");
}
if (shaderType == ShaderType.Combined)
{
sb.AppendLine(combinedCBuffer.text);
}
}
public override void WriteFunctions(string [] features, System.Text.StringBuilder sb)
{
if (meshWorkflow != DataSource.None)
{
if (meshWorkflow == DataSource.Vertex)
{
sb.AppendLine (vertexFunc.text);
}
if (shaderType == ShaderType.Combined)
{
sb.AppendLine (combinedFunc.text);
}
}
}
public override void ComputeSampleCounts(string[] features, ref int arraySampleCount, ref int textureSampleCount, ref int maxSamples, ref int tessellationSamples, ref int depTexReadLevel)
{
if (meshWorkflow == DataSource.None)
return;
if (shaderType == ShaderType.Combined)
{
textureSampleCount += 2;
if (combinedEmission)
textureSampleCount++;
if (combinedDetailAlbedo)
textureSampleCount++;
if (combinedDetailNormal)
textureSampleCount++;
if (combinedSpecular)
textureSampleCount++;
if (PBRPacking == PBRMapPacking.Packed)
{
textureSampleCount++;
}
else
{
if (combinedHeight)
textureSampleCount++;
if (combinedSmoothMetal)
textureSampleCount++;
if (combinedOcclusion)
textureSampleCount++;
}
if (sssMode == SSSMode.Texture)
{
textureSampleCount++;
}
}
}
public static GUIContent CPerTexNormalBlend = new GUIContent ("Mesh Normal Blend", "Blends between mixed normals and splat map normals");
public override void DrawPerTextureGUI (int index, MicroSplatKeywords keywords, Material mat, MicroSplatPropData propData)
{
if (keywords.IsKeywordEnabled ("_MESHCOMBINED"))
{
perTexNormalBlend = DrawPerTexFloatSlider (index, 12, GetFeatureName (DefineFeature._MESHCOMBINEDPERTEXNORMALBLEND),
keywords, propData, Channel.A, CPerTexNormalBlend, 0.0f, 1.5f);
}
}
}
#endif
}