升级水插件
This commit is contained in:
@@ -0,0 +1,739 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Rendering.BuiltIn;
|
||||
using UnityEditor.Rendering.BuiltIn.ShaderGraph;
|
||||
using UnityEditor.ShaderGraph;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
#if UNITY_2022_3_OR_NEWER
|
||||
using UnityEngine.UIElements;
|
||||
#else
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
#endif
|
||||
|
||||
using UnityBuiltInLitSubTarget = UnityEditor.Rendering.BuiltIn.ShaderGraph.BuiltInLitSubTarget;
|
||||
|
||||
namespace WaveHarmonic.Crest.Editor.ShaderGraph
|
||||
{
|
||||
sealed class MaterialModificationProcessor : AssetModificationProcessor
|
||||
{
|
||||
static void OnWillCreateAsset(string asset)
|
||||
{
|
||||
if (!asset.ToLowerInvariant().EndsWith(".mat"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MaterialPostProcessor.s_CreatedAssets.Add(asset);
|
||||
}
|
||||
}
|
||||
|
||||
sealed class MaterialPostProcessor : AssetPostprocessor
|
||||
{
|
||||
public override int GetPostprocessOrder()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
internal static readonly List<string> s_CreatedAssets = new();
|
||||
|
||||
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
|
||||
{
|
||||
foreach (var asset in importedAssets)
|
||||
{
|
||||
// We only care about materials
|
||||
if (!asset.EndsWith(".mat", System.StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Load the material and look for it's BuiltIn ShaderID.
|
||||
// We only care about versioning materials using a known BuiltIn ShaderID.
|
||||
// This skips any materials that only target other render pipelines, are user shaders,
|
||||
// or are shaders we don't care to version
|
||||
var material = (Material)AssetDatabase.LoadAssetAtPath(asset, typeof(Material));
|
||||
var shaderID = ShaderUtils.GetShaderID(material.shader);
|
||||
if (shaderID == ShaderUtils.ShaderID.Unknown)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (material.shader == null || material.shader.name != "Crest/Water")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Look for the BuiltIn AssetVersion
|
||||
AssetVersion assetVersion = null;
|
||||
var allAssets = AssetDatabase.LoadAllAssetsAtPath(asset);
|
||||
foreach (var subAsset in allAssets)
|
||||
{
|
||||
if (subAsset is AssetVersion sub)
|
||||
{
|
||||
assetVersion = sub;
|
||||
}
|
||||
}
|
||||
|
||||
if (!assetVersion)
|
||||
{
|
||||
if (s_CreatedAssets.Contains(asset))
|
||||
{
|
||||
s_CreatedAssets.Remove(asset);
|
||||
CustomBuiltInLitGUI.UpdateMaterial(material);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CustomBuiltInLitGUI : BuiltInLitGUI
|
||||
{
|
||||
MaterialEditor _MaterialEditor;
|
||||
MaterialProperty[] _Properties;
|
||||
|
||||
static readonly GUIContent s_WorkflowModeText = EditorGUIUtility.TrTextContent
|
||||
(
|
||||
"Workflow Mode",
|
||||
"Select a workflow that fits your textures. Choose between Metallic or Specular."
|
||||
);
|
||||
|
||||
static readonly GUIContent s_TransparentReceiveShadowsText = EditorGUIUtility.TrTextContent
|
||||
(
|
||||
"Receives Shadows",
|
||||
"When enabled, other GameObjects can cast shadows onto this GameObject."
|
||||
);
|
||||
|
||||
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
|
||||
{
|
||||
_MaterialEditor = materialEditor;
|
||||
_Properties = properties;
|
||||
|
||||
base.OnGUI(materialEditor, properties);
|
||||
}
|
||||
|
||||
public override void ValidateMaterial(Material material)
|
||||
{
|
||||
base.ValidateMaterial(material);
|
||||
UpdateMaterial(material);
|
||||
}
|
||||
|
||||
public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
|
||||
{
|
||||
base.AssignNewShaderToMaterial(material, oldShader, newShader);
|
||||
UpdateMaterial(material);
|
||||
}
|
||||
|
||||
protected override void DrawSurfaceOptions(Material material)
|
||||
{
|
||||
var materialEditor = _MaterialEditor;
|
||||
var properties = _Properties;
|
||||
|
||||
var workflowProperty = FindProperty(Property.SpecularWorkflowMode(), properties, false);
|
||||
if (workflowProperty != null)
|
||||
{
|
||||
DoPopup(s_WorkflowModeText, materialEditor, workflowProperty, System.Enum.GetNames(typeof(WorkflowMode)));
|
||||
}
|
||||
|
||||
base.DrawSurfaceOptions(material);
|
||||
|
||||
var surfaceTypeProp = FindProperty(Property.Surface(), properties, false);
|
||||
if (surfaceTypeProp != null && (SurfaceType)surfaceTypeProp.floatValue == SurfaceType.Transparent)
|
||||
{
|
||||
var trsProperty = FindProperty(BuiltInLitSubTarget.s_TransparentReceiveShadowsProperty, properties, false);
|
||||
DrawFloatToggleProperty(s_TransparentReceiveShadowsText, trsProperty);
|
||||
}
|
||||
}
|
||||
|
||||
// Should be called by ShaderGraphMaterialsUpdater, but we will never upgrade.
|
||||
public static new void UpdateMaterial(Material material)
|
||||
{
|
||||
if (material.HasProperty(Property.SpecularWorkflowMode()))
|
||||
{
|
||||
var workflow = (WorkflowMode)material.GetFloat(Property.SpecularWorkflowMode());
|
||||
CoreUtils.SetKeyword(material, BuiltInLitSubTarget.LitDefines.s_SpecularSetup.referenceName, workflow == WorkflowMode.Specular);
|
||||
}
|
||||
|
||||
if (material.HasProperty(BuiltInLitSubTarget.s_TransparentReceiveShadowsProperty))
|
||||
{
|
||||
var receive = material.GetFloat(BuiltInLitSubTarget.s_TransparentReceiveShadowsProperty) == 1f;
|
||||
CoreUtils.SetKeyword(material, BuiltInLitSubTarget.LitDefines.s_TransparentReceivesShadows.referenceName, receive);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class BuiltInLitSubTarget : BuiltInSubTarget
|
||||
{
|
||||
const string k_ShaderPath = "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy";
|
||||
const string k_TemplatePath = "Packages/com.waveharmonic.crest/Editor/Shaders/Templates";
|
||||
|
||||
readonly UnityBuiltInLitSubTarget _BuiltInLitSubTarget;
|
||||
|
||||
#pragma warning disable IDE0032, IDE1006
|
||||
[SerializeField]
|
||||
WorkflowMode m_WorkflowMode = WorkflowMode.Metallic;
|
||||
|
||||
[SerializeField]
|
||||
NormalDropOffSpace m_NormalDropOffSpace = NormalDropOffSpace.Tangent;
|
||||
|
||||
[SerializeField]
|
||||
bool m_TransparentReceiveShadows = true;
|
||||
#pragma warning restore IDE0032, IDE1006
|
||||
|
||||
public static readonly string s_TransparentReceiveShadowsProperty = "_BUILTIN_TransparentReceiveShadows";
|
||||
|
||||
public BuiltInLitSubTarget()
|
||||
{
|
||||
_BuiltInLitSubTarget = new();
|
||||
displayName = _BuiltInLitSubTarget.displayName;
|
||||
}
|
||||
|
||||
protected override ShaderUtils.ShaderID shaderID => ShaderUtils.ShaderID.SG_Lit;
|
||||
public override bool IsActive() => true;
|
||||
|
||||
WorkflowMode WorkflowMode
|
||||
{
|
||||
get => m_WorkflowMode;
|
||||
set => m_WorkflowMode = value;
|
||||
}
|
||||
|
||||
NormalDropOffSpace NormalDropOffSpace
|
||||
{
|
||||
get => m_NormalDropOffSpace;
|
||||
set => m_NormalDropOffSpace = value;
|
||||
}
|
||||
|
||||
bool TransparentReceiveShadows
|
||||
{
|
||||
get => m_TransparentReceiveShadows;
|
||||
set => m_TransparentReceiveShadows = value;
|
||||
}
|
||||
|
||||
#if UNITY_2022_3_OR_NEWER
|
||||
static FieldInfo s_CustomEditorForRenderPipelines;
|
||||
static FieldInfo CustomEditorForRenderPipelines => s_CustomEditorForRenderPipelines ??= typeof(TargetSetupContext).GetField("customEditorForRenderPipelines", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
#endif
|
||||
|
||||
public override void Setup(ref TargetSetupContext context)
|
||||
{
|
||||
_BuiltInLitSubTarget.target = target;
|
||||
_BuiltInLitSubTarget.normalDropOffSpace = NormalDropOffSpace;
|
||||
_BuiltInLitSubTarget.Setup(ref context);
|
||||
|
||||
// Caused a crash: !context.HasCustomEditorForRenderPipeline(null)
|
||||
if (string.IsNullOrEmpty(target.customEditorGUI))
|
||||
{
|
||||
#if UNITY_2022_3_OR_NEWER
|
||||
var editors = (List<ShaderCustomEditor>)CustomEditorForRenderPipelines.GetValue(context);
|
||||
if (editors.Count > 0)
|
||||
{
|
||||
editors.RemoveAt(editors.Count - 1);
|
||||
}
|
||||
|
||||
context.AddCustomEditorForRenderPipeline(typeof(CustomBuiltInLitGUI).FullName, "");
|
||||
#else
|
||||
if (context.customEditorForRenderPipelines.Count > 0)
|
||||
{
|
||||
context.customEditorForRenderPipelines.RemoveAt(context.customEditorForRenderPipelines.Count - 1);
|
||||
}
|
||||
|
||||
context.customEditorForRenderPipelines.Add((typeof(CustomBuiltInLitGUI).FullName, ""));
|
||||
#endif
|
||||
}
|
||||
|
||||
context.subShaders.RemoveAt(0);
|
||||
context.AddSubShader(SubShaders.Lit(this));
|
||||
}
|
||||
|
||||
public override void ProcessPreviewMaterial(Material material)
|
||||
{
|
||||
_BuiltInLitSubTarget.target = target;
|
||||
_BuiltInLitSubTarget.normalDropOffSpace = NormalDropOffSpace;
|
||||
_BuiltInLitSubTarget.ProcessPreviewMaterial(material);
|
||||
CustomBuiltInLitGUI.UpdateMaterial(material);
|
||||
}
|
||||
|
||||
public override void GetFields(ref TargetFieldContext context)
|
||||
{
|
||||
_BuiltInLitSubTarget.target = target;
|
||||
_BuiltInLitSubTarget.normalDropOffSpace = NormalDropOffSpace;
|
||||
_BuiltInLitSubTarget.GetFields(ref context);
|
||||
// Do not use this, as we handle this properly.
|
||||
context.AddField(BuiltInFields.SpecularSetup, false);
|
||||
}
|
||||
|
||||
public override void GetActiveBlocks(ref TargetActiveBlockContext context)
|
||||
{
|
||||
_BuiltInLitSubTarget.target = target;
|
||||
_BuiltInLitSubTarget.normalDropOffSpace = NormalDropOffSpace;
|
||||
_BuiltInLitSubTarget.GetActiveBlocks(ref context);
|
||||
|
||||
context.activeBlocks.Remove(BlockFields.SurfaceDescription.Metallic);
|
||||
var insertion = context.activeBlocks.FindIndex(x => x == BlockFields.SurfaceDescription.Occlusion) + 1;
|
||||
|
||||
if ((WorkflowMode == WorkflowMode.Specular) || target.allowMaterialOverride)
|
||||
{
|
||||
context.activeBlocks.Insert(insertion, BlockFields.SurfaceDescription.Specular);
|
||||
}
|
||||
|
||||
if ((WorkflowMode == WorkflowMode.Metallic) || target.allowMaterialOverride)
|
||||
{
|
||||
context.activeBlocks.Insert(insertion, BlockFields.SurfaceDescription.Metallic);
|
||||
}
|
||||
}
|
||||
|
||||
public override void CollectShaderProperties(PropertyCollector collector, GenerationMode generationMode)
|
||||
{
|
||||
if (target.allowMaterialOverride)
|
||||
{
|
||||
collector.AddFloatProperty(Property.SpecularWorkflowMode(), (float)WorkflowMode);
|
||||
}
|
||||
|
||||
_BuiltInLitSubTarget.target = target;
|
||||
_BuiltInLitSubTarget.normalDropOffSpace = NormalDropOffSpace;
|
||||
_BuiltInLitSubTarget.CollectShaderProperties(collector, generationMode);
|
||||
|
||||
if (target.allowMaterialOverride)
|
||||
{
|
||||
collector.AddFloatProperty(s_TransparentReceiveShadowsProperty, TransparentReceiveShadows ? 1f : 0f);
|
||||
}
|
||||
|
||||
// LEqual
|
||||
collector.AddFloatProperty(SubShaders.k_ShadowCasterZTest, 4, UnityEditor.ShaderGraph.Internal.HLSLDeclaration.UnityPerMaterial);
|
||||
}
|
||||
|
||||
public override void GetPropertiesGUI(ref TargetPropertyGUIContext context, System.Action onChange, System.Action<string> registerUndo)
|
||||
{
|
||||
target.AddDefaultMaterialOverrideGUI(ref context, onChange, registerUndo);
|
||||
|
||||
context.AddProperty("Workflow", new EnumField(WorkflowMode.Metallic) { value = WorkflowMode }, (evt) =>
|
||||
{
|
||||
if (Equals(WorkflowMode, evt.newValue))
|
||||
return;
|
||||
|
||||
registerUndo("Change Workflow");
|
||||
WorkflowMode = (WorkflowMode)evt.newValue;
|
||||
onChange();
|
||||
});
|
||||
|
||||
target.GetDefaultSurfacePropertiesGUI(ref context, onChange, registerUndo);
|
||||
|
||||
context.AddProperty("Transparent Receives Shadows", new Toggle() { value = TransparentReceiveShadows }, (evt) =>
|
||||
{
|
||||
if (Equals(TransparentReceiveShadows, evt.newValue))
|
||||
return;
|
||||
|
||||
registerUndo("Change Transparent Receives Shadows");
|
||||
TransparentReceiveShadows = evt.newValue;
|
||||
onChange();
|
||||
});
|
||||
|
||||
context.AddProperty("Fragment Normal Space", new EnumField(NormalDropOffSpace.Tangent) { value = NormalDropOffSpace }, (evt) =>
|
||||
{
|
||||
if (Equals(NormalDropOffSpace, evt.newValue))
|
||||
return;
|
||||
|
||||
registerUndo("Change Fragment Normal Space");
|
||||
NormalDropOffSpace = (NormalDropOffSpace)evt.newValue;
|
||||
_BuiltInLitSubTarget.normalDropOffSpace = NormalDropOffSpace;
|
||||
onChange();
|
||||
});
|
||||
}
|
||||
|
||||
static class SubShaders
|
||||
{
|
||||
static readonly string s_ShaderPathDefines = $"{k_ShaderPath}/Defines.hlsl";
|
||||
static readonly string s_ShaderPathBuilding = $"{k_ShaderPath}/LegacyBuilding.hlsl";
|
||||
|
||||
// SetShaderPassEnabled on ShadowCaster pass does not work for BIRP. We set ZTest
|
||||
// to Never which is the best we can do. We are still incurring the draw call cost.
|
||||
// This is an issue because of the way we trigger motion vectors, but is a bug with
|
||||
// Unity and should be reported.
|
||||
internal const string k_ShadowCasterZTest = "_Crest_BUILTIN_ShadowCasterZTest";
|
||||
|
||||
internal static System.Type s_SubShadersType;
|
||||
internal static System.Type SubShadersType => s_SubShadersType ??= typeof(UnityBuiltInLitSubTarget).GetNestedType("SubShaders", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
internal static MethodInfo s_LitMethod;
|
||||
internal static MethodInfo LitMethod => s_LitMethod ??= SubShadersType.GetMethod("Lit", BindingFlags.Static | BindingFlags.Public);
|
||||
|
||||
static void PatchIncludes(ref PassDescriptor result)
|
||||
{
|
||||
var includes = new IncludeCollection();
|
||||
|
||||
includes.Add(s_ShaderPathDefines, IncludeLocation.Pregraph);
|
||||
includes.Add("Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/Editor/ShaderGraph/Includes/ShaderPass.hlsl", IncludeLocation.Pregraph);
|
||||
|
||||
foreach (var include in result.includes)
|
||||
{
|
||||
includes.AddInternal(include.guid, include.path, include.location, include.fieldConditions);
|
||||
}
|
||||
|
||||
result.includes = includes;
|
||||
}
|
||||
|
||||
static void PatchSpecularIncludes(ref PassDescriptor result, string file)
|
||||
{
|
||||
var ic = new IncludeCollection();
|
||||
foreach (var include in result.includes)
|
||||
{
|
||||
if (include.path.EndsWith(file))
|
||||
{
|
||||
ic.Add(s_ShaderPathBuilding, include.location);
|
||||
ic.AddInternal(include.guid, include.path, include.location, include.fieldConditions);
|
||||
}
|
||||
else
|
||||
{
|
||||
ic.AddInternal(include.guid, include.path, include.location, include.fieldConditions);
|
||||
}
|
||||
}
|
||||
|
||||
result.includes = ic;
|
||||
}
|
||||
|
||||
static readonly Dictionary<string, string> s_Mappings = new()
|
||||
{
|
||||
{ "SHADERPASS_FORWARD", "PBRForwardPass.hlsl" },
|
||||
{ "SHADERPASS_FORWARD_ADD", "PBRForwardAddPass.hlsl" },
|
||||
{ "SHADERPASS_DEFERRED", "PBRDeferredPass.hlsl" },
|
||||
};
|
||||
|
||||
static readonly string[] s_SkipVariants = new string[]
|
||||
{
|
||||
"LIGHTMAP_ON",
|
||||
"LIGHTMAP_SHADOW_MIXING",
|
||||
"DIRLIGHTMAP_COMBINED",
|
||||
"DYNAMICLIGHTMAP_ON",
|
||||
"SHADOWS_SHADOWMASK",
|
||||
};
|
||||
|
||||
public static SubShaderDescriptor Lit(BuiltInLitSubTarget subtarget)
|
||||
{
|
||||
var target = subtarget.target;
|
||||
var ssd = (SubShaderDescriptor)LitMethod.Invoke(null, new object[] { target, target.renderType, target.renderQueue });
|
||||
|
||||
PassCollection passes = new();
|
||||
|
||||
foreach (var item in ssd.passes)
|
||||
{
|
||||
// Many artifacts in U6 if our Write Depth enabled.
|
||||
// Caused by _SURFACE_TYPE_TRANSPARENT in m_ValidKeywords.
|
||||
if (item.descriptor.referenceName == "SceneSelectionPass")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var result = item.descriptor;
|
||||
|
||||
var keywords = new KeywordCollection();
|
||||
|
||||
foreach (var keyword in result.keywords)
|
||||
{
|
||||
// All others are either duplicate or unused.
|
||||
if (!keyword.descriptor.referenceName.StartsWith("_BUILTIN_"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
keywords.Add(keyword.descriptor, keyword.fieldConditions);
|
||||
}
|
||||
|
||||
result.keywords = keywords;
|
||||
|
||||
switch (item.descriptor.referenceName)
|
||||
{
|
||||
case "SHADERPASS_FORWARD":
|
||||
case "SHADERPASS_FORWARD_ADD":
|
||||
case "SHADERPASS_DEFERRED":
|
||||
AddWorkflowModeControlToPass(ref result, target, subtarget.WorkflowMode);
|
||||
PatchSpecularIncludes(ref result, s_Mappings[item.descriptor.referenceName]);
|
||||
|
||||
var pragmas = new PragmaCollection();
|
||||
foreach (var pragma in result.pragmas)
|
||||
{
|
||||
// For UAVs (RWStructuredBuffer).
|
||||
if (pragma.descriptor.value.StartsWithNoAlloc("target"))
|
||||
{
|
||||
pragmas.Add(Pragma.Target(ShaderModel.Target45));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pragma.descriptor.value.StartsWithNoAlloc("vertex"))
|
||||
{
|
||||
pragmas.Add(Pragma.SkipVariants(s_SkipVariants));
|
||||
}
|
||||
|
||||
pragmas.Add(pragma.descriptor, pragma.fieldConditions);
|
||||
}
|
||||
result.pragmas = pragmas;
|
||||
|
||||
goto default;
|
||||
default:
|
||||
PatchIncludes(ref result);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (item.descriptor.referenceName)
|
||||
{
|
||||
case "SHADERPASS_FORWARD":
|
||||
case "SHADERPASS_FORWARD_ADD":
|
||||
AddReceivesShadowsControlToPass(ref result, target, subtarget.TransparentReceiveShadows);
|
||||
break;
|
||||
case "SHADERPASS_SHADOWCASTER":
|
||||
var states = new RenderStateCollection();
|
||||
foreach (var state in result.renderStates)
|
||||
{
|
||||
if (state.descriptor.type == RenderStateType.ZTest)
|
||||
{
|
||||
states.Add(RenderState.ZTest($"[{k_ShadowCasterZTest}]"));
|
||||
continue;
|
||||
}
|
||||
|
||||
states.Add(state.descriptor, state.fieldConditions);
|
||||
}
|
||||
|
||||
result.renderStates = states;
|
||||
break;
|
||||
}
|
||||
|
||||
// Add missing cull render state.
|
||||
if (item.descriptor.referenceName == "SHADERPASS_FORWARD_ADD")
|
||||
{
|
||||
CoreRenderStates.AddUberSwitchedCull(target, result.renderStates);
|
||||
}
|
||||
|
||||
// Inject MV before DO pass.
|
||||
if (item.descriptor.referenceName == "SHADERPASS_DEPTHONLY")
|
||||
{
|
||||
var mv = LitPasses.MotionVectors(target);
|
||||
PatchIncludes(ref mv);
|
||||
passes.Add(mv);
|
||||
}
|
||||
|
||||
// Fix XR SPI.
|
||||
if (result.requiredFields != null)
|
||||
{
|
||||
var found = false;
|
||||
|
||||
foreach (var collection in result.requiredFields)
|
||||
{
|
||||
if (collection.field == StructFields.Attributes.instanceID)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
result.requiredFields.Add(StructFields.Attributes.instanceID);
|
||||
}
|
||||
}
|
||||
|
||||
passes.Add(result);
|
||||
}
|
||||
|
||||
ssd.passes = passes;
|
||||
|
||||
return ssd;
|
||||
}
|
||||
|
||||
static void AddWorkflowModeControlToPass(ref PassDescriptor pass, BuiltInTarget target, WorkflowMode workflowMode)
|
||||
{
|
||||
if (target.allowMaterialOverride)
|
||||
{
|
||||
pass.keywords.Add(LitDefines.s_SpecularSetup);
|
||||
}
|
||||
else if (workflowMode == WorkflowMode.Specular)
|
||||
{
|
||||
pass.defines.Add(LitDefines.s_SpecularSetup, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void AddReceivesShadowsControlToPass(ref PassDescriptor pass, BuiltInTarget target, bool receives)
|
||||
{
|
||||
if (target.allowMaterialOverride)
|
||||
{
|
||||
pass.keywords.Add(LitDefines.s_TransparentReceivesShadows);
|
||||
pass.keywords.Add(LitDefines.s_ShadowsSingleCascade);
|
||||
pass.keywords.Add(LitDefines.s_ShadowsSplitSpheres);
|
||||
pass.keywords.Add(LitDefines.s_ShadowsSoft);
|
||||
}
|
||||
else if (receives)
|
||||
{
|
||||
pass.defines.Add(LitDefines.s_TransparentReceivesShadows, 1);
|
||||
pass.keywords.Add(LitDefines.s_ShadowsSingleCascade);
|
||||
pass.keywords.Add(LitDefines.s_ShadowsSplitSpheres);
|
||||
pass.keywords.Add(LitDefines.s_ShadowsSoft);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class LitPasses
|
||||
{
|
||||
static readonly string s_ShaderPathMotionVectorCommon = $"{k_ShaderPath}/MotionVectorCommon.hlsl";
|
||||
static readonly string s_ShaderPathMotionVectorPass = $"{k_ShaderPath}/MotionVectorPass.hlsl";
|
||||
|
||||
public static RenderStateDescriptor UberSwitchedCullRenderState(BuiltInTarget target)
|
||||
{
|
||||
if (target.allowMaterialOverride)
|
||||
{
|
||||
return RenderState.Cull(CoreRenderStates.Uniforms.cullMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
return RenderState.Cull(CoreRenderStates.RenderFaceToCull(target.renderFace));
|
||||
}
|
||||
}
|
||||
|
||||
public static PassDescriptor MotionVectors(BuiltInTarget target)
|
||||
{
|
||||
var result = new PassDescriptor()
|
||||
{
|
||||
// Definition
|
||||
displayName = "BuiltIn MotionVectors",
|
||||
referenceName = "SHADERPASS_MOTION_VECTORS",
|
||||
lightMode = "MotionVectors",
|
||||
useInPreview = false,
|
||||
|
||||
// Template
|
||||
passTemplatePath = BuiltInTarget.kTemplatePath,
|
||||
sharedTemplateDirectories = BuiltInTarget.kSharedTemplateDirectories.Union
|
||||
(
|
||||
new string[]
|
||||
{
|
||||
k_TemplatePath,
|
||||
"Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/Editor/ShaderGraph"
|
||||
}
|
||||
).ToArray(),
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = new BlockFieldDescriptor[]
|
||||
{
|
||||
BlockFields.VertexDescription.Position,
|
||||
},
|
||||
validPixelBlocks = CoreBlockMasks.FragmentAlphaOnly,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
requiredFields = new()
|
||||
{
|
||||
// Needed for XR, but not sure if correct.
|
||||
StructFields.Attributes.instanceID,
|
||||
},
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = new()
|
||||
{
|
||||
{ RenderState.ZTest(ZTest.LEqual) },
|
||||
{ RenderState.ZWrite(ZWrite.On) },
|
||||
{ UberSwitchedCullRenderState(target) },
|
||||
// MVs write to the depth buffer causing z-fighting. Luckily, the depth texture has
|
||||
// already been updated, and will not be updated before water renders.
|
||||
{ RenderState.ColorMask("ColorMask RG\nOffset 1, 1") },
|
||||
},
|
||||
|
||||
pragmas = new()
|
||||
{
|
||||
{ Pragma.Target(ShaderModel.Target35) }, // NOTE: SM 2.0 only GL
|
||||
{ Pragma.MultiCompileInstancing },
|
||||
{ Pragma.Vertex("vert") },
|
||||
{ Pragma.Fragment("frag") },
|
||||
},
|
||||
|
||||
defines = new() { CoreDefines.BuiltInTargetAPI },
|
||||
keywords = new(),
|
||||
includes = new()
|
||||
{
|
||||
// Pre-graph
|
||||
{ CoreIncludes.CorePregraph },
|
||||
{ CoreIncludes.ShaderGraphPregraph },
|
||||
|
||||
// Post-graph
|
||||
{ s_ShaderPathMotionVectorCommon, IncludeLocation.Postgraph },
|
||||
{ CoreIncludes.CorePostgraph },
|
||||
{ s_ShaderPathMotionVectorPass, IncludeLocation.Postgraph },
|
||||
},
|
||||
|
||||
// Custom Interpolator Support
|
||||
customInterpolators = CoreCustomInterpDescriptors.Common,
|
||||
};
|
||||
|
||||
// Only support time for now.
|
||||
result.defines.Add(LitDefines.s_AutomaticTimeBasedMotionVectors, 1);
|
||||
|
||||
CorePasses.AddAlphaClipControlToPass(ref result, target);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
internal static class LitDefines
|
||||
{
|
||||
public static readonly KeywordDescriptor s_AutomaticTimeBasedMotionVectors = new()
|
||||
{
|
||||
displayName = "Automatic Time-Based Motion Vectors",
|
||||
referenceName = "AUTOMATIC_TIME_BASED_MOTION_VECTORS",
|
||||
type = KeywordType.Boolean,
|
||||
definition = KeywordDefinition.Predefined,
|
||||
scope = KeywordScope.Local,
|
||||
stages = KeywordShaderStage.Vertex,
|
||||
};
|
||||
|
||||
public static readonly KeywordDescriptor s_SpecularSetup = new()
|
||||
{
|
||||
displayName = "Specular Setup",
|
||||
referenceName = "_BUILTIN_SPECULAR_SETUP",
|
||||
type = KeywordType.Boolean,
|
||||
definition = KeywordDefinition.ShaderFeature,
|
||||
scope = KeywordScope.Local,
|
||||
stages = KeywordShaderStage.Fragment
|
||||
};
|
||||
|
||||
public static readonly KeywordDescriptor s_TransparentReceivesShadows = new()
|
||||
{
|
||||
displayName = "Transparent Receives Shadows",
|
||||
referenceName = "_BUILTIN_TRANSPARENT_RECEIVES_SHADOWS",
|
||||
type = KeywordType.Boolean,
|
||||
definition = KeywordDefinition.ShaderFeature,
|
||||
scope = KeywordScope.Local,
|
||||
stages = KeywordShaderStage.Fragment
|
||||
};
|
||||
|
||||
public static readonly KeywordDescriptor s_ShadowsSingleCascade = new()
|
||||
{
|
||||
displayName = "Single Cascade Shadows",
|
||||
referenceName = "SHADOWS_SINGLE_CASCADE",
|
||||
type = KeywordType.Boolean,
|
||||
definition = KeywordDefinition.MultiCompile,
|
||||
scope = KeywordScope.Global,
|
||||
stages = KeywordShaderStage.All,
|
||||
};
|
||||
|
||||
public static readonly KeywordDescriptor s_ShadowsSoft = new()
|
||||
{
|
||||
displayName = "Soft Shadows",
|
||||
referenceName = "SHADOWS_SOFT",
|
||||
type = KeywordType.Boolean,
|
||||
definition = KeywordDefinition.MultiCompile,
|
||||
scope = KeywordScope.Global,
|
||||
stages = KeywordShaderStage.All,
|
||||
};
|
||||
|
||||
public static readonly KeywordDescriptor s_ShadowsSplitSpheres = new()
|
||||
{
|
||||
displayName = "Stable Fit Shadows",
|
||||
referenceName = "SHADOWS_SPLIT_SPHERES",
|
||||
type = KeywordType.Boolean,
|
||||
definition = KeywordDefinition.MultiCompile,
|
||||
scope = KeywordScope.Global,
|
||||
stages = KeywordShaderStage.All,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user