UnityGame/Library/PackageCache/com.unity.render-pipelines.universal/Editor/ShaderGraph/Targets/UniversalTarget.cs
2024-10-27 10:53:47 +03:00

2315 lines
88 KiB
C#

using System;
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.UIElements;
using UnityEditor.ShaderGraph;
using UnityEditor.ShaderGraph.Internal;
using UnityEditor.UIElements;
using UnityEditor.ShaderGraph.Serialization;
using UnityEditor.ShaderGraph.Legacy;
#if HAS_VFX_GRAPH
using UnityEditor.VFX;
#endif
namespace UnityEditor.Rendering.Universal.ShaderGraph
{
/// <summary>
/// Options for the material type.
/// </summary>
public enum MaterialType
{
/// <summary>
/// Use this for URP lit.
/// </summary>
Lit,
/// <summary>
/// Use this for URP unlit.
/// </summary>
Unlit,
/// <summary>
/// Use this for sprite lit.
/// </summary>
SpriteLit,
/// <summary>
/// Use this for Sprite unlit.
/// </summary>
SpriteUnlit,
}
/// <summary>
/// Workflow modes for the shader.
/// </summary>
public enum WorkflowMode
{
/// <summary>
/// Use this for specular workflow.
/// </summary>
Specular,
/// <summary>
/// Use this for metallic workflow.
/// </summary>
Metallic,
}
enum SurfaceType
{
Opaque,
Transparent,
}
enum ZWriteControl
{
Auto = 0,
ForceEnabled = 1,
ForceDisabled = 2
}
enum ZTestMode // the values here match UnityEngine.Rendering.CompareFunction
{
Disabled = 0,
Never = 1,
Less = 2,
Equal = 3,
LEqual = 4, // default for most rendering
Greater = 5,
NotEqual = 6,
GEqual = 7,
Always = 8,
}
enum AlphaMode
{
Alpha,
Premultiply,
Additive,
Multiply,
}
internal enum RenderFace
{
Front = 2, // = CullMode.Back -- render front face only
Back = 1, // = CullMode.Front -- render back face only
Both = 0 // = CullMode.Off -- render both faces
}
internal enum AdditionalMotionVectorMode
{
None,
TimeBased,
Custom
}
sealed class UniversalTarget : Target, IHasMetadata, ILegacyTarget, IMaySupportVFX
#if HAS_VFX_GRAPH
, IRequireVFXContext
#endif
{
public override int latestVersion => 1;
// Constants
static readonly GUID kSourceCodeGuid = new GUID("8c72f47fdde33b14a9340e325ce56f4d"); // UniversalTarget.cs
public const string kPipelineTag = "UniversalPipeline";
public const string kComplexLitMaterialTypeTag = "\"UniversalMaterialType\" = \"ComplexLit\"";
public const string kLitMaterialTypeTag = "\"UniversalMaterialType\" = \"Lit\"";
public const string kUnlitMaterialTypeTag = "\"UniversalMaterialType\" = \"Unlit\"";
public const string kAlwaysRenderMotionVectorsTag = "\"AlwaysRenderMotionVectors\" = \"true\"";
public static readonly string[] kSharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories().Union(new string[]
{
"Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Templates"
#if HAS_VFX_GRAPH
, "Packages/com.unity.visualeffectgraph/Editor/ShaderGraph/Templates"
#endif
}).ToArray();
public const string kUberTemplatePath = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Templates/ShaderPass.template";
// SubTarget
List<SubTarget> m_SubTargets;
List<string> m_SubTargetNames;
int activeSubTargetIndex => m_SubTargets.IndexOf(m_ActiveSubTarget);
// Subtarget Data
[SerializeField]
List<JsonData<JsonObject>> m_Datas = new List<JsonData<JsonObject>>();
// View
PopupField<string> m_SubTargetField;
TextField m_CustomGUIField;
#if HAS_VFX_GRAPH
Toggle m_SupportVFXToggle;
#endif
[SerializeField]
JsonData<SubTarget> m_ActiveSubTarget;
// when checked, allows the material to control ALL surface settings (uber shader style)
[SerializeField]
bool m_AllowMaterialOverride = false;
[SerializeField]
SurfaceType m_SurfaceType = SurfaceType.Opaque;
[SerializeField]
ZTestMode m_ZTestMode = ZTestMode.LEqual;
[SerializeField]
ZWriteControl m_ZWriteControl = ZWriteControl.Auto;
[SerializeField]
AlphaMode m_AlphaMode = AlphaMode.Alpha;
[SerializeField]
RenderFace m_RenderFace = RenderFace.Front;
[SerializeField]
bool m_AlphaClip = false;
[SerializeField]
bool m_CastShadows = true;
[SerializeField]
bool m_ReceiveShadows = true;
[SerializeField]
bool m_DisableTint = false;
[SerializeField]
AdditionalMotionVectorMode m_AdditionalMotionVectorMode = AdditionalMotionVectorMode.None;
[SerializeField]
bool m_AlembicMotionVectors = false;
[SerializeField]
bool m_SupportsLODCrossFade = false;
[SerializeField]
string m_CustomEditorGUI;
[SerializeField]
bool m_SupportVFX;
internal override bool ignoreCustomInterpolators => m_ActiveSubTarget.value is UniversalCanvasSubTarget;
internal override int padCustomInterpolatorLimit => 4;
internal override bool prefersSpritePreview =>
activeSubTarget is UniversalSpriteUnlitSubTarget or UniversalSpriteLitSubTarget or
UniversalSpriteCustomLitSubTarget or UniversalCanvasSubTarget;
public UniversalTarget()
{
displayName = "Universal";
m_SubTargets = TargetUtils.GetSubTargets(this);
m_SubTargetNames = m_SubTargets.Select(x => x.displayName).ToList();
TargetUtils.ProcessSubTargetList(ref m_ActiveSubTarget, ref m_SubTargets);
ProcessSubTargetDatas(m_ActiveSubTarget.value);
}
public string renderType
{
get
{
if (surfaceType == SurfaceType.Transparent)
return $"{RenderType.Transparent}";
else
return $"{RenderType.Opaque}";
}
}
// this sets up the default renderQueue -- but it can be overridden by ResetMaterialKeywords()
public string renderQueue
{
get
{
if (surfaceType == SurfaceType.Transparent)
return $"{UnityEditor.ShaderGraph.RenderQueue.Transparent}";
else if (alphaClip)
return $"{UnityEditor.ShaderGraph.RenderQueue.AlphaTest}";
else
return $"{UnityEditor.ShaderGraph.RenderQueue.Geometry}";
}
}
public string disableBatching
{
get
{
if (supportsLodCrossFade)
return $"{UnityEditor.ShaderGraph.DisableBatching.LODFading}";
else
return $"{UnityEditor.ShaderGraph.DisableBatching.False}";
}
}
public SubTarget activeSubTarget
{
get => m_ActiveSubTarget.value;
set => m_ActiveSubTarget = value;
}
public bool allowMaterialOverride
{
get => m_AllowMaterialOverride;
set => m_AllowMaterialOverride = value;
}
public SurfaceType surfaceType
{
get => m_SurfaceType;
set => m_SurfaceType = value;
}
public ZWriteControl zWriteControl
{
get => m_ZWriteControl;
set => m_ZWriteControl = value;
}
public ZTestMode zTestMode
{
get => m_ZTestMode;
set => m_ZTestMode = value;
}
public AlphaMode alphaMode
{
get => m_AlphaMode;
set => m_AlphaMode = value;
}
public RenderFace renderFace
{
get => m_RenderFace;
set => m_RenderFace = value;
}
public bool alphaClip
{
get => m_AlphaClip;
set => m_AlphaClip = value;
}
public bool disableTint
{
get => m_DisableTint;
set => m_DisableTint = value;
}
public bool castShadows
{
get => m_CastShadows;
set => m_CastShadows = value;
}
public bool receiveShadows
{
get => m_ReceiveShadows;
set => m_ReceiveShadows = value;
}
public AdditionalMotionVectorMode additionalMotionVectorMode
{
get => m_AdditionalMotionVectorMode;
set => m_AdditionalMotionVectorMode = value;
}
public bool alembicMotionVectors
{
get => m_AlembicMotionVectors;
set => m_AlembicMotionVectors = value;
}
public bool alwaysRenderMotionVectors
{
get => additionalMotionVectorMode != AdditionalMotionVectorMode.None || alembicMotionVectors;
}
public bool supportsLodCrossFade
{
get => m_SupportsLODCrossFade;
set => m_SupportsLODCrossFade = value;
}
public string customEditorGUI
{
get => m_CustomEditorGUI;
set => m_CustomEditorGUI = value;
}
// generally used to know if we need to build a depth pass
public bool mayWriteDepth
{
get
{
if (allowMaterialOverride)
{
// material may or may not choose to write depth... we should create the depth pass
return true;
}
else
{
switch (zWriteControl)
{
case ZWriteControl.Auto:
return (surfaceType == SurfaceType.Opaque);
case ZWriteControl.ForceDisabled:
return false;
default:
return true;
}
}
}
}
public override bool IsActive()
{
bool isUniversalRenderPipeline = GraphicsSettings.currentRenderPipeline is UniversalRenderPipelineAsset;
return isUniversalRenderPipeline && activeSubTarget.IsActive();
}
public override bool IsNodeAllowedByTarget(Type nodeType)
{
SRPFilterAttribute srpFilter = NodeClassCache.GetAttributeOnNodeType<SRPFilterAttribute>(nodeType);
bool worksWithThisSrp = srpFilter == null || srpFilter.srpTypes.Contains(typeof(UniversalRenderPipeline));
SubTargetFilterAttribute subTargetFilter = NodeClassCache.GetAttributeOnNodeType<SubTargetFilterAttribute>(nodeType);
bool worksWithThisSubTarget = subTargetFilter == null || subTargetFilter.subTargetTypes.Contains(activeSubTarget.GetType());
if (activeSubTarget.IsActive())
worksWithThisSubTarget &= activeSubTarget.IsNodeAllowedBySubTarget(nodeType);
return worksWithThisSrp && worksWithThisSubTarget && base.IsNodeAllowedByTarget(nodeType);
}
public override void Setup(ref TargetSetupContext context)
{
// Setup the Target
context.AddAssetDependency(kSourceCodeGuid, AssetCollection.Flags.SourceDependency);
// Override EditorGUI (replaces the URP material editor by a custom one)
if (!string.IsNullOrEmpty(m_CustomEditorGUI))
context.AddCustomEditorForRenderPipeline(m_CustomEditorGUI, typeof(UniversalRenderPipelineAsset));
// Setup the active SubTarget
TargetUtils.ProcessSubTargetList(ref m_ActiveSubTarget, ref m_SubTargets);
m_ActiveSubTarget.value.target = this;
ProcessSubTargetDatas(m_ActiveSubTarget.value);
m_ActiveSubTarget.value.Setup(ref context);
}
public override void OnAfterMultiDeserialize(string json)
{
TargetUtils.ProcessSubTargetList(ref m_ActiveSubTarget, ref m_SubTargets);
m_ActiveSubTarget.value.target = this;
// OnAfterMultiDeserialize order is not guaranteed to be hierarchical (target->subtarget).
// Update active subTarget (only, since the target is shared and non-active subTargets could override active settings)
// after Target has been deserialized and target <-> subtarget references are intact.
m_ActiveSubTarget.value.OnAfterParentTargetDeserialized();
}
public override void GetFields(ref TargetFieldContext context)
{
var descs = context.blocks.Select(x => x.descriptor);
// Core fields
context.AddField(Fields.GraphVertex, descs.Contains(BlockFields.VertexDescription.Position) ||
descs.Contains(BlockFields.VertexDescription.Normal) ||
descs.Contains(BlockFields.VertexDescription.Tangent));
context.AddField(Fields.GraphPixel);
// SubTarget fields
m_ActiveSubTarget.value.GetFields(ref context);
}
public override void GetActiveBlocks(ref TargetActiveBlockContext context)
{
// Core blocks
bool useCoreBlocks = !(m_ActiveSubTarget.value is UnityEditor.Rendering.Fullscreen.ShaderGraph.FullscreenSubTarget<UniversalTarget> | m_ActiveSubTarget.value is UnityEditor.Rendering.Canvas.ShaderGraph.CanvasSubTarget<UniversalTarget>);
// Core blocks
if (useCoreBlocks)
{
context.AddBlock(BlockFields.VertexDescription.Position);
context.AddBlock(BlockFields.VertexDescription.Normal);
context.AddBlock(BlockFields.VertexDescription.Tangent);
context.AddBlock(BlockFields.SurfaceDescription.BaseColor);
}
// SubTarget blocks
m_ActiveSubTarget.value.GetActiveBlocks(ref context);
}
public override void ProcessPreviewMaterial(Material material)
{
m_ActiveSubTarget.value.ProcessPreviewMaterial(material);
}
public override object saveContext => m_ActiveSubTarget.value?.saveContext;
public override void CollectShaderProperties(PropertyCollector collector, GenerationMode generationMode)
{
base.CollectShaderProperties(collector, generationMode);
activeSubTarget.CollectShaderProperties(collector, generationMode);
collector.AddShaderProperty(LightmappingShaderProperties.kLightmapsArray);
collector.AddShaderProperty(LightmappingShaderProperties.kLightmapsIndirectionArray);
collector.AddShaderProperty(LightmappingShaderProperties.kShadowMasksArray);
collector.AddShaderProperty(MipmapStreamingShaderProperties.kDebugTex);
// SubTarget blocks
m_ActiveSubTarget.value.CollectShaderProperties(collector, generationMode);
}
public override void GetPropertiesGUI(ref TargetPropertyGUIContext context, Action onChange, Action<String> registerUndo)
{
// Core properties
m_SubTargetField = new PopupField<string>(m_SubTargetNames, activeSubTargetIndex);
context.AddProperty("Material", m_SubTargetField, (evt) =>
{
if (Equals(activeSubTargetIndex, m_SubTargetField.index))
return;
registerUndo("Change Material");
m_ActiveSubTarget = m_SubTargets[m_SubTargetField.index];
ProcessSubTargetDatas(m_ActiveSubTarget.value);
onChange();
});
// SubTarget properties
m_ActiveSubTarget.value.GetPropertiesGUI(ref context, onChange, registerUndo);
// Custom Editor GUI
// Requires FocusOutEvent
m_CustomGUIField = new TextField("") { value = customEditorGUI };
m_CustomGUIField.RegisterCallback<FocusOutEvent>(s =>
{
if (Equals(customEditorGUI, m_CustomGUIField.value))
return;
registerUndo("Change Custom Editor GUI");
customEditorGUI = m_CustomGUIField.value;
onChange();
});
context.AddProperty("Custom Editor GUI", m_CustomGUIField, (evt) => { });
#if HAS_VFX_GRAPH
if (m_ActiveSubTarget.value is UniversalSubTarget universalSubTarget && universalSubTarget.target.CanSupportVFX())
{
m_SupportVFXToggle = new Toggle("") { value = m_SupportVFX };
context.AddProperty("Support VFX Graph", m_SupportVFXToggle, (evt) =>
{
m_SupportVFX = m_SupportVFXToggle.value;
});
}
else
{
context.AddHelpBox(MessageType.Info, $"The {m_ActiveSubTarget.value.displayName} target does not support VFX Graph.");
}
#endif
}
// this is a copy of ZTestMode, but hides the "Disabled" option, which is invalid
internal enum ZTestModeForUI
{
Never = 1,
Less = 2,
Equal = 3,
LEqual = 4, // default for most rendering
Greater = 5,
NotEqual = 6,
GEqual = 7,
Always = 8,
};
public void AddDefaultMaterialOverrideGUI(ref TargetPropertyGUIContext context, Action onChange, Action<String> registerUndo)
{
// At some point we may want to convert this to be a per-property control
// or Unify the UX with the upcoming "lock" feature of the Material Variant properties
context.AddProperty("Allow Material Override", new Toggle() { value = allowMaterialOverride }, (evt) =>
{
if (Equals(allowMaterialOverride, evt.newValue))
return;
registerUndo("Change Allow Material Override");
allowMaterialOverride = evt.newValue;
onChange();
});
}
public void AddDefaultSurfacePropertiesGUI(ref TargetPropertyGUIContext context, Action onChange, Action<String> registerUndo, bool showReceiveShadows)
{
context.AddProperty("Surface Type", new EnumField(SurfaceType.Opaque) { value = surfaceType }, (evt) =>
{
if (Equals(surfaceType, evt.newValue))
return;
registerUndo("Change Surface");
surfaceType = (SurfaceType)evt.newValue;
onChange();
});
context.AddProperty("Blending Mode", new EnumField(AlphaMode.Alpha) { value = alphaMode }, surfaceType == SurfaceType.Transparent, (evt) =>
{
if (Equals(alphaMode, evt.newValue))
return;
registerUndo("Change Blend");
alphaMode = (AlphaMode)evt.newValue;
onChange();
});
context.AddProperty("Render Face", new EnumField(RenderFace.Front) { value = renderFace }, (evt) =>
{
if (Equals(renderFace, evt.newValue))
return;
registerUndo("Change Render Face");
renderFace = (RenderFace)evt.newValue;
onChange();
});
context.AddProperty("Depth Write", new EnumField(ZWriteControl.Auto) { value = zWriteControl }, (evt) =>
{
if (Equals(zWriteControl, evt.newValue))
return;
registerUndo("Change Depth Write Control");
zWriteControl = (ZWriteControl)evt.newValue;
onChange();
});
context.AddProperty("Depth Test", new EnumField(ZTestModeForUI.LEqual) { value = (ZTestModeForUI)zTestMode }, (evt) =>
{
if (Equals(zTestMode, evt.newValue))
return;
registerUndo("Change Depth Test");
zTestMode = (ZTestMode)evt.newValue;
onChange();
});
context.AddProperty("Alpha Clipping", "Avoid using when Alpha and AlphaThreshold are constant for the entire material as enabling in this case could introduce visual artifacts and will add an unnecessary performance cost when used with MSAA (due to AlphaToMask)", 0, new Toggle() { value = alphaClip }, (evt) =>
{
if (Equals(alphaClip, evt.newValue))
return;
registerUndo("Change Alpha Clip");
alphaClip = evt.newValue;
onChange();
});
context.AddProperty("Cast Shadows", new Toggle() { value = castShadows }, (evt) =>
{
if (Equals(castShadows, evt.newValue))
return;
registerUndo("Change Cast Shadows");
castShadows = evt.newValue;
onChange();
});
if (showReceiveShadows)
context.AddProperty("Receive Shadows", new Toggle() { value = receiveShadows }, (evt) =>
{
if (Equals(receiveShadows, evt.newValue))
return;
registerUndo("Change Receive Shadows");
receiveShadows = evt.newValue;
onChange();
});
context.AddProperty("Supports LOD Cross Fade", new Toggle() { value = supportsLodCrossFade }, (evt) =>
{
if (Equals(supportsLodCrossFade, evt.newValue))
return;
registerUndo("Change Supports LOD Cross Fade");
supportsLodCrossFade = evt.newValue;
onChange();
});
context.AddProperty("Additional Motion Vectors", "Specifies how motion vectors for local Shader Graph position modifications are handled (on top of camera, transform, skeletal and Alembic motion vectors).", 0, new EnumField(AdditionalMotionVectorMode.None) { value = additionalMotionVectorMode }, (evt) =>
{
if (Equals(additionalMotionVectorMode, evt.newValue))
return;
registerUndo("Change Additional Motion Vectors");
additionalMotionVectorMode = (AdditionalMotionVectorMode)evt.newValue;
onChange();
});
context.AddProperty(EditorUtils.Styles.alembicMotionVectors.text, EditorUtils.Styles.alembicMotionVectors.tooltip, 0, new Toggle() {value = alembicMotionVectors}, (evt) =>
{
if (Equals(alembicMotionVectors, evt.newValue))
return;
registerUndo("Change Alembic Motion Vectors");
alembicMotionVectors = evt.newValue;
onChange();
});
}
public bool TrySetActiveSubTarget(Type subTargetType)
{
if (!subTargetType.IsSubclassOf(typeof(SubTarget)))
return false;
foreach (var subTarget in m_SubTargets)
{
if (subTarget.GetType().Equals(subTargetType))
{
m_ActiveSubTarget = subTarget;
ProcessSubTargetDatas(m_ActiveSubTarget);
return true;
}
}
return false;
}
void ProcessSubTargetDatas(SubTarget subTarget)
{
var typeCollection = TypeCache.GetTypesDerivedFrom<JsonObject>();
foreach (var type in typeCollection)
{
if (type.IsGenericType)
continue;
// Data requirement interfaces need generic type arguments
// Therefore we need to use reflections to call the method
var methodInfo = typeof(UniversalTarget).GetMethod(nameof(SetDataOnSubTarget));
var genericMethodInfo = methodInfo.MakeGenericMethod(type);
genericMethodInfo.Invoke(this, new object[] { subTarget });
}
}
void ClearUnusedData()
{
for (int i = 0; i < m_Datas.Count; i++)
{
var data = m_Datas[i];
if (data.value is null)
continue;
var type = data.value.GetType();
// Data requirement interfaces need generic type arguments
// Therefore we need to use reflections to call the method
var methodInfo = typeof(UniversalTarget).GetMethod(nameof(ValidateDataForSubTarget));
var genericMethodInfo = methodInfo.MakeGenericMethod(type);
genericMethodInfo.Invoke(this, new object[] { m_ActiveSubTarget.value, data.value });
}
}
public void SetDataOnSubTarget<T>(SubTarget subTarget) where T : JsonObject
{
if (!(subTarget is IRequiresData<T> requiresData))
return;
// Ensure data object exists in list
T data = null;
foreach (var x in m_Datas.SelectValue())
{
if (x is T y)
{
data = y;
break;
}
}
if (data == null)
{
data = Activator.CreateInstance(typeof(T)) as T;
m_Datas.Add(data);
}
// Apply data object to SubTarget
requiresData.data = data;
}
public void ValidateDataForSubTarget<T>(SubTarget subTarget, T data) where T : JsonObject
{
if (!(subTarget is IRequiresData<T> requiresData))
{
m_Datas.Remove(data);
}
}
public override void OnBeforeSerialize()
{
ClearUnusedData();
}
public bool TryUpgradeFromMasterNode(IMasterNode1 masterNode, out Dictionary<BlockFieldDescriptor, int> blockMap)
{
void UpgradeAlphaClip()
{
var clipThresholdId = 8;
var node = masterNode as AbstractMaterialNode;
var clipThresholdSlot = node.FindSlot<Vector1MaterialSlot>(clipThresholdId);
if (clipThresholdSlot == null)
return;
clipThresholdSlot.owner = node;
if (clipThresholdSlot.isConnected || clipThresholdSlot.value > 0.0f)
{
m_AlphaClip = true;
}
}
// Upgrade Target
allowMaterialOverride = false;
switch (masterNode)
{
case PBRMasterNode1 pbrMasterNode:
m_SurfaceType = (SurfaceType)pbrMasterNode.m_SurfaceType;
m_AlphaMode = (AlphaMode)pbrMasterNode.m_AlphaMode;
m_RenderFace = pbrMasterNode.m_TwoSided ? RenderFace.Both : RenderFace.Front;
UpgradeAlphaClip();
m_CustomEditorGUI = pbrMasterNode.m_OverrideEnabled ? pbrMasterNode.m_ShaderGUIOverride : "";
break;
case UnlitMasterNode1 unlitMasterNode:
m_SurfaceType = (SurfaceType)unlitMasterNode.m_SurfaceType;
m_AlphaMode = (AlphaMode)unlitMasterNode.m_AlphaMode;
m_RenderFace = unlitMasterNode.m_TwoSided ? RenderFace.Both : RenderFace.Front;
UpgradeAlphaClip();
m_CustomEditorGUI = unlitMasterNode.m_OverrideEnabled ? unlitMasterNode.m_ShaderGUIOverride : "";
break;
case SpriteLitMasterNode1 spriteLitMasterNode:
m_CustomEditorGUI = spriteLitMasterNode.m_OverrideEnabled ? spriteLitMasterNode.m_ShaderGUIOverride : "";
break;
case SpriteUnlitMasterNode1 spriteUnlitMasterNode:
m_CustomEditorGUI = spriteUnlitMasterNode.m_OverrideEnabled ? spriteUnlitMasterNode.m_ShaderGUIOverride : "";
break;
}
// Upgrade SubTarget
foreach (var subTarget in m_SubTargets)
{
if (!(subTarget is ILegacyTarget legacySubTarget))
continue;
if (legacySubTarget.TryUpgradeFromMasterNode(masterNode, out blockMap))
{
m_ActiveSubTarget = subTarget;
return true;
}
}
blockMap = null;
return false;
}
public override bool WorksWithSRP(RenderPipelineAsset scriptableRenderPipeline)
{
return scriptableRenderPipeline?.GetType() == typeof(UniversalRenderPipelineAsset);
}
#if HAS_VFX_GRAPH
public void ConfigureContextData(VFXContext context, VFXTaskCompiledData data)
{
if (!(m_ActiveSubTarget.value is IRequireVFXContext vfxSubtarget))
return;
vfxSubtarget.ConfigureContextData(context, data);
}
#endif
public bool CanSupportVFX()
{
if (m_ActiveSubTarget.value == null)
return false;
if (m_ActiveSubTarget.value is UniversalUnlitSubTarget)
return true;
if (m_ActiveSubTarget.value is UniversalSixWaySubTarget)
return true;
if (m_ActiveSubTarget.value is UniversalLitSubTarget)
return true;
if (m_ActiveSubTarget.value is UniversalSpriteLitSubTarget)
return true;
if (m_ActiveSubTarget.value is UniversalSpriteUnlitSubTarget)
return true;
if (m_ActiveSubTarget.value is UniversalSpriteCustomLitSubTarget)
return true;
//It excludes:
// - UniversalDecalSubTarget
return false;
}
public bool SupportsVFX() => CanSupportVFX() && m_SupportVFX;
[Serializable]
class UniversalTargetLegacySerialization
{
[SerializeField]
public bool m_TwoSided = false;
}
public override void OnAfterDeserialize(string json)
{
base.OnAfterDeserialize(json);
if (this.sgVersion < latestVersion)
{
if (this.sgVersion == 0)
{
// deserialize the old settings to upgrade
var oldSettings = JsonUtility.FromJson<UniversalTargetLegacySerialization>(json);
this.m_RenderFace = oldSettings.m_TwoSided ? RenderFace.Both : RenderFace.Front;
}
ChangeVersion(latestVersion);
}
}
#region Metadata
string IHasMetadata.identifier
{
get
{
// defer to subtarget
if (m_ActiveSubTarget.value is IHasMetadata subTargetHasMetaData)
return subTargetHasMetaData.identifier;
return null;
}
}
ScriptableObject IHasMetadata.GetMetadataObject(GraphDataReadOnly graph)
{
// defer to subtarget
if (m_ActiveSubTarget.value is IHasMetadata subTargetHasMetaData)
return subTargetHasMetaData.GetMetadataObject(graph);
return null;
}
#endregion
}
#region Passes
static class CorePasses
{
/// <summary>
/// Automatically enables Alpha-To-Coverage in the provided opaque pass targets using alpha clipping
/// </summary>
/// <param name="pass">The pass to modify</param>
/// <param name="target">The target to query</param>
internal static void AddAlphaToMaskControlToPass(ref PassDescriptor pass, UniversalTarget target)
{
if (target.allowMaterialOverride)
{
// When material overrides are allowed, we have to rely on the _AlphaToMask material property since we can't be
// sure of the surface type and alpha clip state based on the target alone.
pass.renderStates.Add(RenderState.AlphaToMask("[_AlphaToMask]"));
}
else if (target.alphaClip && (target.surfaceType == SurfaceType.Opaque))
{
pass.renderStates.Add(RenderState.AlphaToMask("On"));
}
}
internal static void AddAlphaClipControlToPass(ref PassDescriptor pass, UniversalTarget target)
{
if (target.allowMaterialOverride)
pass.keywords.Add(CoreKeywordDescriptors.AlphaTestOn);
else if (target.alphaClip)
pass.defines.Add(CoreKeywordDescriptors.AlphaTestOn, 1);
}
internal static void AddLODCrossFadeControlToPass(ref PassDescriptor pass, UniversalTarget target)
{
if (target.supportsLodCrossFade)
{
pass.includes.Add(CoreIncludes.LODCrossFade);
pass.keywords.Add(CoreKeywordDescriptors.LODFadeCrossFade);
pass.defines.Add(CoreKeywordDescriptors.UseUnityCrossFade, 1);
}
}
internal static void AddTargetSurfaceControlsToPass(ref PassDescriptor pass, UniversalTarget target, bool blendModePreserveSpecular = false)
{
// the surface settings can either be material controlled or target controlled
if (target.allowMaterialOverride)
{
// setup material control of via keyword
pass.keywords.Add(CoreKeywordDescriptors.SurfaceTypeTransparent);
pass.keywords.Add(CoreKeywordDescriptors.AlphaPremultiplyOn);
pass.keywords.Add(CoreKeywordDescriptors.AlphaModulateOn);
}
else
{
// setup target control via define
if (target.surfaceType == SurfaceType.Transparent)
{
pass.defines.Add(CoreKeywordDescriptors.SurfaceTypeTransparent, 1);
// alpha premultiply in shader only needed when alpha is different for diffuse & specular
if ((target.alphaMode == AlphaMode.Alpha || target.alphaMode == AlphaMode.Additive) && blendModePreserveSpecular)
pass.defines.Add(CoreKeywordDescriptors.AlphaPremultiplyOn, 1);
else if (target.alphaMode == AlphaMode.Multiply)
pass.defines.Add(CoreKeywordDescriptors.AlphaModulateOn, 1);
}
}
AddAlphaClipControlToPass(ref pass, target);
}
// used by lit/unlit subtargets
public static PassDescriptor DepthOnly(UniversalTarget target)
{
var result = new PassDescriptor()
{
// Definition
displayName = "DepthOnly",
referenceName = "SHADERPASS_DEPTHONLY",
lightMode = "DepthOnly",
useInPreview = true,
// Template
passTemplatePath = UniversalTarget.kUberTemplatePath,
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
// Port Mask
validVertexBlocks = CoreBlockMasks.Vertex,
validPixelBlocks = CoreBlockMasks.FragmentAlphaOnly,
// Fields
structs = CoreStructCollections.Default,
fieldDependencies = CoreFieldDependencies.Default,
// Conditional State
renderStates = CoreRenderStates.DepthOnly(target),
pragmas = CorePragmas.Instanced,
defines = new DefineCollection(),
keywords = new KeywordCollection(),
includes = new IncludeCollection { CoreIncludes.DepthOnly },
// Custom Interpolator Support
customInterpolators = CoreCustomInterpDescriptors.Common
};
AddAlphaClipControlToPass(ref result, target);
AddLODCrossFadeControlToPass(ref result, target);
return result;
}
// used by lit/unlit subtargets
public static PassDescriptor DepthNormal(UniversalTarget target)
{
var result = new PassDescriptor()
{
// Definition
displayName = "DepthNormals",
referenceName = "SHADERPASS_DEPTHNORMALS",
lightMode = "DepthNormals",
useInPreview = true,
// Template
passTemplatePath = UniversalTarget.kUberTemplatePath,
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
// Port Mask
validVertexBlocks = CoreBlockMasks.Vertex,
validPixelBlocks = CoreBlockMasks.FragmentDepthNormals,
// Fields
structs = CoreStructCollections.Default,
requiredFields = CoreRequiredFields.DepthNormals,
fieldDependencies = CoreFieldDependencies.Default,
// Conditional State
renderStates = CoreRenderStates.DepthNormalsOnly(target),
pragmas = CorePragmas.Instanced,
defines = new DefineCollection(),
keywords = new KeywordCollection(),
includes = new IncludeCollection { CoreIncludes.DepthNormalsOnly },
// Custom Interpolator Support
customInterpolators = CoreCustomInterpDescriptors.Common
};
AddAlphaClipControlToPass(ref result, target);
AddLODCrossFadeControlToPass(ref result, target);
return result;
}
// used by lit/unlit subtargets
public static PassDescriptor DepthNormalOnly(UniversalTarget target)
{
var result = new PassDescriptor()
{
// Definition
displayName = "DepthNormalsOnly",
referenceName = "SHADERPASS_DEPTHNORMALSONLY",
lightMode = "DepthNormalsOnly",
useInPreview = true,
// Template
passTemplatePath = UniversalTarget.kUberTemplatePath,
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
// Port Mask
validVertexBlocks = CoreBlockMasks.Vertex,
validPixelBlocks = CoreBlockMasks.FragmentDepthNormals,
// Fields
structs = CoreStructCollections.Default,
requiredFields = CoreRequiredFields.DepthNormals,
fieldDependencies = CoreFieldDependencies.Default,
// Conditional State
renderStates = CoreRenderStates.DepthNormalsOnly(target),
pragmas = CorePragmas.Instanced,
defines = new DefineCollection(),
keywords = new KeywordCollection { CoreKeywordDescriptors.GBufferNormalsOct },
includes = new IncludeCollection { CoreIncludes.DepthNormalsOnly },
// Custom Interpolator Support
customInterpolators = CoreCustomInterpDescriptors.Common
};
AddAlphaClipControlToPass(ref result, target);
AddLODCrossFadeControlToPass(ref result, target);
return result;
}
// used by lit/unlit targets
public static PassDescriptor ShadowCaster(UniversalTarget target)
{
var result = new PassDescriptor()
{
// Definition
displayName = "ShadowCaster",
referenceName = "SHADERPASS_SHADOWCASTER",
lightMode = "ShadowCaster",
// Template
passTemplatePath = UniversalTarget.kUberTemplatePath,
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
// Port Mask
validVertexBlocks = CoreBlockMasks.Vertex,
validPixelBlocks = CoreBlockMasks.FragmentAlphaOnly,
// Fields
structs = CoreStructCollections.Default,
requiredFields = CoreRequiredFields.ShadowCaster,
fieldDependencies = CoreFieldDependencies.Default,
// Conditional State
renderStates = CoreRenderStates.ShadowCaster(target),
pragmas = CorePragmas.Instanced,
defines = new DefineCollection(),
keywords = new KeywordCollection { CoreKeywords.ShadowCaster },
includes = new IncludeCollection { CoreIncludes.ShadowCaster },
// Custom Interpolator Support
customInterpolators = CoreCustomInterpDescriptors.Common
};
AddAlphaClipControlToPass(ref result, target);
AddLODCrossFadeControlToPass(ref result, target);
return result;
}
public static PassDescriptor MotionVectors(UniversalTarget target)
{
var result = new PassDescriptor()
{
// Definition
displayName = "MotionVectors",
referenceName = "SHADERPASS_MOTION_VECTORS",
lightMode = "MotionVectors",
useInPreview = false,
// Template
passTemplatePath = UniversalTarget.kUberTemplatePath,
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
// Port Mask
validVertexBlocks = target.additionalMotionVectorMode == AdditionalMotionVectorMode.Custom ? CoreBlockMasks.CustomMotionVectorVertex : CoreBlockMasks.MotionVectorVertex,
validPixelBlocks = CoreBlockMasks.FragmentAlphaOnly,
// Fields
structs = CoreStructCollections.Default,
requiredFields = new FieldCollection(),
fieldDependencies = CoreFieldDependencies.Default,
// Conditional State
renderStates = CoreRenderStates.MotionVector(target),
pragmas = CorePragmas.MotionVectors,
defines = new DefineCollection(),
keywords = new KeywordCollection(),
includes = CoreIncludes.MotionVectors,
// Custom Interpolator Support
customInterpolators = CoreCustomInterpDescriptors.Common
};
if (target.additionalMotionVectorMode == AdditionalMotionVectorMode.TimeBased)
result.defines.Add(CoreKeywordDescriptors.AutomaticTimeBasedMotionVectors, 1);
if (target.alembicMotionVectors)
result.defines.Add(CoreKeywordDescriptors.AddPrecomputedVelocity, 1);
AddAlphaClipControlToPass(ref result, target);
AddLODCrossFadeControlToPass(ref result, target);
return result;
}
public static PassDescriptor SceneSelection(UniversalTarget target)
{
var result = new PassDescriptor()
{
// Definition
displayName = "SceneSelectionPass",
referenceName = "SHADERPASS_DEPTHONLY",
lightMode = "SceneSelectionPass",
useInPreview = false,
// Template
passTemplatePath = UniversalTarget.kUberTemplatePath,
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
// Port Mask
validVertexBlocks = CoreBlockMasks.Vertex,
validPixelBlocks = CoreBlockMasks.FragmentAlphaOnly,
// Fields
structs = CoreStructCollections.Default,
fieldDependencies = CoreFieldDependencies.Default,
// Conditional State
renderStates = CoreRenderStates.SceneSelection(target),
pragmas = CorePragmas.Instanced,
defines = new DefineCollection { CoreDefines.SceneSelection, { CoreKeywordDescriptors.AlphaClipThreshold, 1 } },
keywords = new KeywordCollection(),
includes = CoreIncludes.SceneSelection,
// Custom Interpolator Support
customInterpolators = CoreCustomInterpDescriptors.Common
};
AddAlphaClipControlToPass(ref result, target);
return result;
}
public static PassDescriptor ScenePicking(UniversalTarget target)
{
var result = new PassDescriptor()
{
// Definition
displayName = "ScenePickingPass",
referenceName = "SHADERPASS_DEPTHONLY",
lightMode = "Picking",
useInPreview = false,
// Template
passTemplatePath = UniversalTarget.kUberTemplatePath,
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
// Port Mask
validVertexBlocks = CoreBlockMasks.Vertex,
// NB Color is not strickly needed for scene picking but adding it here so that there are nodes to be
// collected for the pixel shader. Some packages might use this to customize the scene picking rendering.
validPixelBlocks = CoreBlockMasks.FragmentColorAlpha,
// Fields
structs = CoreStructCollections.Default,
fieldDependencies = CoreFieldDependencies.Default,
// Conditional State
renderStates = CoreRenderStates.ScenePicking(target),
pragmas = CorePragmas.Instanced,
defines = new DefineCollection { CoreDefines.ScenePicking, { CoreKeywordDescriptors.AlphaClipThreshold, 1 } },
keywords = new KeywordCollection(),
includes = CoreIncludes.ScenePicking,
// Custom Interpolator Support
customInterpolators = CoreCustomInterpDescriptors.Common
};
AddAlphaClipControlToPass(ref result, target);
return result;
}
public static PassDescriptor _2DSceneSelection(UniversalTarget target)
{
var result = new PassDescriptor()
{
// Definition
displayName = "SceneSelectionPass",
referenceName = "SHADERPASS_DEPTHONLY",
lightMode = "SceneSelectionPass",
useInPreview = false,
// Template
passTemplatePath = UniversalTarget.kUberTemplatePath,
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
// Port Mask
validVertexBlocks = CoreBlockMasks.Vertex,
validPixelBlocks = CoreBlockMasks.FragmentAlphaOnly,
// Fields
structs = CoreStructCollections.Default,
fieldDependencies = CoreFieldDependencies.Default,
// Conditional State
renderStates = CoreRenderStates.SceneSelection(target),
pragmas = CorePragmas._2DDefault,
defines = new DefineCollection { CoreDefines.SceneSelection, { CoreKeywordDescriptors.AlphaClipThreshold, 0 } },
keywords = new KeywordCollection(),
includes = CoreIncludes.ScenePicking,
// Custom Interpolator Support
customInterpolators = CoreCustomInterpDescriptors.Common
};
AddAlphaClipControlToPass(ref result, target);
return result;
}
public static PassDescriptor _2DScenePicking(UniversalTarget target)
{
var result = new PassDescriptor()
{
// Definition
displayName = "ScenePickingPass",
referenceName = "SHADERPASS_DEPTHONLY",
lightMode = "Picking",
useInPreview = false,
// Template
passTemplatePath = UniversalTarget.kUberTemplatePath,
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
// Port Mask
validVertexBlocks = CoreBlockMasks.Vertex,
validPixelBlocks = CoreBlockMasks.FragmentAlphaOnly,
// Fields
structs = CoreStructCollections.Default,
fieldDependencies = CoreFieldDependencies.Default,
// Conditional State
renderStates = CoreRenderStates.ScenePicking(target),
pragmas = CorePragmas._2DDefault,
defines = new DefineCollection { CoreDefines.ScenePicking, { CoreKeywordDescriptors.AlphaClipThreshold, 0 } },
keywords = new KeywordCollection(),
includes = CoreIncludes.SceneSelection,
// Custom Interpolator Support
customInterpolators = CoreCustomInterpDescriptors.Common
};
AddAlphaClipControlToPass(ref result, target);
return result;
}
}
#endregion
#region PortMasks
class CoreBlockMasks
{
public static readonly BlockFieldDescriptor[] MotionVectorVertex = new BlockFieldDescriptor[]
{
BlockFields.VertexDescription.Position,
};
public static readonly BlockFieldDescriptor[] CustomMotionVectorVertex = new BlockFieldDescriptor[]
{
BlockFields.VertexDescription.Position,
UniversalBlockFields.VertexDescription.MotionVector,
};
public static readonly BlockFieldDescriptor[] Vertex = new BlockFieldDescriptor[]
{
BlockFields.VertexDescription.Position,
BlockFields.VertexDescription.Normal,
BlockFields.VertexDescription.Tangent,
};
public static readonly BlockFieldDescriptor[] FragmentAlphaOnly = new BlockFieldDescriptor[]
{
BlockFields.SurfaceDescription.Alpha,
BlockFields.SurfaceDescription.AlphaClipThreshold,
};
public static readonly BlockFieldDescriptor[] FragmentColorAlpha = new BlockFieldDescriptor[]
{
BlockFields.SurfaceDescription.BaseColor,
BlockFields.SurfaceDescription.Alpha,
BlockFields.SurfaceDescription.AlphaClipThreshold,
};
public static readonly BlockFieldDescriptor[] FragmentDepthNormals = new BlockFieldDescriptor[]
{
BlockFields.SurfaceDescription.NormalOS,
BlockFields.SurfaceDescription.NormalTS,
BlockFields.SurfaceDescription.NormalWS,
BlockFields.SurfaceDescription.Alpha,
BlockFields.SurfaceDescription.AlphaClipThreshold,
};
}
#endregion
#region StructCollections
static class CoreStructCollections
{
public static readonly StructCollection Default = new StructCollection
{
{ Structs.Attributes },
{ UniversalStructs.Varyings },
{ Structs.SurfaceDescriptionInputs },
{ Structs.VertexDescriptionInputs },
};
}
#endregion
#region RequiredFields
static class CoreRequiredFields
{
public static readonly FieldCollection ShadowCaster = new FieldCollection()
{
StructFields.Varyings.normalWS,
};
public static readonly FieldCollection DepthNormals = new FieldCollection()
{
StructFields.Attributes.uv1, // needed for meta vertex position
StructFields.Varyings.normalWS,
StructFields.Varyings.tangentWS, // needed for vertex lighting
};
}
#endregion
#region FieldDependencies
static class CoreFieldDependencies
{
public static readonly DependencyCollection Default = new DependencyCollection()
{
{ FieldDependencies.Default },
new FieldDependency(UniversalStructFields.Varyings.stereoTargetEyeIndexAsRTArrayIdx, StructFields.Attributes.instanceID),
new FieldDependency(UniversalStructFields.Varyings.stereoTargetEyeIndexAsBlendIdx0, StructFields.Attributes.instanceID),
};
}
#endregion
#region RenderStates
static class CoreRenderStates
{
public static class Uniforms
{
public static readonly string srcBlend = "[" + Property.SrcBlend + "]";
public static readonly string dstBlend = "[" + Property.DstBlend + "]";
public static readonly string cullMode = "[" + Property.CullMode + "]";
public static readonly string zWrite = "[" + Property.ZWrite + "]";
public static readonly string zTest = "[" + Property.ZTest + "]";
}
// used by sprite targets, NOT used by lit/unlit anymore
public static readonly RenderStateCollection Default = new RenderStateCollection
{
{ RenderState.Cull(Cull.Back), new FieldCondition(Fields.DoubleSided, false) },
{ RenderState.Cull(Cull.Off), new FieldCondition(Fields.DoubleSided, true) },
{ RenderState.Blend(Blend.One, Blend.Zero), new FieldCondition(UniversalFields.SurfaceOpaque, true) },
{ RenderState.Blend(Blend.SrcAlpha, Blend.OneMinusSrcAlpha, Blend.One, Blend.OneMinusSrcAlpha), new FieldCondition(Fields.BlendAlpha, true) },
{ RenderState.Blend(Blend.One, Blend.OneMinusSrcAlpha, Blend.One, Blend.OneMinusSrcAlpha), new FieldCondition(UniversalFields.BlendPremultiply, true) },
{ RenderState.Blend(Blend.SrcAlpha, Blend.One, Blend.One, Blend.One), new FieldCondition(UniversalFields.BlendAdd, true) },
{ RenderState.Blend(Blend.DstColor, Blend.Zero), new FieldCondition(UniversalFields.BlendMultiply, true) },
};
public static Cull RenderFaceToCull(RenderFace renderFace)
{
switch (renderFace)
{
case RenderFace.Back:
return Cull.Front;
case RenderFace.Front:
return Cull.Back;
case RenderFace.Both:
return Cull.Off;
}
return Cull.Back;
}
// used by lit/unlit subtargets
public static RenderStateCollection UberSwitchedRenderState(UniversalTarget target, bool blendModePreserveSpecular = false)
{
if (target.allowMaterialOverride)
{
return new RenderStateCollection
{
RenderState.ZTest(Uniforms.zTest),
RenderState.ZWrite(Uniforms.zWrite),
RenderState.Cull(Uniforms.cullMode),
RenderState.Blend(Uniforms.srcBlend, Uniforms.dstBlend),
};
}
else
{
var result = new RenderStateCollection();
result.Add(RenderState.ZTest(target.zTestMode.ToString()));
if (target.zWriteControl == ZWriteControl.Auto)
{
if (target.surfaceType == SurfaceType.Opaque)
result.Add(RenderState.ZWrite(ZWrite.On));
else
result.Add(RenderState.ZWrite(ZWrite.Off));
}
else if (target.zWriteControl == ZWriteControl.ForceEnabled)
result.Add(RenderState.ZWrite(ZWrite.On));
else
result.Add(RenderState.ZWrite(ZWrite.Off));
result.Add(RenderState.Cull(RenderFaceToCull(target.renderFace)));
if (target.surfaceType == SurfaceType.Opaque)
{
result.Add(RenderState.Blend(Blend.One, Blend.Zero));
}
else
{
// Lift alpha multiply from ROP to shader in preserve spec for different diffuse and specular blends.
Blend blendSrcRGB = blendModePreserveSpecular ? Blend.One : Blend.SrcAlpha;
switch (target.alphaMode)
{
case AlphaMode.Alpha:
result.Add(RenderState.Blend(blendSrcRGB, Blend.OneMinusSrcAlpha, Blend.One, Blend.OneMinusSrcAlpha));
break;
case AlphaMode.Premultiply:
result.Add(RenderState.Blend(Blend.One, Blend.OneMinusSrcAlpha, Blend.One, Blend.OneMinusSrcAlpha));
break;
case AlphaMode.Additive:
result.Add(RenderState.Blend(blendSrcRGB, Blend.One, Blend.One, Blend.One));
break;
case AlphaMode.Multiply:
result.Add(RenderState.Blend(Blend.DstColor, Blend.Zero, Blend.Zero, Blend.One)); // Multiply RGB only, keep A
break;
}
}
return result;
}
}
// used by lit target ONLY
public static readonly RenderStateCollection Meta = new RenderStateCollection
{
{ RenderState.Cull(Cull.Off) },
};
public static RenderStateDescriptor UberSwitchedCullRenderState(UniversalTarget target)
{
if (target.allowMaterialOverride)
return RenderState.Cull(Uniforms.cullMode);
else
return RenderState.Cull(RenderFaceToCull(target.renderFace));
}
public static RenderStateCollection MotionVector(UniversalTarget target)
{
var result = new RenderStateCollection
{
{ RenderState.ZTest(ZTest.LEqual) },
{ RenderState.ZWrite(ZWrite.On) },
{ UberSwitchedCullRenderState(target) },
{ RenderState.ColorMask("ColorMask RG") },
};
return result;
}
// used by lit/unlit targets
public static RenderStateCollection ShadowCaster(UniversalTarget target)
{
var result = new RenderStateCollection
{
{ RenderState.ZTest(ZTest.LEqual) },
{ RenderState.ZWrite(ZWrite.On) },
{ UberSwitchedCullRenderState(target) },
{ RenderState.ColorMask("ColorMask 0") },
};
return result;
}
// used by lit/unlit targets
public static RenderStateCollection DepthOnly(UniversalTarget target)
{
var result = new RenderStateCollection
{
{ RenderState.ZTest(ZTest.LEqual) },
{ RenderState.ZWrite(ZWrite.On) },
{ UberSwitchedCullRenderState(target) },
{ RenderState.ColorMask("ColorMask R") },
};
return result;
}
// used by lit target ONLY
public static RenderStateCollection DepthNormalsOnly(UniversalTarget target)
{
var result = new RenderStateCollection
{
{ RenderState.ZTest(ZTest.LEqual) },
{ RenderState.ZWrite(ZWrite.On) },
{ UberSwitchedCullRenderState(target) }
};
return result;
}
// Used by all targets
public static RenderStateCollection SceneSelection(UniversalTarget target)
{
var result = new RenderStateCollection
{
{ RenderState.Cull(Cull.Off) },
};
return result;
}
public static RenderStateCollection ScenePicking(UniversalTarget target)
{
var result = new RenderStateCollection
{
{ UberSwitchedCullRenderState(target) }
};
return result;
}
}
#endregion
#region Pragmas
static class CorePragmas
{
public static readonly PragmaCollection Default = new PragmaCollection
{
{ Pragma.Target(ShaderModel.Target20) },
{ Pragma.Vertex("vert") },
{ Pragma.Fragment("frag") },
};
public static readonly PragmaCollection Instanced = new PragmaCollection
{
{ Pragma.Target(ShaderModel.Target20) },
{ Pragma.MultiCompileInstancing },
{ Pragma.Vertex("vert") },
{ Pragma.Fragment("frag") },
};
public static readonly PragmaCollection MotionVectors = new PragmaCollection
{
{ Pragma.Target(ShaderModel.Target35) },
{ Pragma.MultiCompileInstancing },
{ Pragma.Vertex("vert") },
{ Pragma.Fragment("frag") },
};
public static readonly PragmaCollection Forward = new PragmaCollection
{
{ Pragma.Target(ShaderModel.Target20) },
{ Pragma.MultiCompileInstancing },
{ Pragma.MultiCompileFog },
{ Pragma.InstancingOptions(InstancingOptions.RenderingLayer) },
{ Pragma.Vertex("vert") },
{ Pragma.Fragment("frag") },
};
public static readonly PragmaCollection _2DDefault = new PragmaCollection
{
{ Pragma.Target(ShaderModel.Target20) },
{ Pragma.ExcludeRenderers(new[] { Platform.D3D9 }) },
{ Pragma.Vertex("vert") },
{ Pragma.Fragment("frag") },
};
public static readonly PragmaCollection GBuffer = new PragmaCollection
{
{ Pragma.Target(ShaderModel.Target45) },
{ Pragma.ExcludeRenderers(new[] { Platform.GLES3, Platform.GLCore }) },
{ Pragma.MultiCompileInstancing },
{ Pragma.MultiCompileFog },
{ Pragma.InstancingOptions(InstancingOptions.RenderingLayer) },
{ Pragma.Vertex("vert") },
{ Pragma.Fragment("frag") },
};
}
#endregion
#region Includes
static class CoreIncludes
{
const string kColor = "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl";
const string kTexture = "Packages/com.unity.render-pipelines.core/ShaderLibrary/Texture.hlsl";
const string kCore = "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl";
const string kInput = "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl";
const string kLighting = "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl";
const string kGraphFunctions = "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderGraphFunctions.hlsl";
const string kVaryings = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/Varyings.hlsl";
const string kShaderPass = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/ShaderPass.hlsl";
const string kDepthOnlyPass = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/DepthOnlyPass.hlsl";
const string kDepthNormalsOnlyPass = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/DepthNormalsOnlyPass.hlsl";
const string kShadowCasterPass = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/ShadowCasterPass.hlsl";
const string kMotionVectorPass = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/MotionVectorPass.hlsl";
const string kTextureStack = "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl";
const string kDBuffer = "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DBuffer.hlsl";
const string kSelectionPickingPass = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/SelectionPickingPass.hlsl";
const string kLODCrossFade = "Packages/com.unity.render-pipelines.universal/ShaderLibrary/LODCrossFade.hlsl";
const string kFoveatedRenderingKeywords = "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl";
const string kFoveatedRendering = "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl";
const string kMipmapDebugMacros = "Packages/com.unity.render-pipelines.core/ShaderLibrary/DebugMipmapStreamingMacros.hlsl";
// Files that are included with #include_with_pragmas
const string kDOTS = "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl";
const string kRenderingLayers = "Packages/com.unity.render-pipelines.universal/ShaderLibrary/RenderingLayers.hlsl";
const string kProbeVolumes = "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ProbeVolumeVariants.hlsl";
public static readonly IncludeCollection CorePregraph = new IncludeCollection
{
{ kColor, IncludeLocation.Pregraph },
{ kTexture, IncludeLocation.Pregraph },
{ kCore, IncludeLocation.Pregraph },
{ kLighting, IncludeLocation.Pregraph },
{ kInput, IncludeLocation.Pregraph },
{ kTextureStack, IncludeLocation.Pregraph }, // TODO: put this on a conditional
{ kFoveatedRenderingKeywords, IncludeLocation.Pregraph, true },
{ kFoveatedRendering, IncludeLocation.Pregraph },
{ kMipmapDebugMacros, IncludeLocation.Pregraph}
};
public static readonly IncludeCollection DOTSPregraph = new IncludeCollection
{
{ kDOTS, IncludeLocation.Pregraph, true },
};
public static readonly IncludeCollection WriteRenderLayersPregraph = new IncludeCollection
{
{ kRenderingLayers, IncludeLocation.Pregraph, true },
};
public static readonly IncludeCollection ProbeVolumePregraph = new IncludeCollection
{
{ kProbeVolumes, IncludeLocation.Pregraph, true },
};
public static readonly IncludeCollection ShaderGraphPregraph = new IncludeCollection
{
{ kGraphFunctions, IncludeLocation.Pregraph },
};
public static readonly IncludeCollection CorePostgraph = new IncludeCollection
{
{ kShaderPass, IncludeLocation.Pregraph },
{ kVaryings, IncludeLocation.Postgraph },
};
public static readonly IncludeCollection DepthOnly = new IncludeCollection
{
// Pre-graph
{ DOTSPregraph },
{ CorePregraph },
{ ShaderGraphPregraph },
// Post-graph
{ CorePostgraph },
{ kDepthOnlyPass, IncludeLocation.Postgraph },
};
public static readonly IncludeCollection DepthNormalsOnly = new IncludeCollection
{
// Pre-graph
{ DOTSPregraph },
{ WriteRenderLayersPregraph },
{ CorePregraph },
{ ShaderGraphPregraph },
// Post-graph
{ CorePostgraph },
{ kDepthNormalsOnlyPass, IncludeLocation.Postgraph },
};
public static readonly IncludeCollection MotionVectors = new IncludeCollection
{
// Pre-graph
{ DOTSPregraph },
{ WriteRenderLayersPregraph },
{ CorePregraph },
{ ShaderGraphPregraph },
//Post-graph
{ CorePostgraph },
{ kMotionVectorPass, IncludeLocation.Postgraph },
};
public static readonly IncludeCollection ShadowCaster = new IncludeCollection
{
// Pre-graph
{ DOTSPregraph },
{ CorePregraph },
{ ShaderGraphPregraph },
// Post-graph
{ CorePostgraph },
{ kShadowCasterPass, IncludeLocation.Postgraph },
};
public static readonly IncludeCollection DBufferPregraph = new IncludeCollection
{
{ kDBuffer, IncludeLocation.Pregraph },
};
public static readonly IncludeCollection SceneSelection = new IncludeCollection
{
// Pre-graph
{ CorePregraph },
{ ShaderGraphPregraph },
{ DOTSPregraph },
// Post-graph
{ CorePostgraph },
{ kSelectionPickingPass, IncludeLocation.Postgraph },
};
public static readonly IncludeCollection ScenePicking = new IncludeCollection
{
// Pre-graph
{ CorePregraph },
{ ShaderGraphPregraph },
{ DOTSPregraph },
// Post-graph
{ CorePostgraph },
{ kSelectionPickingPass, IncludeLocation.Postgraph },
};
public static readonly IncludeCollection LODCrossFade = new IncludeCollection
{
{ kLODCrossFade, IncludeLocation.Pregraph }
};
}
#endregion
#region Defines
static class CoreDefines
{
public static readonly DefineCollection UseLegacySpriteBlocks = new DefineCollection
{
{ CoreKeywordDescriptors.UseLegacySpriteBlocks, 1, new FieldCondition(CoreFields.UseLegacySpriteBlocks, true) },
};
public static readonly DefineCollection UseFragmentFog = new DefineCollection()
{
{CoreKeywordDescriptors.UseFragmentFog, 1},
};
public static readonly DefineCollection SceneSelection = new DefineCollection
{
{ CoreKeywordDescriptors.SceneSelectionPass, 1 },
};
public static readonly DefineCollection ScenePicking = new DefineCollection
{
{ CoreKeywordDescriptors.ScenePickingPass, 1 },
};
}
#endregion
#region KeywordDescriptors
static class CoreKeywordDescriptors
{
public static readonly KeywordDescriptor StaticLightmap = new KeywordDescriptor()
{
displayName = "Static Lightmap",
referenceName = "LIGHTMAP_ON",
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
};
public static readonly KeywordDescriptor DynamicLightmap = new KeywordDescriptor()
{
displayName = "Dynamic Lightmap",
referenceName = "DYNAMICLIGHTMAP_ON",
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
};
public static readonly KeywordDescriptor DirectionalLightmapCombined = new KeywordDescriptor()
{
displayName = "Directional Lightmap Combined",
referenceName = "DIRLIGHTMAP_COMBINED",
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
};
public static readonly KeywordDescriptor SampleGI = new KeywordDescriptor()
{
displayName = "Sample GI",
referenceName = "_SAMPLE_GI",
type = KeywordType.Boolean,
definition = KeywordDefinition.ShaderFeature,
scope = KeywordScope.Global,
};
public static readonly KeywordDescriptor AlphaTestOn = new KeywordDescriptor()
{
displayName = ShaderKeywordStrings._ALPHATEST_ON,
referenceName = ShaderKeywordStrings._ALPHATEST_ON,
type = KeywordType.Boolean,
definition = KeywordDefinition.ShaderFeature,
scope = KeywordScope.Local,
stages = KeywordShaderStage.Fragment,
};
public static readonly KeywordDescriptor SurfaceTypeTransparent = new KeywordDescriptor()
{
displayName = ShaderKeywordStrings._SURFACE_TYPE_TRANSPARENT,
referenceName = ShaderKeywordStrings._SURFACE_TYPE_TRANSPARENT,
type = KeywordType.Boolean,
definition = KeywordDefinition.ShaderFeature,
scope = KeywordScope.Global, // needs to match HDRP
stages = KeywordShaderStage.Fragment,
};
public static readonly KeywordDescriptor AlphaPremultiplyOn = new KeywordDescriptor()
{
displayName = ShaderKeywordStrings._ALPHAPREMULTIPLY_ON,
referenceName = ShaderKeywordStrings._ALPHAPREMULTIPLY_ON,
type = KeywordType.Boolean,
definition = KeywordDefinition.ShaderFeature,
scope = KeywordScope.Local,
stages = KeywordShaderStage.Fragment,
};
public static readonly KeywordDescriptor AlphaModulateOn = new KeywordDescriptor()
{
displayName = ShaderKeywordStrings._ALPHAMODULATE_ON,
referenceName = ShaderKeywordStrings._ALPHAMODULATE_ON,
type = KeywordType.Boolean,
definition = KeywordDefinition.ShaderFeature,
scope = KeywordScope.Local,
stages = KeywordShaderStage.Fragment,
};
public static readonly KeywordDescriptor EvaluateSh = new KeywordDescriptor()
{
displayName = "Evaluate SH",
referenceName = "EVALUATE_SH",
type = KeywordType.Enum,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
entries = new KeywordEntry[]
{
new KeywordEntry() { displayName = "Off", referenceName = "" },
new KeywordEntry() { displayName = "Evaluate SH Mixed", referenceName = "MIXED" },
new KeywordEntry() { displayName = "Evaluate SH Vertex", referenceName = "VERTEX" },
}
};
public static readonly KeywordDescriptor MainLightShadows = new KeywordDescriptor()
{
displayName = "Main Light Shadows",
referenceName = "",
type = KeywordType.Enum,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
entries = new KeywordEntry[]
{
new KeywordEntry() { displayName = "Off", referenceName = "" },
new KeywordEntry() { displayName = "No Cascade", referenceName = "MAIN_LIGHT_SHADOWS" },
new KeywordEntry() { displayName = "Cascade", referenceName = "MAIN_LIGHT_SHADOWS_CASCADE" },
new KeywordEntry() { displayName = "Screen", referenceName = "MAIN_LIGHT_SHADOWS_SCREEN" },
}
};
public static readonly KeywordDescriptor CastingPunctualLightShadow = new KeywordDescriptor()
{
displayName = "Casting Punctual Light Shadow",
referenceName = "_CASTING_PUNCTUAL_LIGHT_SHADOW",
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
stages = KeywordShaderStage.Vertex,
};
public static readonly KeywordDescriptor AutomaticTimeBasedMotionVectors = new KeywordDescriptor()
{
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 AddPrecomputedVelocity = new KeywordDescriptor()
{
displayName = "Add Precomputed Velocity",
referenceName = ShaderKeywordStrings._ADD_PRECOMPUTED_VELOCITY,
type = KeywordType.Boolean,
definition = KeywordDefinition.Predefined,
scope = KeywordScope.Local,
stages = KeywordShaderStage.Vertex,
};
public static readonly KeywordDescriptor AdditionalLights = new KeywordDescriptor()
{
displayName = "Additional Lights",
referenceName = "",
type = KeywordType.Enum,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
entries = new KeywordEntry[]
{
new KeywordEntry() { displayName = "Off", referenceName = "" },
new KeywordEntry() { displayName = "Vertex", referenceName = "ADDITIONAL_LIGHTS_VERTEX" },
new KeywordEntry() { displayName = "Fragment", referenceName = "ADDITIONAL_LIGHTS" },
}
};
public static readonly KeywordDescriptor AdditionalLightShadows = new KeywordDescriptor()
{
displayName = "Additional Light Shadows",
referenceName = "_ADDITIONAL_LIGHT_SHADOWS",
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
stages = KeywordShaderStage.Fragment,
};
public static readonly KeywordDescriptor ReflectionProbeBlending = new KeywordDescriptor()
{
displayName = "Reflection Probe Blending",
referenceName = "_REFLECTION_PROBE_BLENDING",
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
stages = KeywordShaderStage.Fragment,
};
public static readonly KeywordDescriptor ReflectionProbeBoxProjection = new KeywordDescriptor()
{
displayName = "Reflection Probe Box Projection",
referenceName = "_REFLECTION_PROBE_BOX_PROJECTION",
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
stages = KeywordShaderStage.Fragment,
};
public static readonly KeywordDescriptor ShadowsSoft = new KeywordDescriptor()
{
displayName = "Soft Shadows",
referenceName = "",
type = KeywordType.Enum,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
stages = KeywordShaderStage.Fragment,
entries = new KeywordEntry[]
{
new KeywordEntry() { displayName = "Off", referenceName = "" },
new KeywordEntry() { displayName = "Soft Shadows Per Light", referenceName = "SHADOWS_SOFT" },
new KeywordEntry() { displayName = "Soft Shadows Low", referenceName = "SHADOWS_SOFT_LOW" },
new KeywordEntry() { displayName = "Soft Shadows Medium", referenceName = "SHADOWS_SOFT_MEDIUM" },
new KeywordEntry() { displayName = "Soft Shadows High", referenceName = "SHADOWS_SOFT_HIGH" },
}
};
public static readonly KeywordDescriptor MixedLightingSubtractive = new KeywordDescriptor()
{
displayName = "Mixed Lighting Subtractive",
referenceName = "_MIXED_LIGHTING_SUBTRACTIVE",
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
};
public static readonly KeywordDescriptor LightmapShadowMixing = new KeywordDescriptor()
{
displayName = "Lightmap Shadow Mixing",
referenceName = "LIGHTMAP_SHADOW_MIXING",
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
};
public static readonly KeywordDescriptor ShadowsShadowmask = new KeywordDescriptor()
{
displayName = "Shadows Shadowmask",
referenceName = "SHADOWS_SHADOWMASK",
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
};
public static readonly KeywordDescriptor LightLayers = new KeywordDescriptor()
{
displayName = "Light Layers",
referenceName = "_LIGHT_LAYERS",
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
stages = KeywordShaderStage.Fragment,
};
public static readonly KeywordDescriptor RenderPassEnabled = new KeywordDescriptor()
{
displayName = "Render Pass Enabled",
referenceName = "_RENDER_PASS_ENABLED",
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
stages = KeywordShaderStage.Fragment,
};
public static readonly KeywordDescriptor ShapeLightType0 = new KeywordDescriptor()
{
displayName = "Shape Light Type 0",
referenceName = "USE_SHAPE_LIGHT_TYPE_0",
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
};
public static readonly KeywordDescriptor ShapeLightType1 = new KeywordDescriptor()
{
displayName = "Shape Light Type 1",
referenceName = "USE_SHAPE_LIGHT_TYPE_1",
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
};
public static readonly KeywordDescriptor ShapeLightType2 = new KeywordDescriptor()
{
displayName = "Shape Light Type 2",
referenceName = "USE_SHAPE_LIGHT_TYPE_2",
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
};
public static readonly KeywordDescriptor ShapeLightType3 = new KeywordDescriptor()
{
displayName = "Shape Light Type 3",
referenceName = "USE_SHAPE_LIGHT_TYPE_3",
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
};
public static readonly KeywordDescriptor UseLegacySpriteBlocks = new KeywordDescriptor()
{
displayName = "UseLegacySpriteBlocks",
referenceName = "USELEGACYSPRITEBLOCKS",
type = KeywordType.Boolean,
};
public static readonly KeywordDescriptor UseFragmentFog = new KeywordDescriptor()
{
displayName = "UseFragmentFog",
referenceName = "_FOG_FRAGMENT",
type = KeywordType.Boolean,
};
public static readonly KeywordDescriptor GBufferNormalsOct = new KeywordDescriptor()
{
displayName = "GBuffer normal octahedron encoding",
referenceName = "_GBUFFER_NORMALS_OCT",
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
stages = KeywordShaderStage.Fragment,
};
public static readonly KeywordDescriptor DBuffer = new KeywordDescriptor()
{
displayName = "Decals",
referenceName = "",
type = KeywordType.Enum,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
entries = new KeywordEntry[]
{
new KeywordEntry() { displayName = "Off", referenceName = "" },
new KeywordEntry() { displayName = "DBuffer Mrt1", referenceName = "DBUFFER_MRT1" },
new KeywordEntry() { displayName = "DBuffer Mrt2", referenceName = "DBUFFER_MRT2" },
new KeywordEntry() { displayName = "DBuffer Mrt3", referenceName = "DBUFFER_MRT3" },
},
stages = KeywordShaderStage.Fragment,
};
public static readonly KeywordDescriptor DebugDisplay = new KeywordDescriptor()
{
displayName = "Debug Display",
referenceName = "DEBUG_DISPLAY",
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
stages = KeywordShaderStage.Fragment,
};
public static readonly KeywordDescriptor SceneSelectionPass = new KeywordDescriptor()
{
displayName = "Scene Selection Pass",
referenceName = "SCENESELECTIONPASS",
type = KeywordType.Boolean,
};
public static readonly KeywordDescriptor ScenePickingPass = new KeywordDescriptor()
{
displayName = "Scene Picking Pass",
referenceName = "SCENEPICKINGPASS",
type = KeywordType.Boolean,
};
public static readonly KeywordDescriptor AlphaClipThreshold = new KeywordDescriptor()
{
displayName = "AlphaClipThreshold",
referenceName = "ALPHA_CLIP_THRESHOLD",
type = KeywordType.Boolean,
definition = KeywordDefinition.Predefined,
};
public static readonly KeywordDescriptor LightCookies = new KeywordDescriptor()
{
displayName = "Light Cookies",
referenceName = "_LIGHT_COOKIES",
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
stages = KeywordShaderStage.Fragment,
};
public static readonly KeywordDescriptor ForwardPlus = new KeywordDescriptor()
{
displayName = "Forward+",
referenceName = "_FORWARD_PLUS",
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
};
public static readonly KeywordDescriptor EditorVisualization = new KeywordDescriptor()
{
displayName = "Editor Visualization",
referenceName = "EDITOR_VISUALIZATION",
type = KeywordType.Boolean,
definition = KeywordDefinition.ShaderFeature,
scope = KeywordScope.Global,
};
public static readonly KeywordDescriptor LODFadeCrossFade = new KeywordDescriptor()
{
displayName = ShaderKeywordStrings.LOD_FADE_CROSSFADE,
referenceName = ShaderKeywordStrings.LOD_FADE_CROSSFADE,
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
// Note: SpeedTree shaders used to have their own PS-based Crossfade,
// as well as a VS-based smooth LOD transition effect.
// These shaders need the LOD_FADE_CROSSFADE keyword in the VS
// to skip the VS-based effect.
// Note: DOTS instancing uses a different instance index encoding
// when crossfade is active, so all stages are affected by the
// LOD_FADE_CROSSFADE keyword.
scope = KeywordScope.Global
};
public static readonly KeywordDescriptor UseUnityCrossFade = new KeywordDescriptor()
{
displayName = ShaderKeywordStrings.USE_UNITY_CROSSFADE,
referenceName = ShaderKeywordStrings.USE_UNITY_CROSSFADE,
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
stages = KeywordShaderStage.Fragment,
};
public static readonly KeywordDescriptor ScreenSpaceAmbientOcclusion = new KeywordDescriptor()
{
displayName = "Screen Space Ambient Occlusion",
referenceName = "_SCREEN_SPACE_OCCLUSION",
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
stages = KeywordShaderStage.Fragment,
};
public static readonly KeywordDescriptor UseLegacyLightmaps = new KeywordDescriptor()
{
displayName = "Use Legacy Lightmaps",
referenceName = ShaderKeywordStrings.USE_LEGACY_LIGHTMAPS,
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global
};
}
#endregion
#region Keywords
static class CoreKeywords
{
public static readonly KeywordCollection ShadowCaster = new KeywordCollection
{
{ CoreKeywordDescriptors.CastingPunctualLightShadow },
};
}
#endregion
#region FieldDescriptors
static class CoreFields
{
public static readonly FieldDescriptor UseLegacySpriteBlocks = new FieldDescriptor("Universal", "UseLegacySpriteBlocks", "UNIVERSAL_USELEGACYSPRITEBLOCKS");
}
#endregion
#region CustomInterpolators
static class CoreCustomInterpDescriptors
{
public static readonly CustomInterpSubGen.Collection Common = new CustomInterpSubGen.Collection
{
// Custom interpolators are not explicitly defined in the SurfaceDescriptionInputs template.
// This entry point will let us generate a block of pass-through assignments for each field.
CustomInterpSubGen.Descriptor.MakeBlock(CustomInterpSubGen.Splice.k_spliceCopyToSDI, "output", "input"),
// sgci_PassThroughFunc is called from BuildVaryings in Varyings.hlsl to copy custom interpolators from vertex descriptions.
// this entry point allows for the function to be defined before it is used.
CustomInterpSubGen.Descriptor.MakeFunc(CustomInterpSubGen.Splice.k_splicePreSurface, "CustomInterpolatorPassThroughFunc", "Varyings", "VertexDescription", "CUSTOMINTERPOLATOR_VARYPASSTHROUGH_FUNC", "FEATURES_GRAPH_VERTEX")
};
}
#endregion
}