Firstborn/Library/PackageCache/com.unity.render-pipelines..../Editor/ShaderGraph/Targets/UniversalUnlitSubTarget.cs

350 lines
16 KiB
C#
Raw Normal View History

2023-03-28 13:24:16 -04:00
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor.ShaderGraph;
using UnityEditor.ShaderGraph.Legacy;
using static UnityEditor.Rendering.Universal.ShaderGraph.SubShaderUtils;
using static Unity.Rendering.Universal.ShaderUtils;
namespace UnityEditor.Rendering.Universal.ShaderGraph
{
sealed class UniversalUnlitSubTarget : UniversalSubTarget, ILegacyTarget
{
static readonly GUID kSourceCodeGuid = new GUID("97c3f7dcb477ec842aa878573640313a"); // UniversalUnlitSubTarget.cs
public UniversalUnlitSubTarget()
{
displayName = "Unlit";
}
protected override ShaderID shaderID => ShaderID.SG_Unlit;
public override bool IsActive() => true;
public override void Setup(ref TargetSetupContext context)
{
context.AddAssetDependency(kSourceCodeGuid, AssetCollection.Flags.SourceDependency);
base.Setup(ref context);
var universalRPType = typeof(UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset);
if (!context.HasCustomEditorForRenderPipeline(universalRPType))
{
var gui = typeof(ShaderGraphUnlitGUI);
#if HAS_VFX_GRAPH
if (TargetsVFX())
gui = typeof(VFXShaderGraphUnlitGUI);
#endif
context.AddCustomEditorForRenderPipeline(gui.FullName, universalRPType);
}
// Process SubShaders
context.AddSubShader(PostProcessSubShader(SubShaders.UnlitDOTS(target, target.renderType, target.renderQueue)));
context.AddSubShader(PostProcessSubShader(SubShaders.Unlit(target, target.renderType, target.renderQueue)));
}
public override void ProcessPreviewMaterial(Material material)
{
if (target.allowMaterialOverride)
{
// copy our target's default settings into the material
// (technically not necessary since we are always recreating the material from the shader each time,
// which will pull over the defaults from the shader definition)
// but if that ever changes, this will ensure the defaults are set
material.SetFloat(Property.SurfaceType, (float)target.surfaceType);
material.SetFloat(Property.BlendMode, (float)target.alphaMode);
material.SetFloat(Property.AlphaClip, target.alphaClip ? 1.0f : 0.0f);
material.SetFloat(Property.CullMode, (int)target.renderFace);
material.SetFloat(Property.CastShadows, target.castShadows ? 1.0f : 0.0f);
material.SetFloat(Property.ZWriteControl, (float)target.zWriteControl);
material.SetFloat(Property.ZTest, (float)target.zTestMode);
}
// We always need these properties regardless of whether the material is allowed to override
// Queue control & offset enable correct automatic render queue behavior
// Control == 0 is automatic, 1 is user-specified render queue
material.SetFloat(Property.QueueOffset, 0.0f);
material.SetFloat(Property.QueueControl, (float)BaseShaderGUI.QueueControl.Auto);
// call the full unlit material setup function
ShaderGraphUnlitGUI.UpdateMaterial(material, MaterialUpdateType.CreatedNewMaterial);
}
public override void GetFields(ref TargetFieldContext context)
{
base.GetFields(ref context);
}
public override void GetActiveBlocks(ref TargetActiveBlockContext context)
{
context.AddBlock(BlockFields.SurfaceDescription.Alpha, (target.surfaceType == SurfaceType.Transparent || target.alphaClip) || target.allowMaterialOverride);
context.AddBlock(BlockFields.SurfaceDescription.AlphaClipThreshold, target.alphaClip || target.allowMaterialOverride);
}
public override void CollectShaderProperties(PropertyCollector collector, GenerationMode generationMode)
{
if (target.allowMaterialOverride)
{
collector.AddFloatProperty(Property.CastShadows, target.castShadows ? 1.0f : 0.0f);
collector.AddFloatProperty(Property.SurfaceType, (float)target.surfaceType);
collector.AddFloatProperty(Property.BlendMode, (float)target.alphaMode);
collector.AddFloatProperty(Property.AlphaClip, target.alphaClip ? 1.0f : 0.0f);
collector.AddFloatProperty(Property.SrcBlend, 1.0f); // always set by material inspector
collector.AddFloatProperty(Property.DstBlend, 0.0f); // always set by material inspector
collector.AddToggleProperty(Property.ZWrite, (target.surfaceType == SurfaceType.Opaque));
collector.AddFloatProperty(Property.ZWriteControl, (float)target.zWriteControl);
collector.AddFloatProperty(Property.ZTest, (float)target.zTestMode); // ztest mode is designed to directly pass as ztest
collector.AddFloatProperty(Property.CullMode, (float)target.renderFace); // render face enum is designed to directly pass as a cull mode
}
// We always need these properties regardless of whether the material is allowed to override other shader properties.
// Queue control & offset enable correct automatic render queue behavior. Control == 0 is automatic, 1 is user-specified.
// We initialize queue control to -1 to indicate to UpdateMaterial that it needs to initialize it properly on the material.
collector.AddFloatProperty(Property.QueueOffset, 0.0f);
collector.AddFloatProperty(Property.QueueControl, -1.0f);
}
public override void GetPropertiesGUI(ref TargetPropertyGUIContext context, Action onChange, Action<String> registerUndo)
{
var universalTarget = (target as UniversalTarget);
universalTarget.AddDefaultMaterialOverrideGUI(ref context, onChange, registerUndo);
universalTarget.AddDefaultSurfacePropertiesGUI(ref context, onChange, registerUndo, showReceiveShadows: false);
}
public bool TryUpgradeFromMasterNode(IMasterNode1 masterNode, out Dictionary<BlockFieldDescriptor, int> blockMap)
{
blockMap = null;
if (!(masterNode is UnlitMasterNode1 unlitMasterNode))
return false;
// Set blockmap
blockMap = new Dictionary<BlockFieldDescriptor, int>()
{
{ BlockFields.VertexDescription.Position, 9 },
{ BlockFields.VertexDescription.Normal, 10 },
{ BlockFields.VertexDescription.Tangent, 11 },
{ BlockFields.SurfaceDescription.BaseColor, 0 },
{ BlockFields.SurfaceDescription.Alpha, 7 },
{ BlockFields.SurfaceDescription.AlphaClipThreshold, 8 },
};
return true;
}
#region SubShader
static class SubShaders
{
public static SubShaderDescriptor Unlit(UniversalTarget target, string renderType, string renderQueue)
{
var result = new SubShaderDescriptor()
{
pipelineTag = UniversalTarget.kPipelineTag,
customTags = UniversalTarget.kUnlitMaterialTypeTag,
renderType = renderType,
renderQueue = renderQueue,
generatesPreview = true,
passes = new PassCollection()
};
result.passes.Add(UnlitPasses.Forward(target));
if (target.mayWriteDepth)
result.passes.Add(CorePasses.DepthOnly(target));
result.passes.Add(CorePasses.DepthNormalOnly(target));
if (target.castShadows || target.allowMaterialOverride)
result.passes.Add(CorePasses.ShadowCaster(target));
// Currently neither of these passes (selection/picking) can be last for the game view for
// UI shaders to render correctly. Verify [1352225] before changing this order.
result.passes.Add(CorePasses.SceneSelection(target));
result.passes.Add(CorePasses.ScenePicking(target));
result.passes.Add(UnlitPasses.DepthNormalOnly(target));
return result;
}
public static SubShaderDescriptor UnlitDOTS(UniversalTarget target, string renderType, string renderQueue)
{
var result = new SubShaderDescriptor()
{
pipelineTag = UniversalTarget.kPipelineTag,
customTags = UniversalTarget.kUnlitMaterialTypeTag,
renderType = renderType,
renderQueue = renderQueue,
generatesPreview = true,
passes = new PassCollection()
};
result.passes.Add(PassVariant(UnlitPasses.Forward(target), CorePragmas.DOTSForward));
if (target.mayWriteDepth)
result.passes.Add(PassVariant(CorePasses.DepthOnly(target), CorePragmas.DOTSInstanced));
result.passes.Add(PassVariant(CorePasses.DepthNormalOnly(target), CorePragmas.DOTSInstanced));
if (target.castShadows || target.allowMaterialOverride)
result.passes.Add(PassVariant(CorePasses.ShadowCaster(target), CorePragmas.DOTSInstanced));
// Currently neither of these passes (selection/picking) can be last for the game view for
// UI shaders to render correctly. Verify [1352225] before changing this order.
result.passes.Add(PassVariant(CorePasses.SceneSelection(target), CorePragmas.DOTSDefault));
result.passes.Add(PassVariant(CorePasses.ScenePicking(target), CorePragmas.DOTSDefault));
result.passes.Add(PassVariant(UnlitPasses.DepthNormalOnly(target), CorePragmas.DOTSInstanced));
return result;
}
}
#endregion
#region Pass
static class UnlitPasses
{
public static PassDescriptor Forward(UniversalTarget target)
{
var result = new PassDescriptor
{
// Definition
displayName = "Universal Forward",
referenceName = "SHADERPASS_UNLIT",
useInPreview = true,
// Template
passTemplatePath = UniversalTarget.kUberTemplatePath,
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
// Port Mask
validVertexBlocks = CoreBlockMasks.Vertex,
validPixelBlocks = CoreBlockMasks.FragmentColorAlpha,
// Fields
structs = CoreStructCollections.Default,
requiredFields = UnlitRequiredFields.Unlit,
fieldDependencies = CoreFieldDependencies.Default,
// Conditional State
renderStates = CoreRenderStates.UberSwitchedRenderState(target),
pragmas = CorePragmas.Forward,
defines = new DefineCollection() { CoreDefines.UseFragmentFog },
keywords = new KeywordCollection() { UnlitKeywords.UnlitBaseKeywords },
includes = UnlitIncludes.Unlit,
// Custom Interpolator Support
customInterpolators = CoreCustomInterpDescriptors.Common
};
CorePasses.AddTargetSurfaceControlsToPass(ref result, target);
return result;
}
public static PassDescriptor DepthNormalOnly(UniversalTarget target)
{
var result = new PassDescriptor
{
// Definition
displayName = "DepthNormals",
referenceName = "SHADERPASS_DEPTHNORMALSONLY",
lightMode = "DepthNormalsOnly",
useInPreview = false,
// Template
passTemplatePath = UniversalTarget.kUberTemplatePath,
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
// Port Mask
validVertexBlocks = CoreBlockMasks.Vertex,
validPixelBlocks = UnlitBlockMasks.FragmentDepthNormals,
// Fields
structs = CoreStructCollections.Default,
requiredFields = UnlitRequiredFields.DepthNormalsOnly,
fieldDependencies = CoreFieldDependencies.Default,
// Conditional State
renderStates = CoreRenderStates.DepthNormalsOnly(target),
pragmas = CorePragmas.Forward,
defines = new DefineCollection(),
keywords = new KeywordCollection(),
includes = CoreIncludes.DepthNormalsOnly,
// Custom Interpolator Support
customInterpolators = CoreCustomInterpDescriptors.Common
};
CorePasses.AddTargetSurfaceControlsToPass(ref result, target);
return result;
}
#region PortMasks
static class UnlitBlockMasks
{
public static readonly BlockFieldDescriptor[] FragmentDepthNormals = new BlockFieldDescriptor[]
{
BlockFields.SurfaceDescription.NormalWS,
BlockFields.SurfaceDescription.Alpha,
BlockFields.SurfaceDescription.AlphaClipThreshold,
};
}
#endregion
#region RequiredFields
static class UnlitRequiredFields
{
public static readonly FieldCollection Unlit = new FieldCollection()
{
StructFields.Varyings.positionWS,
StructFields.Varyings.normalWS,
StructFields.Varyings.viewDirectionWS,
};
public static readonly FieldCollection DepthNormalsOnly = new FieldCollection()
{
StructFields.Varyings.normalWS,
};
}
#endregion
}
#endregion
#region Keywords
static class UnlitKeywords
{
public static readonly KeywordCollection UnlitBaseKeywords = new KeywordCollection()
{
// This contain lightmaps because without a proper custom lighting solution in Shadergraph,
// people start with the unlit then add lightmapping nodes to it.
// If we removed lightmaps from the unlit target this would ruin a lot of peoples days.
CoreKeywordDescriptors.StaticLightmap,
CoreKeywordDescriptors.DirectionalLightmapCombined,
CoreKeywordDescriptors.SampleGI,
CoreKeywordDescriptors.DBuffer,
CoreKeywordDescriptors.DebugDisplay,
};
}
#endregion
#region Includes
static class UnlitIncludes
{
const string kUnlitPass = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/UnlitPass.hlsl";
public static IncludeCollection Unlit = new IncludeCollection
{
// Pre-graph
{ CoreIncludes.CorePregraph },
{ CoreIncludes.ShaderGraphPregraph },
{ CoreIncludes.DBufferPregraph },
// Post-graph
{ CoreIncludes.CorePostgraph },
{ kUnlitPass, IncludeLocation.Postgraph },
};
}
#endregion
}
}