1
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"reference": "GUID:90ab0119788ed4ec6b8fe54dd44f01fa"
|
||||
}
|
@@ -0,0 +1,279 @@
|
||||
//////////////////////////////////////////////////////
|
||||
// MicroSplat
|
||||
// Copyright (c) Jason Booth
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Callbacks;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace JBooth.MicroSplat
|
||||
{
|
||||
#if __MICROSPLAT__ && (VEGETATION_STUDIO || VEGETATION_STUDIO_PRO)
|
||||
[InitializeOnLoad]
|
||||
public class MicroSplatVegetationStudio : FeatureDescriptor
|
||||
{
|
||||
public override string ModuleName()
|
||||
{
|
||||
return "Vegetation Studio";
|
||||
}
|
||||
|
||||
public enum DefineFeature
|
||||
{
|
||||
_VSGRASSMAP,
|
||||
_VSSHADOWMAP,
|
||||
_VSSHADOWTAPNONE,
|
||||
_VSSHADOWTAPLOW,
|
||||
_VSSHADOWTAPMEDIUM,
|
||||
_VSSHADOWTAPHIGH,
|
||||
kNumFeatures,
|
||||
}
|
||||
|
||||
public enum ShadowTapCount
|
||||
{
|
||||
None,
|
||||
Low,
|
||||
Medium,
|
||||
High,
|
||||
}
|
||||
|
||||
public bool grassMap;
|
||||
public bool shadowMap;
|
||||
public ShadowTapCount shadowTapCount = ShadowTapCount.Medium;
|
||||
|
||||
public TextAsset propsGrassMap;
|
||||
public TextAsset funcGrassMap;
|
||||
public TextAsset propsShadowMap;
|
||||
public TextAsset funcShadowMap;
|
||||
public TextAsset cbufferGrassMap;
|
||||
public TextAsset cbufferShadowMap;
|
||||
|
||||
GUIContent CShaderGrassMap = new GUIContent("Vegetation Studio GrassMap", "Enable texturing of distant grasses");
|
||||
GUIContent CShaderShadowMap = new GUIContent("Vegetation Studio ShadowMap", "Enable distance shadows for trees");
|
||||
GUIContent CShaderTapCount = new GUIContent("Shadow Map Quality", "Higher quality gives smoother shadows in the distance");
|
||||
// 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 override string GetVersion()
|
||||
{
|
||||
return "3.9";
|
||||
}
|
||||
|
||||
public override void DrawFeatureGUI(MicroSplatKeywords keywords)
|
||||
{
|
||||
grassMap = EditorGUILayout.Toggle(CShaderGrassMap, grassMap);
|
||||
shadowMap = EditorGUILayout.Toggle(CShaderShadowMap, shadowMap);
|
||||
if (shadowMap)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
shadowTapCount = (ShadowTapCount)EditorGUILayout.EnumPopup(CShaderTapCount, shadowTapCount);
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
|
||||
GUIContent CShaderTint = new GUIContent("Grass Mask Tint", "Tint the grass overlay color, or reduce it's overall effect with the alpha");
|
||||
//GUIContent CShadowMap = new GUIContent("Shadow Map", "Shadow Map for distant terrain");
|
||||
|
||||
public override void DrawShaderGUI(MicroSplatShaderGUI shaderGUI, MicroSplatKeywords keywords, Material mat, MaterialEditor materialEditor, MaterialProperty[] props)
|
||||
{
|
||||
if ((grassMap || shadowMap) && MicroSplatUtilities.DrawRollup("Vegetation Studio"))
|
||||
{
|
||||
if (grassMap && mat.HasProperty("_VSTint"))
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var c = mat.GetColor("_VSTint");
|
||||
c = EditorGUILayout.ColorField(CShaderTint, c);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
mat.SetColor("_VSTint", c);
|
||||
EditorUtility.SetDirty(mat);
|
||||
}
|
||||
}
|
||||
|
||||
if (shadowMap && mat.HasProperty("_VSShadowMap"))
|
||||
{
|
||||
var offsetProp = shaderGUI.FindProp("_VSShadowMapOffsetStrength", props);
|
||||
|
||||
Vector4 v = offsetProp.vectorValue;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
//v.x = EditorGUILayout.FloatField("Offset", v.x);
|
||||
v.y = EditorGUILayout.Slider("Min Tree Height", v.y, 0, 1.0f);
|
||||
v.z = EditorGUILayout.Slider("Shadow Strength", v.z, 0, 1.0f);
|
||||
v.w = EditorGUILayout.Slider("Shadow Ambient", v.w, 0, 1.0f);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
offsetProp.vectorValue = v;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override void InitCompiler(string[] paths)
|
||||
{
|
||||
for (int i = 0; i < paths.Length; ++i)
|
||||
{
|
||||
string p = paths[i];
|
||||
if (p.EndsWith("microsplat_properties_vsgrassmap.txt"))
|
||||
{
|
||||
propsGrassMap = AssetDatabase.LoadAssetAtPath<TextAsset>(p);
|
||||
}
|
||||
if (p.EndsWith("microsplat_func_vsgrassmap.txt"))
|
||||
{
|
||||
funcGrassMap = AssetDatabase.LoadAssetAtPath<TextAsset>(p);
|
||||
}
|
||||
if (p.EndsWith("microsplat_properties_vsshadowmap.txt"))
|
||||
{
|
||||
propsShadowMap = AssetDatabase.LoadAssetAtPath<TextAsset>(p);
|
||||
}
|
||||
if (p.EndsWith("microsplat_func_vsshadowmap.txt"))
|
||||
{
|
||||
funcShadowMap = AssetDatabase.LoadAssetAtPath<TextAsset>(p);
|
||||
}
|
||||
if (p.EndsWith ("microsplat_cbuffer_vsshadowmap.txt"))
|
||||
{
|
||||
cbufferShadowMap = AssetDatabase.LoadAssetAtPath<TextAsset> (p);
|
||||
}
|
||||
if (p.EndsWith ("microsplat_cbuffer_vsgrassmap.txt"))
|
||||
{
|
||||
cbufferGrassMap = AssetDatabase.LoadAssetAtPath<TextAsset> (p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteProperties(string[] features, System.Text.StringBuilder sb)
|
||||
{
|
||||
if (grassMap)
|
||||
{
|
||||
sb.Append(propsGrassMap.text);
|
||||
}
|
||||
|
||||
if (shadowMap)
|
||||
{
|
||||
sb.Append(propsShadowMap.text);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override void ComputeSampleCounts(string[] features, ref int arraySampleCount, ref int textureSampleCount, ref int maxSamples, ref int tessellationSamples, ref int depTexReadLevel)
|
||||
{
|
||||
if (grassMap)
|
||||
{
|
||||
textureSampleCount++;
|
||||
}
|
||||
|
||||
if (shadowMap)
|
||||
{
|
||||
textureSampleCount += ((int)shadowTapCount);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override string[] Pack()
|
||||
{
|
||||
List<string> features = new List<string>();
|
||||
if (grassMap)
|
||||
{
|
||||
features.Add(GetFeatureName(DefineFeature._VSGRASSMAP));
|
||||
}
|
||||
|
||||
if (shadowMap)
|
||||
{
|
||||
features.Add(GetFeatureName(DefineFeature._VSSHADOWMAP));
|
||||
switch (shadowTapCount)
|
||||
{
|
||||
case ShadowTapCount.None:
|
||||
features.Add(GetFeatureName(DefineFeature._VSSHADOWTAPNONE));
|
||||
break;
|
||||
case ShadowTapCount.Low:
|
||||
features.Add(GetFeatureName(DefineFeature._VSSHADOWTAPLOW));
|
||||
break;
|
||||
case ShadowTapCount.Medium:
|
||||
features.Add(GetFeatureName(DefineFeature._VSSHADOWTAPMEDIUM));
|
||||
break;
|
||||
case ShadowTapCount.High:
|
||||
features.Add(GetFeatureName(DefineFeature._VSSHADOWTAPHIGH));
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return features.ToArray();
|
||||
}
|
||||
|
||||
public override void WritePerMaterialCBuffer (string [] features, StringBuilder sb)
|
||||
{
|
||||
if (grassMap)
|
||||
{
|
||||
sb.AppendLine (cbufferGrassMap.text);
|
||||
}
|
||||
|
||||
if (shadowMap)
|
||||
{
|
||||
sb.AppendLine (cbufferShadowMap.text);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteFunctions(string[] features, System.Text.StringBuilder sb)
|
||||
{
|
||||
if (grassMap)
|
||||
{
|
||||
sb.AppendLine(funcGrassMap.text);
|
||||
}
|
||||
|
||||
if (shadowMap)
|
||||
{
|
||||
sb.AppendLine(funcShadowMap.text);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override void Unpack(string[] keywords)
|
||||
{
|
||||
grassMap = HasFeature(keywords, DefineFeature._VSGRASSMAP);
|
||||
shadowMap = HasFeature(keywords, DefineFeature._VSSHADOWMAP);
|
||||
|
||||
shadowTapCount = ShadowTapCount.Medium;
|
||||
if (HasFeature(keywords, DefineFeature._VSSHADOWTAPNONE))
|
||||
{
|
||||
shadowTapCount = ShadowTapCount.None;
|
||||
}
|
||||
else if (HasFeature(keywords, DefineFeature._VSSHADOWTAPLOW))
|
||||
{
|
||||
shadowTapCount = ShadowTapCount.Low;
|
||||
}
|
||||
else if (HasFeature(keywords, DefineFeature._VSSHADOWTAPHIGH))
|
||||
{
|
||||
shadowTapCount = ShadowTapCount.High;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
|
||||
|
||||
float4 _VSGrassFade;
|
||||
half4 _VSTint;
|
@@ -0,0 +1,8 @@
|
||||
|
||||
|
||||
float4 _VSShadowMap_TexelSize;
|
||||
float4 _VSShadowMapFadeScale;
|
||||
float4 _VSShadowMapOffsetStrength;
|
||||
|
||||
float4 gVSSunSettings;
|
||||
|
@@ -0,0 +1,18 @@
|
||||
|
||||
sampler2D _VSGrassMap;
|
||||
|
||||
|
||||
// no per tex is faster, just final value.
|
||||
void VSGrassTexture(inout half3 albedo, Config config, float camDist)
|
||||
{
|
||||
#if _VSGRASSMAP
|
||||
half4 tex = tex2D(_VSGrassMap, config.uv);
|
||||
half3 tint = _VSTint.rgb;
|
||||
#ifdef UNITY_COLORSPACE_GAMMA
|
||||
tint = GammaToLinearSpace(_VSTint.rgb);
|
||||
#endif
|
||||
tex *= half4(tint, _VSTint.a) * 2;
|
||||
float fade = saturate((camDist - _VSGrassFade.x) / max(_VSGrassFade.y, 0.01));
|
||||
albedo = lerp(albedo, BlendMult2X(albedo, tex.rgb), saturate(fade * tex.a));
|
||||
#endif
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
|
||||
sampler2D _VSShadowMap;
|
||||
|
||||
|
||||
void VSShadowTexture(inout MicroSplatLayer o, Input i, Config config, float camDist)
|
||||
{
|
||||
#if _VSSHADOWMAP
|
||||
#if _VSSHADOWTAPNONE
|
||||
const int taps = 1;
|
||||
#elif _VSSHADOWTAPLOW
|
||||
const int taps = 4;
|
||||
#elif _VSSHADOWTAPHIGH
|
||||
const int taps = 16;
|
||||
#else
|
||||
const int taps = 8; // medium
|
||||
#endif
|
||||
|
||||
const int maxTreeHeight = 64;
|
||||
// start at light and raycast back
|
||||
// offset the UVs to the end and subdivide the UV offset
|
||||
|
||||
|
||||
float3 tang = mul( GetTBN(i), gVSSunDirection.xyz ).xyz;
|
||||
|
||||
float2 uvOffset = tang.xy * _VSShadowMap_TexelSize.xy * maxTreeHeight;
|
||||
float2 uv = config.uv + uvOffset;
|
||||
uvOffset /= taps;
|
||||
// we move down/back along the ray
|
||||
float heightStep = (1.0 / (float)taps);
|
||||
float currentHeight = 1;
|
||||
float maxHeight = 0;
|
||||
|
||||
|
||||
// do taps.
|
||||
float dist = 1;
|
||||
for (int i = 0; i < taps; ++i)
|
||||
{
|
||||
uv -= uvOffset;
|
||||
currentHeight -= heightStep;
|
||||
half4 tex = tex2D(_VSShadowMap, uv);
|
||||
half top = tex.r;
|
||||
half bottom = 0.13; // hard coded min tree hight for now, use tex.g to see issue with dynamic.
|
||||
if (top > currentHeight && bottom < currentHeight)
|
||||
{
|
||||
maxHeight = 1;
|
||||
dist = i * heightStep;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (maxHeight > 0)
|
||||
{
|
||||
float fade = saturate((camDist - _VSShadowMapFadeScale.x) / max(_VSShadowMapFadeScale.y, 0.01));
|
||||
half shadow = fade * _VSShadowMapOffsetStrength.z * dist;
|
||||
shadow *= saturate(gVSSunDirection.w);
|
||||
o.Occlusion = saturate(o.Occlusion - shadow);
|
||||
o.Albedo = saturate(o.Albedo - shadow * _VSShadowMapOffsetStrength.w * gVSSunSettings.x * o.Albedo);
|
||||
o.Smoothness = saturate(o.Smoothness - shadow);
|
||||
o.Normal.xy *= (1-shadow);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
|
||||
_VSGrassMap("VS Grass Map", 2D) = "white" {}
|
||||
_VSTint("VS Tint", Color) = (0.5,0.5,0.5,1)
|
||||
//global//_VSGrassFade("VS Fade", Vector) = (50, 150, 1, 1)
|
@@ -0,0 +1,4 @@
|
||||
|
||||
_VSShadowMap("VS Shadow Map", 2D) = "black" {}
|
||||
_VSShadowMapOffsetStrength("VS Shadow Offset/Strength", Vector) = (16,0.13,0.4,0.3)
|
||||
//_VSShadowMapFadeScale("VS Fade and UV Scale", Vector) = (50, 150, 1.1, 1.1)
|
Reference in New Issue
Block a user