You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
349 lines
16 KiB
349 lines
16 KiB
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 |
|
} |
|
}
|
|
|