testss
This commit is contained in:
@@ -0,0 +1,756 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor.ShaderGraph;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.ShaderGraph.Legacy;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGraph
|
||||
{
|
||||
sealed class UniversalLitSubTarget : SubTarget<UniversalTarget>, ILegacyTarget
|
||||
{
|
||||
static readonly GUID kSourceCodeGuid = new GUID("d6c78107b64145745805d963de80cc17"); // UniversalLitSubTarget.cs
|
||||
|
||||
[SerializeField]
|
||||
WorkflowMode m_WorkflowMode = WorkflowMode.Metallic;
|
||||
|
||||
[SerializeField]
|
||||
NormalDropOffSpace m_NormalDropOffSpace = NormalDropOffSpace.Tangent;
|
||||
|
||||
[SerializeField]
|
||||
bool m_ClearCoat = false;
|
||||
|
||||
public UniversalLitSubTarget()
|
||||
{
|
||||
displayName = "Lit";
|
||||
}
|
||||
|
||||
public WorkflowMode workflowMode
|
||||
{
|
||||
get => m_WorkflowMode;
|
||||
set => m_WorkflowMode = value;
|
||||
}
|
||||
|
||||
public NormalDropOffSpace normalDropOffSpace
|
||||
{
|
||||
get => m_NormalDropOffSpace;
|
||||
set => m_NormalDropOffSpace = value;
|
||||
}
|
||||
|
||||
public bool clearCoat
|
||||
{
|
||||
get => m_ClearCoat;
|
||||
set => m_ClearCoat = value;
|
||||
}
|
||||
|
||||
private bool complexLit
|
||||
{
|
||||
get
|
||||
{
|
||||
// Rules for switching to ComplexLit with forward only pass
|
||||
return clearCoat; // && <complex feature>
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsActive() => true;
|
||||
|
||||
public override void Setup(ref TargetSetupContext context)
|
||||
{
|
||||
context.AddAssetDependency(kSourceCodeGuid, AssetCollection.Flags.SourceDependency);
|
||||
if (!context.HasCustomEditorForRenderPipeline(typeof(UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset)))
|
||||
context.AddCustomEditorForRenderPipeline("ShaderGraph.PBRMasterGUI", typeof(UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset)); // TODO: This should be owned by URP
|
||||
|
||||
// Process SubShaders
|
||||
SubShaderDescriptor[] litSubShaders = { SubShaders.LitComputeDOTS, SubShaders.LitGLES };
|
||||
SubShaderDescriptor[] complexLitSubShaders = { SubShaders.ComplexLitComputeDOTS, SubShaders.LitGLESForwardOnly};
|
||||
|
||||
// TODO: In the future:
|
||||
// We could take a copy of subshaders and dynamically modify them here.
|
||||
// For example, toggle "ComplexLit.ForwardOnlyPass.defines.ClearCoat" index/enable/disable to dynamically
|
||||
// remove clear coat code.
|
||||
// Currently ClearCoat is always on for a ComplexLit, but it's only used when ClearCoat is on.
|
||||
// An alternative is to rely on shader branches and reduce variants/unique graph generations.
|
||||
|
||||
SubShaderDescriptor[] subShaders = complexLit ? complexLitSubShaders : litSubShaders;
|
||||
|
||||
for (int i = 0; i < subShaders.Length; i++)
|
||||
{
|
||||
// Update Render State
|
||||
subShaders[i].renderType = target.renderType;
|
||||
subShaders[i].renderQueue = target.renderQueue;
|
||||
|
||||
context.AddSubShader(subShaders[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public override void GetFields(ref TargetFieldContext context)
|
||||
{
|
||||
var descs = context.blocks.Select(x => x.descriptor);
|
||||
// Surface Type & Blend Mode
|
||||
// These must be set per SubTarget as Sprite SubTargets override them
|
||||
context.AddField(UniversalFields.SurfaceOpaque, target.surfaceType == SurfaceType.Opaque);
|
||||
context.AddField(UniversalFields.SurfaceTransparent, target.surfaceType != SurfaceType.Opaque);
|
||||
context.AddField(UniversalFields.BlendAdd, target.surfaceType != SurfaceType.Opaque && target.alphaMode == AlphaMode.Additive);
|
||||
context.AddField(Fields.BlendAlpha, target.surfaceType != SurfaceType.Opaque && target.alphaMode == AlphaMode.Alpha);
|
||||
context.AddField(UniversalFields.BlendMultiply, target.surfaceType != SurfaceType.Opaque && target.alphaMode == AlphaMode.Multiply);
|
||||
context.AddField(UniversalFields.BlendPremultiply, target.surfaceType != SurfaceType.Opaque && target.alphaMode == AlphaMode.Premultiply);
|
||||
|
||||
// Lit
|
||||
context.AddField(UniversalFields.NormalDropOffOS, normalDropOffSpace == NormalDropOffSpace.Object);
|
||||
context.AddField(UniversalFields.NormalDropOffTS, normalDropOffSpace == NormalDropOffSpace.Tangent);
|
||||
context.AddField(UniversalFields.NormalDropOffWS, normalDropOffSpace == NormalDropOffSpace.World);
|
||||
context.AddField(UniversalFields.SpecularSetup, workflowMode == WorkflowMode.Specular);
|
||||
context.AddField(UniversalFields.Normal, descs.Contains(BlockFields.SurfaceDescription.NormalOS) ||
|
||||
descs.Contains(BlockFields.SurfaceDescription.NormalTS) ||
|
||||
descs.Contains(BlockFields.SurfaceDescription.NormalWS));
|
||||
// Complex Lit
|
||||
|
||||
// Template Predicates
|
||||
//context.AddField(UniversalFields.PredicateClearCoat, clearCoat);
|
||||
}
|
||||
|
||||
public override void GetActiveBlocks(ref TargetActiveBlockContext context)
|
||||
{
|
||||
context.AddBlock(BlockFields.SurfaceDescription.Smoothness);
|
||||
context.AddBlock(BlockFields.SurfaceDescription.NormalOS, normalDropOffSpace == NormalDropOffSpace.Object);
|
||||
context.AddBlock(BlockFields.SurfaceDescription.NormalTS, normalDropOffSpace == NormalDropOffSpace.Tangent);
|
||||
context.AddBlock(BlockFields.SurfaceDescription.NormalWS, normalDropOffSpace == NormalDropOffSpace.World);
|
||||
context.AddBlock(BlockFields.SurfaceDescription.Emission);
|
||||
context.AddBlock(BlockFields.SurfaceDescription.Occlusion);
|
||||
context.AddBlock(BlockFields.SurfaceDescription.Specular, workflowMode == WorkflowMode.Specular);
|
||||
context.AddBlock(BlockFields.SurfaceDescription.Metallic, workflowMode == WorkflowMode.Metallic);
|
||||
context.AddBlock(BlockFields.SurfaceDescription.Alpha, target.surfaceType == SurfaceType.Transparent || target.alphaClip);
|
||||
context.AddBlock(BlockFields.SurfaceDescription.AlphaClipThreshold, target.alphaClip);
|
||||
context.AddBlock(BlockFields.SurfaceDescription.CoatMask, clearCoat);
|
||||
context.AddBlock(BlockFields.SurfaceDescription.CoatSmoothness, clearCoat);
|
||||
}
|
||||
|
||||
public override void GetPropertiesGUI(ref TargetPropertyGUIContext context, Action onChange, Action<String> registerUndo)
|
||||
{
|
||||
context.AddProperty("Workflow", new EnumField(WorkflowMode.Metallic) { value = workflowMode }, (evt) =>
|
||||
{
|
||||
if (Equals(workflowMode, evt.newValue))
|
||||
return;
|
||||
|
||||
registerUndo("Change Workflow");
|
||||
workflowMode = (WorkflowMode)evt.newValue;
|
||||
onChange();
|
||||
});
|
||||
|
||||
context.AddProperty("Surface", new EnumField(SurfaceType.Opaque) { value = target.surfaceType }, (evt) =>
|
||||
{
|
||||
if (Equals(target.surfaceType, evt.newValue))
|
||||
return;
|
||||
|
||||
registerUndo("Change Surface");
|
||||
target.surfaceType = (SurfaceType)evt.newValue;
|
||||
onChange();
|
||||
});
|
||||
|
||||
context.AddProperty("Blend", new EnumField(AlphaMode.Alpha) { value = target.alphaMode }, target.surfaceType == SurfaceType.Transparent, (evt) =>
|
||||
{
|
||||
if (Equals(target.alphaMode, evt.newValue))
|
||||
return;
|
||||
|
||||
registerUndo("Change Blend");
|
||||
target.alphaMode = (AlphaMode)evt.newValue;
|
||||
onChange();
|
||||
});
|
||||
|
||||
context.AddProperty("Alpha Clip", new Toggle() { value = target.alphaClip }, (evt) =>
|
||||
{
|
||||
if (Equals(target.alphaClip, evt.newValue))
|
||||
return;
|
||||
|
||||
registerUndo("Change Alpha Clip");
|
||||
target.alphaClip = evt.newValue;
|
||||
onChange();
|
||||
});
|
||||
|
||||
context.AddProperty("Two Sided", new Toggle() { value = target.twoSided }, (evt) =>
|
||||
{
|
||||
if (Equals(target.twoSided, evt.newValue))
|
||||
return;
|
||||
|
||||
registerUndo("Change Two Sided");
|
||||
target.twoSided = evt.newValue;
|
||||
onChange();
|
||||
});
|
||||
|
||||
context.AddProperty("Fragment Normal Space", new EnumField(NormalDropOffSpace.Tangent) { value = normalDropOffSpace }, (evt) =>
|
||||
{
|
||||
if (Equals(normalDropOffSpace, evt.newValue))
|
||||
return;
|
||||
|
||||
registerUndo("Change Fragment Normal Space");
|
||||
normalDropOffSpace = (NormalDropOffSpace)evt.newValue;
|
||||
onChange();
|
||||
});
|
||||
|
||||
context.AddProperty("Clear Coat", new Toggle() { value = clearCoat }, (evt) =>
|
||||
{
|
||||
if (Equals(clearCoat, evt.newValue))
|
||||
return;
|
||||
|
||||
registerUndo("Change Clear Coat");
|
||||
clearCoat = evt.newValue;
|
||||
onChange();
|
||||
});
|
||||
}
|
||||
|
||||
public bool TryUpgradeFromMasterNode(IMasterNode1 masterNode, out Dictionary<BlockFieldDescriptor, int> blockMap)
|
||||
{
|
||||
blockMap = null;
|
||||
if (!(masterNode is PBRMasterNode1 pbrMasterNode))
|
||||
return false;
|
||||
|
||||
m_WorkflowMode = (WorkflowMode)pbrMasterNode.m_Model;
|
||||
m_NormalDropOffSpace = (NormalDropOffSpace)pbrMasterNode.m_NormalDropOffSpace;
|
||||
|
||||
// Handle mapping of Normal block specifically
|
||||
BlockFieldDescriptor normalBlock;
|
||||
switch (m_NormalDropOffSpace)
|
||||
{
|
||||
case NormalDropOffSpace.Object:
|
||||
normalBlock = BlockFields.SurfaceDescription.NormalOS;
|
||||
break;
|
||||
case NormalDropOffSpace.World:
|
||||
normalBlock = BlockFields.SurfaceDescription.NormalWS;
|
||||
break;
|
||||
default:
|
||||
normalBlock = BlockFields.SurfaceDescription.NormalTS;
|
||||
break;
|
||||
}
|
||||
|
||||
// PBRMasterNode adds/removes Metallic/Specular based on settings
|
||||
BlockFieldDescriptor specularMetallicBlock;
|
||||
int specularMetallicId;
|
||||
if (m_WorkflowMode == WorkflowMode.Specular)
|
||||
{
|
||||
specularMetallicBlock = BlockFields.SurfaceDescription.Specular;
|
||||
specularMetallicId = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
specularMetallicBlock = BlockFields.SurfaceDescription.Metallic;
|
||||
specularMetallicId = 2;
|
||||
}
|
||||
|
||||
// Set blockmap
|
||||
blockMap = new Dictionary<BlockFieldDescriptor, int>()
|
||||
{
|
||||
{ BlockFields.VertexDescription.Position, 9 },
|
||||
{ BlockFields.VertexDescription.Normal, 10 },
|
||||
{ BlockFields.VertexDescription.Tangent, 11 },
|
||||
{ BlockFields.SurfaceDescription.BaseColor, 0 },
|
||||
{ normalBlock, 1 },
|
||||
{ specularMetallicBlock, specularMetallicId },
|
||||
{ BlockFields.SurfaceDescription.Emission, 4 },
|
||||
{ BlockFields.SurfaceDescription.Smoothness, 5 },
|
||||
{ BlockFields.SurfaceDescription.Occlusion, 6 },
|
||||
{ BlockFields.SurfaceDescription.Alpha, 7 },
|
||||
{ BlockFields.SurfaceDescription.AlphaClipThreshold, 8 },
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#region SubShader
|
||||
static class SubShaders
|
||||
{
|
||||
// Overloads to do inline PassDescriptor modifications
|
||||
// NOTE: param order should match PassDescriptor field order for consistency
|
||||
#region PassVariant
|
||||
private static PassDescriptor PassVariant(in PassDescriptor source, PragmaCollection pragmas)
|
||||
{
|
||||
var result = source;
|
||||
result.pragmas = pragmas;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static PassDescriptor PassVariant(in PassDescriptor source, BlockFieldDescriptor[] vertexBlocks, BlockFieldDescriptor[] pixelBlocks, PragmaCollection pragmas, DefineCollection defines)
|
||||
{
|
||||
var result = source;
|
||||
result.validVertexBlocks = vertexBlocks;
|
||||
result.validPixelBlocks = pixelBlocks;
|
||||
result.pragmas = pragmas;
|
||||
result.defines = defines;
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// SM 4.5, compute with dots instancing
|
||||
public readonly static SubShaderDescriptor LitComputeDOTS = new SubShaderDescriptor()
|
||||
{
|
||||
pipelineTag = UniversalTarget.kPipelineTag,
|
||||
customTags = UniversalTarget.kLitMaterialTypeTag,
|
||||
generatesPreview = true,
|
||||
passes = new PassCollection
|
||||
{
|
||||
{ PassVariant(LitPasses.Forward, CorePragmas.DOTSForward) },
|
||||
{ LitPasses.GBuffer },
|
||||
{ PassVariant(CorePasses.ShadowCaster, CorePragmas.DOTSInstanced) },
|
||||
{ PassVariant(CorePasses.DepthOnly, CorePragmas.DOTSInstanced) },
|
||||
{ PassVariant(LitPasses.DepthNormalOnly, CorePragmas.DOTSInstanced) },
|
||||
{ PassVariant(LitPasses.Meta, CorePragmas.DOTSDefault) },
|
||||
{ PassVariant(LitPasses._2D, CorePragmas.DOTSDefault) },
|
||||
},
|
||||
};
|
||||
|
||||
// Similar to lit, but handles complex material features.
|
||||
// Always ForwardOnly and acts as forward fallback in deferred.
|
||||
// SM 4.5, compute with dots instancing
|
||||
public readonly static SubShaderDescriptor ComplexLitComputeDOTS = new SubShaderDescriptor()
|
||||
{
|
||||
pipelineTag = UniversalTarget.kPipelineTag,
|
||||
customTags = UniversalTarget.kLitMaterialTypeTag,
|
||||
generatesPreview = true,
|
||||
passes = new PassCollection
|
||||
{
|
||||
{ PassVariant(LitPasses.ForwardOnly, CoreBlockMasks.Vertex, LitBlockMasks.FragmentComplexLit, CorePragmas.DOTSForward, LitDefines.ComplexLit) },
|
||||
{ PassVariant(CorePasses.ShadowCaster, CorePragmas.DOTSInstanced) },
|
||||
{ PassVariant(CorePasses.DepthOnly, CorePragmas.DOTSInstanced) },
|
||||
{ PassVariant(LitPasses.DepthNormalOnly, CorePragmas.DOTSInstanced) },
|
||||
{ PassVariant(LitPasses.Meta, CorePragmas.DOTSDefault) },
|
||||
{ PassVariant(LitPasses._2D, CorePragmas.DOTSDefault) },
|
||||
},
|
||||
};
|
||||
|
||||
// SM 2.0, GLES
|
||||
public readonly static SubShaderDescriptor LitGLES = new SubShaderDescriptor()
|
||||
{
|
||||
pipelineTag = UniversalTarget.kPipelineTag,
|
||||
customTags = UniversalTarget.kLitMaterialTypeTag,
|
||||
generatesPreview = true,
|
||||
passes = new PassCollection
|
||||
{
|
||||
{ LitPasses.Forward },
|
||||
{ CorePasses.ShadowCaster },
|
||||
{ CorePasses.DepthOnly },
|
||||
{ LitPasses.DepthNormalOnly },
|
||||
{ LitPasses.Meta },
|
||||
{ LitPasses._2D },
|
||||
},
|
||||
};
|
||||
|
||||
// ForwardOnly pass for SM 2.0, GLES
|
||||
// Used as complex Lit SM 2.0 fallback for GLES. Drops advanced features and renders materials as Lit.
|
||||
public readonly static SubShaderDescriptor LitGLESForwardOnly = new SubShaderDescriptor()
|
||||
{
|
||||
pipelineTag = UniversalTarget.kPipelineTag,
|
||||
customTags = UniversalTarget.kLitMaterialTypeTag,
|
||||
generatesPreview = true,
|
||||
passes = new PassCollection
|
||||
{
|
||||
{ LitPasses.ForwardOnly },
|
||||
{ CorePasses.ShadowCaster },
|
||||
{ CorePasses.DepthOnly },
|
||||
{ LitPasses.DepthNormalOnly },
|
||||
{ LitPasses.Meta },
|
||||
{ LitPasses._2D },
|
||||
},
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Passes
|
||||
static class LitPasses
|
||||
{
|
||||
public static PassDescriptor Forward = new PassDescriptor
|
||||
{
|
||||
// Definition
|
||||
displayName = "Universal Forward",
|
||||
referenceName = "SHADERPASS_FORWARD",
|
||||
lightMode = "UniversalForward",
|
||||
useInPreview = true,
|
||||
|
||||
// Template
|
||||
passTemplatePath = GenerationUtils.GetDefaultTemplatePath("PassMesh.template"),
|
||||
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = CoreBlockMasks.Vertex,
|
||||
validPixelBlocks = LitBlockMasks.FragmentLit,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
requiredFields = LitRequiredFields.Forward,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.Default,
|
||||
pragmas = CorePragmas.Forward, // NOTE: SM 2.0 only GL
|
||||
keywords = LitKeywords.Forward,
|
||||
includes = LitIncludes.Forward,
|
||||
};
|
||||
|
||||
public static PassDescriptor ForwardOnly = new PassDescriptor
|
||||
{
|
||||
// Definition
|
||||
displayName = "Universal Forward Only",
|
||||
referenceName = "SHADERPASS_FORWARDONLY",
|
||||
lightMode = "UniversalForwardOnly",
|
||||
useInPreview = true,
|
||||
|
||||
// Template
|
||||
passTemplatePath = GenerationUtils.GetDefaultTemplatePath("PassMesh.template"),
|
||||
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = CoreBlockMasks.Vertex,
|
||||
validPixelBlocks = LitBlockMasks.FragmentLit,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
requiredFields = LitRequiredFields.Forward,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.Default,
|
||||
pragmas = CorePragmas.Forward, // NOTE: SM 2.0 only GL
|
||||
keywords = LitKeywords.Forward,
|
||||
includes = LitIncludes.Forward,
|
||||
};
|
||||
|
||||
// Deferred only in SM4.5, MRT not supported in GLES2
|
||||
public static PassDescriptor GBuffer = new PassDescriptor
|
||||
{
|
||||
// Definition
|
||||
displayName = "GBuffer",
|
||||
referenceName = "SHADERPASS_GBUFFER",
|
||||
lightMode = "UniversalGBuffer",
|
||||
|
||||
// Template
|
||||
passTemplatePath = GenerationUtils.GetDefaultTemplatePath("PassMesh.template"),
|
||||
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = CoreBlockMasks.Vertex,
|
||||
validPixelBlocks = LitBlockMasks.FragmentLit,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
requiredFields = LitRequiredFields.GBuffer,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.Default,
|
||||
pragmas = CorePragmas.DOTSGBuffer,
|
||||
keywords = LitKeywords.GBuffer,
|
||||
includes = LitIncludes.GBuffer,
|
||||
};
|
||||
|
||||
public static PassDescriptor Meta = new PassDescriptor()
|
||||
{
|
||||
// Definition
|
||||
displayName = "Meta",
|
||||
referenceName = "SHADERPASS_META",
|
||||
lightMode = "Meta",
|
||||
|
||||
// Template
|
||||
passTemplatePath = GenerationUtils.GetDefaultTemplatePath("PassMesh.template"),
|
||||
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = CoreBlockMasks.Vertex,
|
||||
validPixelBlocks = LitBlockMasks.FragmentMeta,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
requiredFields = LitRequiredFields.Meta,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.Meta,
|
||||
pragmas = CorePragmas.Default,
|
||||
keywords = LitKeywords.Meta,
|
||||
includes = LitIncludes.Meta,
|
||||
};
|
||||
|
||||
public static readonly PassDescriptor _2D = new PassDescriptor()
|
||||
{
|
||||
// Definition
|
||||
referenceName = "SHADERPASS_2D",
|
||||
lightMode = "Universal2D",
|
||||
|
||||
// Template
|
||||
passTemplatePath = GenerationUtils.GetDefaultTemplatePath("PassMesh.template"),
|
||||
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = CoreBlockMasks.Vertex,
|
||||
validPixelBlocks = CoreBlockMasks.FragmentColorAlpha,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.Default,
|
||||
pragmas = CorePragmas.Instanced,
|
||||
includes = LitIncludes._2D,
|
||||
};
|
||||
|
||||
public static readonly PassDescriptor DepthNormalOnly = new PassDescriptor()
|
||||
{
|
||||
// Definition
|
||||
displayName = "DepthNormals",
|
||||
referenceName = "SHADERPASS_DEPTHNORMALSONLY",
|
||||
lightMode = "DepthNormals",
|
||||
useInPreview = false,
|
||||
|
||||
// Template
|
||||
passTemplatePath = GenerationUtils.GetDefaultTemplatePath("PassMesh.template"),
|
||||
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = CoreBlockMasks.Vertex,
|
||||
validPixelBlocks = LitBlockMasks.FragmentDepthNormals,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
requiredFields = LitRequiredFields.DepthNormals,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.DepthNormalsOnly,
|
||||
pragmas = CorePragmas.Instanced,
|
||||
includes = CoreIncludes.DepthNormalsOnly,
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region PortMasks
|
||||
static class LitBlockMasks
|
||||
{
|
||||
public static readonly BlockFieldDescriptor[] FragmentLit = new BlockFieldDescriptor[]
|
||||
{
|
||||
BlockFields.SurfaceDescription.BaseColor,
|
||||
BlockFields.SurfaceDescription.NormalOS,
|
||||
BlockFields.SurfaceDescription.NormalTS,
|
||||
BlockFields.SurfaceDescription.NormalWS,
|
||||
BlockFields.SurfaceDescription.Emission,
|
||||
BlockFields.SurfaceDescription.Metallic,
|
||||
BlockFields.SurfaceDescription.Specular,
|
||||
BlockFields.SurfaceDescription.Smoothness,
|
||||
BlockFields.SurfaceDescription.Occlusion,
|
||||
BlockFields.SurfaceDescription.Alpha,
|
||||
BlockFields.SurfaceDescription.AlphaClipThreshold,
|
||||
};
|
||||
|
||||
public static readonly BlockFieldDescriptor[] FragmentComplexLit = new BlockFieldDescriptor[]
|
||||
{
|
||||
BlockFields.SurfaceDescription.BaseColor,
|
||||
BlockFields.SurfaceDescription.NormalOS,
|
||||
BlockFields.SurfaceDescription.NormalTS,
|
||||
BlockFields.SurfaceDescription.NormalWS,
|
||||
BlockFields.SurfaceDescription.Emission,
|
||||
BlockFields.SurfaceDescription.Metallic,
|
||||
BlockFields.SurfaceDescription.Specular,
|
||||
BlockFields.SurfaceDescription.Smoothness,
|
||||
BlockFields.SurfaceDescription.Occlusion,
|
||||
BlockFields.SurfaceDescription.Alpha,
|
||||
BlockFields.SurfaceDescription.AlphaClipThreshold,
|
||||
BlockFields.SurfaceDescription.CoatMask,
|
||||
BlockFields.SurfaceDescription.CoatSmoothness,
|
||||
};
|
||||
|
||||
public static readonly BlockFieldDescriptor[] FragmentMeta = new BlockFieldDescriptor[]
|
||||
{
|
||||
BlockFields.SurfaceDescription.BaseColor,
|
||||
BlockFields.SurfaceDescription.Emission,
|
||||
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 RequiredFields
|
||||
static class LitRequiredFields
|
||||
{
|
||||
public static readonly FieldCollection Forward = new FieldCollection()
|
||||
{
|
||||
StructFields.Attributes.uv1, // needed for meta vertex position
|
||||
StructFields.Varyings.positionWS,
|
||||
StructFields.Varyings.normalWS,
|
||||
StructFields.Varyings.tangentWS, // needed for vertex lighting
|
||||
StructFields.Varyings.viewDirectionWS,
|
||||
UniversalStructFields.Varyings.lightmapUV,
|
||||
UniversalStructFields.Varyings.sh,
|
||||
UniversalStructFields.Varyings.fogFactorAndVertexLight, // fog and vertex lighting, vert input is dependency
|
||||
UniversalStructFields.Varyings.shadowCoord, // shadow coord, vert input is dependency
|
||||
};
|
||||
|
||||
public static readonly FieldCollection GBuffer = new FieldCollection()
|
||||
{
|
||||
StructFields.Attributes.uv1, // needed for meta vertex position
|
||||
StructFields.Varyings.positionWS,
|
||||
StructFields.Varyings.normalWS,
|
||||
StructFields.Varyings.tangentWS, // needed for vertex lighting
|
||||
StructFields.Varyings.viewDirectionWS,
|
||||
UniversalStructFields.Varyings.lightmapUV,
|
||||
UniversalStructFields.Varyings.sh,
|
||||
UniversalStructFields.Varyings.fogFactorAndVertexLight, // fog and vertex lighting, vert input is dependency
|
||||
UniversalStructFields.Varyings.shadowCoord, // shadow coord, vert input is dependency
|
||||
};
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
public static readonly FieldCollection Meta = new FieldCollection()
|
||||
{
|
||||
StructFields.Attributes.uv1, // needed for meta vertex position
|
||||
StructFields.Attributes.uv2, //needed for meta vertex position
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Defines
|
||||
static class LitDefines
|
||||
{
|
||||
public static readonly KeywordDescriptor ClearCoat = new KeywordDescriptor()
|
||||
{
|
||||
displayName = "Clear Coat",
|
||||
referenceName = "_CLEARCOAT 1",
|
||||
type = KeywordType.Boolean,
|
||||
definition = KeywordDefinition.ShaderFeature,
|
||||
scope = KeywordScope.Local,
|
||||
};
|
||||
|
||||
public static readonly DefineCollection ComplexLit = new DefineCollection()
|
||||
{
|
||||
{ClearCoat, 1},
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Keywords
|
||||
static class LitKeywords
|
||||
{
|
||||
public static readonly KeywordDescriptor GBufferNormalsOct = new KeywordDescriptor()
|
||||
{
|
||||
displayName = "GBuffer normal octaedron encoding",
|
||||
referenceName = "_GBUFFER_NORMALS_OCT",
|
||||
type = KeywordType.Boolean,
|
||||
definition = KeywordDefinition.MultiCompile,
|
||||
scope = KeywordScope.Global,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
public static readonly KeywordCollection Forward = new KeywordCollection
|
||||
{
|
||||
{ ScreenSpaceAmbientOcclusion },
|
||||
{ CoreKeywordDescriptors.Lightmap },
|
||||
{ CoreKeywordDescriptors.DirectionalLightmapCombined },
|
||||
{ CoreKeywordDescriptors.MainLightShadows },
|
||||
{ CoreKeywordDescriptors.AdditionalLights },
|
||||
{ CoreKeywordDescriptors.AdditionalLightShadows },
|
||||
{ CoreKeywordDescriptors.ShadowsSoft },
|
||||
{ CoreKeywordDescriptors.LightmapShadowMixing },
|
||||
{ CoreKeywordDescriptors.ShadowsShadowmask },
|
||||
};
|
||||
|
||||
public static readonly KeywordCollection GBuffer = new KeywordCollection
|
||||
{
|
||||
{ CoreKeywordDescriptors.Lightmap },
|
||||
{ CoreKeywordDescriptors.DirectionalLightmapCombined },
|
||||
{ CoreKeywordDescriptors.MainLightShadows },
|
||||
{ CoreKeywordDescriptors.ShadowsSoft },
|
||||
{ CoreKeywordDescriptors.MixedLightingSubtractive },
|
||||
{ GBufferNormalsOct },
|
||||
};
|
||||
|
||||
public static readonly KeywordCollection Meta = new KeywordCollection
|
||||
{
|
||||
{ CoreKeywordDescriptors.SmoothnessChannel },
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Includes
|
||||
static class LitIncludes
|
||||
{
|
||||
const string kShadows = "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl";
|
||||
const string kMetaInput = "Packages/com.unity.render-pipelines.universal/ShaderLibrary/MetaInput.hlsl";
|
||||
const string kForwardPass = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/PBRForwardPass.hlsl";
|
||||
const string kGBuffer = "Packages/com.unity.render-pipelines.universal/ShaderLibrary/UnityGBuffer.hlsl";
|
||||
const string kPBRGBufferPass = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/PBRGBufferPass.hlsl";
|
||||
const string kLightingMetaPass = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/LightingMetaPass.hlsl";
|
||||
const string k2DPass = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/PBR2DPass.hlsl";
|
||||
|
||||
public static readonly IncludeCollection Forward = new IncludeCollection
|
||||
{
|
||||
// Pre-graph
|
||||
{ CoreIncludes.CorePregraph },
|
||||
{ kShadows, IncludeLocation.Pregraph },
|
||||
{ CoreIncludes.ShaderGraphPregraph },
|
||||
|
||||
// Post-graph
|
||||
{ CoreIncludes.CorePostgraph },
|
||||
{ kForwardPass, IncludeLocation.Postgraph },
|
||||
};
|
||||
|
||||
public static readonly IncludeCollection GBuffer = new IncludeCollection
|
||||
{
|
||||
// Pre-graph
|
||||
{ CoreIncludes.CorePregraph },
|
||||
{ kShadows, IncludeLocation.Pregraph },
|
||||
{ CoreIncludes.ShaderGraphPregraph },
|
||||
|
||||
// Post-graph
|
||||
{ CoreIncludes.CorePostgraph },
|
||||
{ kGBuffer, IncludeLocation.Postgraph },
|
||||
{ kPBRGBufferPass, IncludeLocation.Postgraph },
|
||||
};
|
||||
|
||||
public static readonly IncludeCollection Meta = new IncludeCollection
|
||||
{
|
||||
// Pre-graph
|
||||
{ CoreIncludes.CorePregraph },
|
||||
{ CoreIncludes.ShaderGraphPregraph },
|
||||
{ kMetaInput, IncludeLocation.Pregraph },
|
||||
|
||||
// Post-graph
|
||||
{ CoreIncludes.CorePostgraph },
|
||||
{ kLightingMetaPass, IncludeLocation.Postgraph },
|
||||
};
|
||||
|
||||
public static readonly IncludeCollection _2D = new IncludeCollection
|
||||
{
|
||||
// Pre-graph
|
||||
{ CoreIncludes.CorePregraph },
|
||||
{ CoreIncludes.ShaderGraphPregraph },
|
||||
|
||||
// Post-graph
|
||||
{ CoreIncludes.CorePostgraph },
|
||||
{ k2DPass, IncludeLocation.Postgraph },
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,287 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor.ShaderGraph;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEditor.Experimental.Rendering.Universal;
|
||||
using UnityEditor.ShaderGraph.Legacy;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGraph
|
||||
{
|
||||
sealed class UniversalSpriteLitSubTarget : SubTarget<UniversalTarget>, ILegacyTarget
|
||||
{
|
||||
static readonly GUID kSourceCodeGuid = new GUID("ea1514729d7120344b27dcd67fbf34de"); // UniversalSpriteLitSubTarget.cs
|
||||
|
||||
public UniversalSpriteLitSubTarget()
|
||||
{
|
||||
displayName = "Sprite Lit";
|
||||
}
|
||||
|
||||
public override bool IsActive() => true;
|
||||
|
||||
public override void Setup(ref TargetSetupContext context)
|
||||
{
|
||||
context.AddAssetDependency(kSourceCodeGuid, AssetCollection.Flags.SourceDependency);
|
||||
context.AddSubShader(SubShaders.SpriteLit);
|
||||
}
|
||||
|
||||
public override void GetFields(ref TargetFieldContext context)
|
||||
{
|
||||
// Only support SpriteColor legacy block if BaseColor/Alpha are not active
|
||||
var descs = context.blocks.Select(x => x.descriptor);
|
||||
bool useLegacyBlocks = !descs.Contains(BlockFields.SurfaceDescription.BaseColor) && !descs.Contains(BlockFields.SurfaceDescription.Alpha);
|
||||
context.AddField(CoreFields.UseLegacySpriteBlocks, useLegacyBlocks);
|
||||
|
||||
// Surface Type & Blend Mode
|
||||
context.AddField(UniversalFields.SurfaceTransparent);
|
||||
context.AddField(Fields.BlendAlpha);
|
||||
context.AddField(Fields.DoubleSided);
|
||||
}
|
||||
|
||||
public override void GetActiveBlocks(ref TargetActiveBlockContext context)
|
||||
{
|
||||
// Only support SpriteColor legacy block if BaseColor/Alpha are not active
|
||||
bool useLegacyBlocks = !context.currentBlocks.Contains(BlockFields.SurfaceDescription.BaseColor) && !context.currentBlocks.Contains(BlockFields.SurfaceDescription.Alpha);
|
||||
context.AddBlock(BlockFields.SurfaceDescriptionLegacy.SpriteColor, useLegacyBlocks);
|
||||
|
||||
context.AddBlock(UniversalBlockFields.SurfaceDescription.SpriteMask);
|
||||
context.AddBlock(BlockFields.SurfaceDescription.NormalTS);
|
||||
context.AddBlock(BlockFields.SurfaceDescription.Alpha);
|
||||
}
|
||||
|
||||
public override void GetPropertiesGUI(ref TargetPropertyGUIContext context, Action onChange, Action<String> registerUndo)
|
||||
{
|
||||
}
|
||||
|
||||
public bool TryUpgradeFromMasterNode(IMasterNode1 masterNode, out Dictionary<BlockFieldDescriptor, int> blockMap)
|
||||
{
|
||||
blockMap = null;
|
||||
if (!(masterNode is SpriteLitMasterNode1 spriteLitMasterNode))
|
||||
return false;
|
||||
|
||||
// Set blockmap
|
||||
blockMap = new Dictionary<BlockFieldDescriptor, int>()
|
||||
{
|
||||
{ BlockFields.VertexDescription.Position, 9 },
|
||||
{ BlockFields.VertexDescription.Normal, 10 },
|
||||
{ BlockFields.VertexDescription.Tangent, 11 },
|
||||
{ BlockFields.SurfaceDescriptionLegacy.SpriteColor, 0 },
|
||||
{ UniversalBlockFields.SurfaceDescription.SpriteMask, 1 },
|
||||
{ BlockFields.SurfaceDescription.NormalTS, 2 },
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#region SubShader
|
||||
static class SubShaders
|
||||
{
|
||||
public static SubShaderDescriptor SpriteLit = new SubShaderDescriptor()
|
||||
{
|
||||
pipelineTag = UniversalTarget.kPipelineTag,
|
||||
customTags = UniversalTarget.kLitMaterialTypeTag,
|
||||
renderType = $"{RenderType.Transparent}",
|
||||
renderQueue = $"{UnityEditor.ShaderGraph.RenderQueue.Transparent}",
|
||||
generatesPreview = true,
|
||||
passes = new PassCollection
|
||||
{
|
||||
{ SpriteLitPasses.Lit },
|
||||
{ SpriteLitPasses.Normal },
|
||||
{ SpriteLitPasses.Forward },
|
||||
},
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Passes
|
||||
static class SpriteLitPasses
|
||||
{
|
||||
public static PassDescriptor Lit = new PassDescriptor
|
||||
{
|
||||
// Definition
|
||||
displayName = "Sprite Lit",
|
||||
referenceName = "SHADERPASS_SPRITELIT",
|
||||
lightMode = "Universal2D",
|
||||
useInPreview = true,
|
||||
|
||||
// Template
|
||||
passTemplatePath = GenerationUtils.GetDefaultTemplatePath("PassMesh.template"),
|
||||
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = CoreBlockMasks.Vertex,
|
||||
validPixelBlocks = SpriteLitBlockMasks.FragmentLit,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
requiredFields = SpriteLitRequiredFields.Lit,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.Default,
|
||||
pragmas = CorePragmas._2DDefault,
|
||||
keywords = SpriteLitKeywords.Lit,
|
||||
includes = SpriteLitIncludes.Lit,
|
||||
};
|
||||
|
||||
public static PassDescriptor Normal = new PassDescriptor
|
||||
{
|
||||
// Definition
|
||||
displayName = "Sprite Normal",
|
||||
referenceName = "SHADERPASS_SPRITENORMAL",
|
||||
lightMode = "NormalsRendering",
|
||||
useInPreview = true,
|
||||
|
||||
// Template
|
||||
passTemplatePath = GenerationUtils.GetDefaultTemplatePath("PassMesh.template"),
|
||||
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = CoreBlockMasks.Vertex,
|
||||
validPixelBlocks = SpriteLitBlockMasks.FragmentForwardNormal,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
requiredFields = SpriteLitRequiredFields.Normal,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.Default,
|
||||
pragmas = CorePragmas._2DDefault,
|
||||
includes = SpriteLitIncludes.Normal,
|
||||
};
|
||||
|
||||
public static PassDescriptor Forward = new PassDescriptor
|
||||
{
|
||||
// Definition
|
||||
displayName = "Sprite Forward",
|
||||
referenceName = "SHADERPASS_SPRITEFORWARD",
|
||||
lightMode = "UniversalForward",
|
||||
useInPreview = true,
|
||||
|
||||
// Template
|
||||
passTemplatePath = GenerationUtils.GetDefaultTemplatePath("PassMesh.template"),
|
||||
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = CoreBlockMasks.Vertex,
|
||||
validPixelBlocks = SpriteLitBlockMasks.FragmentForwardNormal,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
requiredFields = SpriteLitRequiredFields.Forward,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.Default,
|
||||
pragmas = CorePragmas._2DDefault,
|
||||
includes = SpriteLitIncludes.Forward,
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region PortMasks
|
||||
static class SpriteLitBlockMasks
|
||||
{
|
||||
public static BlockFieldDescriptor[] FragmentLit = new BlockFieldDescriptor[]
|
||||
{
|
||||
BlockFields.SurfaceDescription.BaseColor,
|
||||
BlockFields.SurfaceDescriptionLegacy.SpriteColor,
|
||||
BlockFields.SurfaceDescription.Alpha,
|
||||
UniversalBlockFields.SurfaceDescription.SpriteMask,
|
||||
};
|
||||
|
||||
public static BlockFieldDescriptor[] FragmentForwardNormal = new BlockFieldDescriptor[]
|
||||
{
|
||||
BlockFields.SurfaceDescription.BaseColor,
|
||||
BlockFields.SurfaceDescriptionLegacy.SpriteColor,
|
||||
BlockFields.SurfaceDescription.Alpha,
|
||||
BlockFields.SurfaceDescription.NormalTS,
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RequiredFields
|
||||
static class SpriteLitRequiredFields
|
||||
{
|
||||
public static FieldCollection Lit = new FieldCollection()
|
||||
{
|
||||
StructFields.Varyings.color,
|
||||
StructFields.Varyings.texCoord0,
|
||||
StructFields.Varyings.screenPosition,
|
||||
};
|
||||
|
||||
public static FieldCollection Normal = new FieldCollection()
|
||||
{
|
||||
StructFields.Varyings.normalWS,
|
||||
StructFields.Varyings.tangentWS,
|
||||
};
|
||||
|
||||
public static FieldCollection Forward = new FieldCollection()
|
||||
{
|
||||
StructFields.Varyings.color,
|
||||
StructFields.Varyings.texCoord0,
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Keywords
|
||||
static class SpriteLitKeywords
|
||||
{
|
||||
public static KeywordCollection Lit = new KeywordCollection
|
||||
{
|
||||
{ CoreKeywordDescriptors.ShapeLightType0 },
|
||||
{ CoreKeywordDescriptors.ShapeLightType1 },
|
||||
{ CoreKeywordDescriptors.ShapeLightType2 },
|
||||
{ CoreKeywordDescriptors.ShapeLightType3 },
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Includes
|
||||
static class SpriteLitIncludes
|
||||
{
|
||||
const string k2DLightingUtil = "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/LightingUtility.hlsl";
|
||||
const string k2DNormal = "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/NormalsRenderingShared.hlsl";
|
||||
const string kSpriteLitPass = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/SpriteLitPass.hlsl";
|
||||
const string kSpriteNormalPass = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/SpriteNormalPass.hlsl";
|
||||
const string kSpriteForwardPass = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/SpriteForwardPass.hlsl";
|
||||
|
||||
public static IncludeCollection Lit = new IncludeCollection
|
||||
{
|
||||
// Pre-graph
|
||||
{ CoreIncludes.CorePregraph },
|
||||
{ CoreIncludes.ShaderGraphPregraph },
|
||||
{ k2DLightingUtil, IncludeLocation.Pregraph },
|
||||
|
||||
// Post-graph
|
||||
{ CoreIncludes.CorePostgraph },
|
||||
{ kSpriteLitPass, IncludeLocation.Postgraph },
|
||||
};
|
||||
|
||||
public static IncludeCollection Normal = new IncludeCollection
|
||||
{
|
||||
// Pre-graph
|
||||
{ CoreIncludes.CorePregraph },
|
||||
{ CoreIncludes.ShaderGraphPregraph },
|
||||
{ k2DNormal, IncludeLocation.Pregraph },
|
||||
|
||||
// Post-graph
|
||||
{ CoreIncludes.CorePostgraph },
|
||||
{ kSpriteNormalPass, IncludeLocation.Postgraph },
|
||||
};
|
||||
|
||||
public static IncludeCollection Forward = new IncludeCollection
|
||||
{
|
||||
// Pre-graph
|
||||
{ CoreIncludes.CorePregraph },
|
||||
{ CoreIncludes.ShaderGraphPregraph },
|
||||
|
||||
// Post-graph
|
||||
{ CoreIncludes.CorePostgraph },
|
||||
{ kSpriteForwardPass, IncludeLocation.Postgraph },
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,195 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor.ShaderGraph;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEditor.Experimental.Rendering.Universal;
|
||||
using UnityEditor.ShaderGraph.Legacy;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGraph
|
||||
{
|
||||
sealed class UniversalSpriteUnlitSubTarget : SubTarget<UniversalTarget>, ILegacyTarget
|
||||
{
|
||||
static readonly GUID kSourceCodeGuid = new GUID("ed7c0aacec26e9646b45c96fb318e5a3"); // UniversalSpriteUnlitSubTarget.cs
|
||||
|
||||
public UniversalSpriteUnlitSubTarget()
|
||||
{
|
||||
displayName = "Sprite Unlit";
|
||||
}
|
||||
|
||||
public override bool IsActive() => true;
|
||||
|
||||
public override void Setup(ref TargetSetupContext context)
|
||||
{
|
||||
context.AddAssetDependency(kSourceCodeGuid, AssetCollection.Flags.SourceDependency);
|
||||
context.AddSubShader(SubShaders.SpriteUnlit);
|
||||
}
|
||||
|
||||
public override void GetFields(ref TargetFieldContext context)
|
||||
{
|
||||
var descs = context.blocks.Select(x => x.descriptor);
|
||||
// Only support SpriteColor legacy block if BaseColor/Alpha are not active
|
||||
bool useLegacyBlocks = !descs.Contains(BlockFields.SurfaceDescription.BaseColor) && !descs.Contains(BlockFields.SurfaceDescription.Alpha);
|
||||
context.AddField(CoreFields.UseLegacySpriteBlocks, useLegacyBlocks);
|
||||
|
||||
// Surface Type & Blend Mode
|
||||
context.AddField(UniversalFields.SurfaceTransparent);
|
||||
context.AddField(Fields.BlendAlpha);
|
||||
context.AddField(Fields.DoubleSided);
|
||||
}
|
||||
|
||||
public override void GetActiveBlocks(ref TargetActiveBlockContext context)
|
||||
{
|
||||
// Only support SpriteColor legacy block if BaseColor/Alpha are not active
|
||||
bool useLegacyBlocks = !context.currentBlocks.Contains(BlockFields.SurfaceDescription.BaseColor) && !context.currentBlocks.Contains(BlockFields.SurfaceDescription.Alpha);
|
||||
context.AddBlock(BlockFields.SurfaceDescriptionLegacy.SpriteColor, useLegacyBlocks);
|
||||
|
||||
context.AddBlock(BlockFields.SurfaceDescription.Alpha);
|
||||
}
|
||||
|
||||
public override void GetPropertiesGUI(ref TargetPropertyGUIContext context, Action onChange, Action<String> registerUndo)
|
||||
{
|
||||
}
|
||||
|
||||
public bool TryUpgradeFromMasterNode(IMasterNode1 masterNode, out Dictionary<BlockFieldDescriptor, int> blockMap)
|
||||
{
|
||||
blockMap = null;
|
||||
if (!(masterNode is SpriteUnlitMasterNode1 spriteUnlitMasterNode))
|
||||
return false;
|
||||
|
||||
// Set blockmap
|
||||
blockMap = new Dictionary<BlockFieldDescriptor, int>()
|
||||
{
|
||||
{ BlockFields.VertexDescription.Position, 9 },
|
||||
{ BlockFields.VertexDescription.Normal, 10 },
|
||||
{ BlockFields.VertexDescription.Tangent, 11 },
|
||||
{ BlockFields.SurfaceDescriptionLegacy.SpriteColor, 0 },
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#region SubShader
|
||||
static class SubShaders
|
||||
{
|
||||
public static SubShaderDescriptor SpriteUnlit = new SubShaderDescriptor()
|
||||
{
|
||||
pipelineTag = UniversalTarget.kPipelineTag,
|
||||
customTags = UniversalTarget.kUnlitMaterialTypeTag,
|
||||
renderType = $"{RenderType.Transparent}",
|
||||
renderQueue = $"{UnityEditor.ShaderGraph.RenderQueue.Transparent}",
|
||||
generatesPreview = true,
|
||||
passes = new PassCollection
|
||||
{
|
||||
{ SpriteUnlitPasses.Unlit },
|
||||
{ SpriteUnlitPasses.Forward },
|
||||
},
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Passes
|
||||
static class SpriteUnlitPasses
|
||||
{
|
||||
public static PassDescriptor Unlit = new PassDescriptor
|
||||
{
|
||||
// Definition
|
||||
displayName = "Sprite Unlit",
|
||||
referenceName = "SHADERPASS_SPRITEUNLIT",
|
||||
lightMode = "Universal2D",
|
||||
useInPreview = true,
|
||||
|
||||
|
||||
// Template
|
||||
passTemplatePath = GenerationUtils.GetDefaultTemplatePath("PassMesh.template"),
|
||||
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = CoreBlockMasks.Vertex,
|
||||
validPixelBlocks = SpriteUnlitBlockMasks.Fragment,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
requiredFields = SpriteUnlitRequiredFields.Unlit,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.Default,
|
||||
pragmas = CorePragmas._2DDefault,
|
||||
includes = SpriteUnlitIncludes.Unlit,
|
||||
};
|
||||
|
||||
public static PassDescriptor Forward = new PassDescriptor
|
||||
{
|
||||
// Definition
|
||||
displayName = "Sprite Unlit",
|
||||
referenceName = "SHADERPASS_SPRITEFORWARD",
|
||||
lightMode = "UniversalForward",
|
||||
useInPreview = true,
|
||||
|
||||
|
||||
// Template
|
||||
passTemplatePath = GenerationUtils.GetDefaultTemplatePath("PassMesh.template"),
|
||||
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = CoreBlockMasks.Vertex,
|
||||
validPixelBlocks = SpriteUnlitBlockMasks.Fragment,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
requiredFields = SpriteUnlitRequiredFields.Unlit,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.Default,
|
||||
pragmas = CorePragmas._2DDefault,
|
||||
includes = SpriteUnlitIncludes.Unlit,
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region PortMasks
|
||||
static class SpriteUnlitBlockMasks
|
||||
{
|
||||
public static BlockFieldDescriptor[] Fragment = new BlockFieldDescriptor[]
|
||||
{
|
||||
BlockFields.SurfaceDescription.BaseColor,
|
||||
BlockFields.SurfaceDescriptionLegacy.SpriteColor,
|
||||
BlockFields.SurfaceDescription.Alpha,
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RequiredFields
|
||||
static class SpriteUnlitRequiredFields
|
||||
{
|
||||
public static FieldCollection Unlit = new FieldCollection()
|
||||
{
|
||||
StructFields.Attributes.color,
|
||||
StructFields.Attributes.uv0,
|
||||
StructFields.Varyings.color,
|
||||
StructFields.Varyings.texCoord0,
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Includes
|
||||
static class SpriteUnlitIncludes
|
||||
{
|
||||
const string kSpriteUnlitPass = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/SpriteUnlitPass.hlsl";
|
||||
|
||||
public static IncludeCollection Unlit = new IncludeCollection
|
||||
{
|
||||
// Pre-graph
|
||||
{ CoreIncludes.CorePregraph },
|
||||
{ CoreIncludes.ShaderGraphPregraph },
|
||||
|
||||
// Post-graph
|
||||
{ CoreIncludes.CorePostgraph },
|
||||
{ kSpriteUnlitPass, IncludeLocation.Postgraph },
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,864 @@
|
||||
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;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGraph
|
||||
{
|
||||
public enum MaterialType
|
||||
{
|
||||
Lit,
|
||||
Unlit,
|
||||
SpriteLit,
|
||||
SpriteUnlit,
|
||||
}
|
||||
|
||||
public enum WorkflowMode
|
||||
{
|
||||
Specular,
|
||||
Metallic,
|
||||
}
|
||||
|
||||
enum SurfaceType
|
||||
{
|
||||
Opaque,
|
||||
Transparent,
|
||||
}
|
||||
|
||||
enum AlphaMode
|
||||
{
|
||||
Alpha,
|
||||
Premultiply,
|
||||
Additive,
|
||||
Multiply,
|
||||
}
|
||||
|
||||
sealed class UniversalTarget : Target, ILegacyTarget
|
||||
{
|
||||
// Constants
|
||||
static readonly GUID kSourceCodeGuid = new GUID("8c72f47fdde33b14a9340e325ce56f4d"); // UniversalTarget.cs
|
||||
public const string kPipelineTag = "UniversalPipeline";
|
||||
public const string kLitMaterialTypeTag = "\"UniversalMaterialType\" = \"Lit\"";
|
||||
public const string kUnlitMaterialTypeTag = "\"UniversalMaterialType\" = \"Unlit\"";
|
||||
|
||||
// SubTarget
|
||||
List<SubTarget> m_SubTargets;
|
||||
List<string> m_SubTargetNames;
|
||||
int activeSubTargetIndex => m_SubTargets.IndexOf(m_ActiveSubTarget);
|
||||
|
||||
// View
|
||||
PopupField<string> m_SubTargetField;
|
||||
TextField m_CustomGUIField;
|
||||
|
||||
[SerializeField]
|
||||
JsonData<SubTarget> m_ActiveSubTarget;
|
||||
|
||||
[SerializeField]
|
||||
SurfaceType m_SurfaceType = SurfaceType.Opaque;
|
||||
|
||||
[SerializeField]
|
||||
AlphaMode m_AlphaMode = AlphaMode.Alpha;
|
||||
|
||||
[SerializeField]
|
||||
bool m_TwoSided = false;
|
||||
|
||||
[SerializeField]
|
||||
bool m_AlphaClip = false;
|
||||
|
||||
[SerializeField]
|
||||
string m_CustomEditorGUI;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public string renderType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (surfaceType == SurfaceType.Transparent)
|
||||
return $"{RenderType.Transparent}";
|
||||
else
|
||||
return $"{RenderType.Opaque}";
|
||||
}
|
||||
}
|
||||
|
||||
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 SubTarget activeSubTarget
|
||||
{
|
||||
get => m_ActiveSubTarget;
|
||||
set => m_ActiveSubTarget = value;
|
||||
}
|
||||
|
||||
public SurfaceType surfaceType
|
||||
{
|
||||
get => m_SurfaceType;
|
||||
set => m_SurfaceType = value;
|
||||
}
|
||||
|
||||
public AlphaMode alphaMode
|
||||
{
|
||||
get => m_AlphaMode;
|
||||
set => m_AlphaMode = value;
|
||||
}
|
||||
|
||||
public bool twoSided
|
||||
{
|
||||
get => m_TwoSided;
|
||||
set => m_TwoSided = value;
|
||||
}
|
||||
|
||||
public bool alphaClip
|
||||
{
|
||||
get => m_AlphaClip;
|
||||
set => m_AlphaClip = value;
|
||||
}
|
||||
|
||||
public string customEditorGUI
|
||||
{
|
||||
get => m_CustomEditorGUI;
|
||||
set => m_CustomEditorGUI = value;
|
||||
}
|
||||
|
||||
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));
|
||||
return worksWithThisSrp && 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;
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
context.AddField(Fields.AlphaClip, alphaClip);
|
||||
context.AddField(Fields.DoubleSided, twoSided);
|
||||
|
||||
// SubTarget fields
|
||||
m_ActiveSubTarget.value.GetFields(ref context);
|
||||
}
|
||||
|
||||
public override void GetActiveBlocks(ref TargetActiveBlockContext context)
|
||||
{
|
||||
// Core blocks
|
||||
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 CollectShaderProperties(PropertyCollector collector, GenerationMode generationMode)
|
||||
{
|
||||
base.CollectShaderProperties(collector, generationMode);
|
||||
|
||||
collector.AddShaderProperty(LightmappingShaderProperties.kLightmapsArray);
|
||||
collector.AddShaderProperty(LightmappingShaderProperties.kLightmapsIndirectionArray);
|
||||
collector.AddShaderProperty(LightmappingShaderProperties.kShadowMasksArray);
|
||||
}
|
||||
|
||||
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];
|
||||
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) => {});
|
||||
}
|
||||
|
||||
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;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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
|
||||
switch (masterNode)
|
||||
{
|
||||
case PBRMasterNode1 pbrMasterNode:
|
||||
m_SurfaceType = (SurfaceType)pbrMasterNode.m_SurfaceType;
|
||||
m_AlphaMode = (AlphaMode)pbrMasterNode.m_AlphaMode;
|
||||
m_TwoSided = pbrMasterNode.m_TwoSided;
|
||||
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_TwoSided = unlitMasterNode.m_TwoSided;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
#region Passes
|
||||
static class CorePasses
|
||||
{
|
||||
public static readonly PassDescriptor DepthOnly = new PassDescriptor()
|
||||
{
|
||||
// Definition
|
||||
displayName = "DepthOnly",
|
||||
referenceName = "SHADERPASS_DEPTHONLY",
|
||||
lightMode = "DepthOnly",
|
||||
useInPreview = true,
|
||||
|
||||
// Template
|
||||
passTemplatePath = GenerationUtils.GetDefaultTemplatePath("PassMesh.template"),
|
||||
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = CoreBlockMasks.Vertex,
|
||||
validPixelBlocks = CoreBlockMasks.FragmentAlphaOnly,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.DepthOnly,
|
||||
pragmas = CorePragmas.Instanced,
|
||||
includes = CoreIncludes.DepthOnly,
|
||||
};
|
||||
|
||||
public static readonly PassDescriptor ShadowCaster = new PassDescriptor()
|
||||
{
|
||||
// Definition
|
||||
displayName = "ShadowCaster",
|
||||
referenceName = "SHADERPASS_SHADOWCASTER",
|
||||
lightMode = "ShadowCaster",
|
||||
|
||||
// Template
|
||||
passTemplatePath = GenerationUtils.GetDefaultTemplatePath("PassMesh.template"),
|
||||
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = CoreBlockMasks.Vertex,
|
||||
validPixelBlocks = CoreBlockMasks.FragmentAlphaOnly,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
requiredFields = CoreRequiredFields.ShadowCaster,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.ShadowCaster,
|
||||
pragmas = CorePragmas.Instanced,
|
||||
keywords = CoreKeywords.ShadowCaster,
|
||||
includes = CoreIncludes.ShadowCaster,
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region PortMasks
|
||||
class CoreBlockMasks
|
||||
{
|
||||
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,
|
||||
};
|
||||
}
|
||||
#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.Attributes.normalOS,
|
||||
};
|
||||
}
|
||||
#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 readonly RenderStateCollection Default = new RenderStateCollection
|
||||
{
|
||||
{ RenderState.ZTest(ZTest.LEqual) },
|
||||
{ RenderState.ZWrite(ZWrite.On), new FieldCondition(UniversalFields.SurfaceOpaque, true) },
|
||||
{ RenderState.ZWrite(ZWrite.Off), new FieldCondition(UniversalFields.SurfaceTransparent, true) },
|
||||
{ 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 readonly RenderStateCollection Meta = new RenderStateCollection
|
||||
{
|
||||
{ RenderState.Cull(Cull.Off) },
|
||||
};
|
||||
|
||||
public static readonly RenderStateCollection ShadowCaster = new RenderStateCollection
|
||||
{
|
||||
{ RenderState.ZTest(ZTest.LEqual) },
|
||||
{ RenderState.ZWrite(ZWrite.On) },
|
||||
{ RenderState.Cull(Cull.Back), new FieldCondition(Fields.DoubleSided, false) },
|
||||
{ RenderState.Cull(Cull.Off), new FieldCondition(Fields.DoubleSided, true) },
|
||||
{ RenderState.ColorMask("ColorMask 0") },
|
||||
{ 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.One, Blend.One, Blend.One, Blend.One), new FieldCondition(UniversalFields.BlendAdd, true) },
|
||||
{ RenderState.Blend(Blend.DstColor, Blend.Zero), new FieldCondition(UniversalFields.BlendMultiply, true) },
|
||||
};
|
||||
|
||||
public static readonly RenderStateCollection DepthOnly = new RenderStateCollection
|
||||
{
|
||||
{ RenderState.ZTest(ZTest.LEqual) },
|
||||
{ RenderState.ZWrite(ZWrite.On) },
|
||||
{ RenderState.Cull(Cull.Back), new FieldCondition(Fields.DoubleSided, false) },
|
||||
{ RenderState.Cull(Cull.Off), new FieldCondition(Fields.DoubleSided, true) },
|
||||
{ RenderState.ColorMask("ColorMask 0") },
|
||||
{ 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.One, Blend.One, Blend.One, Blend.One), new FieldCondition(UniversalFields.BlendAdd, true) },
|
||||
{ RenderState.Blend(Blend.DstColor, Blend.Zero), new FieldCondition(UniversalFields.BlendMultiply, true) },
|
||||
};
|
||||
|
||||
public static readonly RenderStateCollection DepthNormalsOnly = new RenderStateCollection
|
||||
{
|
||||
{ RenderState.ZTest(ZTest.LEqual) },
|
||||
{ RenderState.ZWrite(ZWrite.On) },
|
||||
{ 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.One, Blend.One, Blend.One, Blend.One), new FieldCondition(UniversalFields.BlendAdd, true) },
|
||||
{ RenderState.Blend(Blend.DstColor, Blend.Zero), new FieldCondition(UniversalFields.BlendMultiply, true) },
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Pragmas
|
||||
// TODO: should these be renamed and moved to UniversalPragmas/UniversalPragmas.cs ?
|
||||
// TODO: these aren't "core" as HDRP doesn't use them
|
||||
// TODO: and the same for the rest "Core" things
|
||||
static class CorePragmas
|
||||
{
|
||||
public static readonly PragmaCollection Default = new PragmaCollection
|
||||
{
|
||||
{ Pragma.Target(ShaderModel.Target20) },
|
||||
{ Pragma.OnlyRenderers(new[] { Platform.GLES, Platform.GLES3, Platform.GLCore, Platform.D3D11 }) },
|
||||
{ Pragma.Vertex("vert") },
|
||||
{ Pragma.Fragment("frag") },
|
||||
};
|
||||
|
||||
public static readonly PragmaCollection Instanced = new PragmaCollection
|
||||
{
|
||||
{ Pragma.Target(ShaderModel.Target20) },
|
||||
{ Pragma.OnlyRenderers(new[] { Platform.GLES, Platform.GLES3, Platform.GLCore, Platform.D3D11 }) },
|
||||
{ Pragma.MultiCompileInstancing },
|
||||
{ Pragma.Vertex("vert") },
|
||||
{ Pragma.Fragment("frag") },
|
||||
};
|
||||
|
||||
public static readonly PragmaCollection Forward = new PragmaCollection
|
||||
{
|
||||
{ Pragma.Target(ShaderModel.Target20) },
|
||||
{ Pragma.OnlyRenderers(new[] { Platform.GLES, Platform.GLES3, Platform.GLCore, Platform.D3D11 }) },
|
||||
{ Pragma.MultiCompileInstancing },
|
||||
{ Pragma.MultiCompileFog },
|
||||
{ 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 DOTSDefault = new PragmaCollection
|
||||
{
|
||||
{ Pragma.Target(ShaderModel.Target45) },
|
||||
{ Pragma.ExcludeRenderers(new[] { Platform.GLES, Platform.GLES3, Platform.GLCore }) },
|
||||
{ Pragma.Vertex("vert") },
|
||||
{ Pragma.Fragment("frag") },
|
||||
};
|
||||
|
||||
public static readonly PragmaCollection DOTSInstanced = new PragmaCollection
|
||||
{
|
||||
{ Pragma.Target(ShaderModel.Target45) },
|
||||
{ Pragma.ExcludeRenderers(new[] { Platform.GLES, Platform.GLES3, Platform.GLCore }) },
|
||||
{ Pragma.MultiCompileInstancing },
|
||||
{ Pragma.DOTSInstancing },
|
||||
{ Pragma.Vertex("vert") },
|
||||
{ Pragma.Fragment("frag") },
|
||||
};
|
||||
|
||||
public static readonly PragmaCollection DOTSForward = new PragmaCollection
|
||||
{
|
||||
{ Pragma.Target(ShaderModel.Target45) },
|
||||
{ Pragma.ExcludeRenderers(new[] { Platform.GLES, Platform.GLES3, Platform.GLCore }) },
|
||||
{ Pragma.MultiCompileInstancing },
|
||||
{ Pragma.MultiCompileFog },
|
||||
{ Pragma.DOTSInstancing },
|
||||
{ Pragma.Vertex("vert") },
|
||||
{ Pragma.Fragment("frag") },
|
||||
};
|
||||
|
||||
public static readonly PragmaCollection DOTSGBuffer = new PragmaCollection
|
||||
{
|
||||
{ Pragma.Target(ShaderModel.Target45) },
|
||||
{ Pragma.ExcludeRenderers(new[] { Platform.GLES, Platform.GLES3, Platform.GLCore }) },
|
||||
{ Pragma.MultiCompileInstancing },
|
||||
{ Pragma.MultiCompileFog },
|
||||
{ Pragma.DOTSInstancing },
|
||||
{ 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 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 kTextureStack = "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl";
|
||||
|
||||
public static readonly IncludeCollection CorePregraph = new IncludeCollection
|
||||
{
|
||||
{ kColor, IncludeLocation.Pregraph },
|
||||
{ kTexture, IncludeLocation.Pregraph },
|
||||
{ kCore, IncludeLocation.Pregraph },
|
||||
{ kLighting, IncludeLocation.Pregraph },
|
||||
{ kTextureStack, IncludeLocation.Pregraph }, // TODO: put this on a conditional
|
||||
};
|
||||
|
||||
public static readonly IncludeCollection ShaderGraphPregraph = new IncludeCollection
|
||||
{
|
||||
{ kGraphFunctions, IncludeLocation.Pregraph },
|
||||
};
|
||||
|
||||
public static readonly IncludeCollection CorePostgraph = new IncludeCollection
|
||||
{
|
||||
{ kShaderPass, IncludeLocation.Postgraph },
|
||||
{ kVaryings, IncludeLocation.Postgraph },
|
||||
};
|
||||
|
||||
public static readonly IncludeCollection DepthOnly = new IncludeCollection
|
||||
{
|
||||
// Pre-graph
|
||||
{ CorePregraph },
|
||||
{ ShaderGraphPregraph },
|
||||
|
||||
// Post-graph
|
||||
{ CorePostgraph },
|
||||
{ kDepthOnlyPass, IncludeLocation.Postgraph },
|
||||
};
|
||||
|
||||
public static readonly IncludeCollection DepthNormalsOnly = new IncludeCollection
|
||||
{
|
||||
// Pre-graph
|
||||
{ CorePregraph },
|
||||
{ ShaderGraphPregraph },
|
||||
|
||||
// Post-graph
|
||||
{ CorePostgraph },
|
||||
{ kDepthNormalsOnlyPass, IncludeLocation.Postgraph },
|
||||
};
|
||||
|
||||
public static readonly IncludeCollection ShadowCaster = new IncludeCollection
|
||||
{
|
||||
// Pre-graph
|
||||
{ CorePregraph },
|
||||
{ ShaderGraphPregraph },
|
||||
|
||||
// Post-graph
|
||||
{ CorePostgraph },
|
||||
{ kShadowCasterPass, IncludeLocation.Postgraph },
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Defines
|
||||
static class CoreDefines
|
||||
{
|
||||
public static readonly DefineCollection UseLegacySpriteBlocks = new DefineCollection
|
||||
{
|
||||
{ CoreKeywordDescriptors.UseLegacySpriteBlocks, 1, new FieldCondition(CoreFields.UseLegacySpriteBlocks, true) },
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region KeywordDescriptors
|
||||
// TODO: should these be renamed and moved to UniversalKeywordDescriptors/UniversalKeywords.cs ?
|
||||
// TODO: these aren't "core" as they aren't used by HDRP
|
||||
static class CoreKeywordDescriptors
|
||||
{
|
||||
public static readonly KeywordDescriptor Lightmap = new KeywordDescriptor()
|
||||
{
|
||||
displayName = "Lightmap",
|
||||
referenceName = "LIGHTMAP_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 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,
|
||||
};
|
||||
|
||||
public static readonly KeywordDescriptor AdditionalLights = new KeywordDescriptor()
|
||||
{
|
||||
displayName = "Additional Lights",
|
||||
referenceName = "_ADDITIONAL",
|
||||
type = KeywordType.Enum,
|
||||
definition = KeywordDefinition.MultiCompile,
|
||||
scope = KeywordScope.Global,
|
||||
entries = new KeywordEntry[]
|
||||
{
|
||||
new KeywordEntry() { displayName = "Vertex", referenceName = "LIGHTS_VERTEX" },
|
||||
new KeywordEntry() { displayName = "Fragment", referenceName = "LIGHTS" },
|
||||
new KeywordEntry() { displayName = "Off", referenceName = "OFF" },
|
||||
}
|
||||
};
|
||||
|
||||
public static readonly KeywordDescriptor AdditionalLightShadows = new KeywordDescriptor()
|
||||
{
|
||||
displayName = "Additional Light Shadows",
|
||||
referenceName = "_ADDITIONAL_LIGHT_SHADOWS",
|
||||
type = KeywordType.Boolean,
|
||||
definition = KeywordDefinition.MultiCompile,
|
||||
scope = KeywordScope.Global,
|
||||
};
|
||||
|
||||
public static readonly KeywordDescriptor ShadowsSoft = new KeywordDescriptor()
|
||||
{
|
||||
displayName = "Shadows Soft",
|
||||
referenceName = "_SHADOWS_SOFT",
|
||||
type = KeywordType.Boolean,
|
||||
definition = KeywordDefinition.MultiCompile,
|
||||
scope = KeywordScope.Global,
|
||||
};
|
||||
|
||||
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 SmoothnessChannel = new KeywordDescriptor()
|
||||
{
|
||||
displayName = "Smoothness Channel",
|
||||
referenceName = "_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A",
|
||||
type = KeywordType.Boolean,
|
||||
definition = KeywordDefinition.ShaderFeature,
|
||||
scope = KeywordScope.Global,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
}
|
||||
#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
|
||||
}
|
@@ -0,0 +1,228 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor.ShaderGraph;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.ShaderGraph.Legacy;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGraph
|
||||
{
|
||||
sealed class UniversalUnlitSubTarget : SubTarget<UniversalTarget>, ILegacyTarget
|
||||
{
|
||||
static readonly GUID kSourceCodeGuid = new GUID("97c3f7dcb477ec842aa878573640313a"); // UniversalUnlitSubTarget.cs
|
||||
|
||||
public UniversalUnlitSubTarget()
|
||||
{
|
||||
displayName = "Unlit";
|
||||
}
|
||||
|
||||
public override bool IsActive() => true;
|
||||
|
||||
public override void Setup(ref TargetSetupContext context)
|
||||
{
|
||||
context.AddAssetDependency(kSourceCodeGuid, AssetCollection.Flags.SourceDependency);
|
||||
|
||||
// Process SubShaders
|
||||
SubShaderDescriptor[] subShaders = { SubShaders.Unlit, SubShaders.UnlitDOTS };
|
||||
for (int i = 0; i < subShaders.Length; i++)
|
||||
{
|
||||
// Update Render State
|
||||
subShaders[i].renderType = target.renderType;
|
||||
subShaders[i].renderQueue = target.renderQueue;
|
||||
|
||||
// Add
|
||||
context.AddSubShader(subShaders[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public override void GetFields(ref TargetFieldContext context)
|
||||
{
|
||||
// Surface Type & Blend Mode
|
||||
// These must be set per SubTarget as Sprite SubTargets override them
|
||||
context.AddField(UniversalFields.SurfaceOpaque, target.surfaceType == SurfaceType.Opaque);
|
||||
context.AddField(UniversalFields.SurfaceTransparent, target.surfaceType != SurfaceType.Opaque);
|
||||
context.AddField(UniversalFields.BlendAdd, target.surfaceType != SurfaceType.Opaque && target.alphaMode == AlphaMode.Additive);
|
||||
context.AddField(Fields.BlendAlpha, target.surfaceType != SurfaceType.Opaque && target.alphaMode == AlphaMode.Alpha);
|
||||
context.AddField(UniversalFields.BlendMultiply, target.surfaceType != SurfaceType.Opaque && target.alphaMode == AlphaMode.Multiply);
|
||||
context.AddField(UniversalFields.BlendPremultiply, target.surfaceType != SurfaceType.Opaque && target.alphaMode == AlphaMode.Premultiply);
|
||||
}
|
||||
|
||||
public override void GetActiveBlocks(ref TargetActiveBlockContext context)
|
||||
{
|
||||
context.AddBlock(BlockFields.SurfaceDescription.Alpha, target.surfaceType == SurfaceType.Transparent || target.alphaClip);
|
||||
context.AddBlock(BlockFields.SurfaceDescription.AlphaClipThreshold, target.alphaClip);
|
||||
}
|
||||
|
||||
public override void GetPropertiesGUI(ref TargetPropertyGUIContext context, Action onChange, Action<String> registerUndo)
|
||||
{
|
||||
context.AddProperty("Surface", new EnumField(SurfaceType.Opaque) { value = target.surfaceType }, (evt) =>
|
||||
{
|
||||
if (Equals(target.surfaceType, evt.newValue))
|
||||
return;
|
||||
|
||||
registerUndo("Change Surface");
|
||||
target.surfaceType = (SurfaceType)evt.newValue;
|
||||
onChange();
|
||||
});
|
||||
|
||||
context.AddProperty("Blend", new EnumField(AlphaMode.Alpha) { value = target.alphaMode }, target.surfaceType == SurfaceType.Transparent, (evt) =>
|
||||
{
|
||||
if (Equals(target.alphaMode, evt.newValue))
|
||||
return;
|
||||
|
||||
registerUndo("Change Blend");
|
||||
target.alphaMode = (AlphaMode)evt.newValue;
|
||||
onChange();
|
||||
});
|
||||
|
||||
context.AddProperty("Alpha Clip", new Toggle() { value = target.alphaClip }, (evt) =>
|
||||
{
|
||||
if (Equals(target.alphaClip, evt.newValue))
|
||||
return;
|
||||
|
||||
registerUndo("Change Alpha Clip");
|
||||
target.alphaClip = evt.newValue;
|
||||
onChange();
|
||||
});
|
||||
|
||||
context.AddProperty("Two Sided", new Toggle() { value = target.twoSided }, (evt) =>
|
||||
{
|
||||
if (Equals(target.twoSided, evt.newValue))
|
||||
return;
|
||||
|
||||
registerUndo("Change Two Sided");
|
||||
target.twoSided = evt.newValue;
|
||||
onChange();
|
||||
});
|
||||
}
|
||||
|
||||
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 = new SubShaderDescriptor()
|
||||
{
|
||||
pipelineTag = UniversalTarget.kPipelineTag,
|
||||
customTags = UniversalTarget.kUnlitMaterialTypeTag,
|
||||
generatesPreview = true,
|
||||
passes = new PassCollection
|
||||
{
|
||||
{ UnlitPasses.Unlit },
|
||||
{ CorePasses.ShadowCaster },
|
||||
{ CorePasses.DepthOnly },
|
||||
},
|
||||
};
|
||||
|
||||
public static SubShaderDescriptor UnlitDOTS
|
||||
{
|
||||
get
|
||||
{
|
||||
var unlit = UnlitPasses.Unlit;
|
||||
var shadowCaster = CorePasses.ShadowCaster;
|
||||
var depthOnly = CorePasses.DepthOnly;
|
||||
|
||||
unlit.pragmas = CorePragmas.DOTSForward;
|
||||
shadowCaster.pragmas = CorePragmas.DOTSInstanced;
|
||||
depthOnly.pragmas = CorePragmas.DOTSInstanced;
|
||||
|
||||
return new SubShaderDescriptor()
|
||||
{
|
||||
pipelineTag = UniversalTarget.kPipelineTag,
|
||||
customTags = UniversalTarget.kUnlitMaterialTypeTag,
|
||||
generatesPreview = true,
|
||||
passes = new PassCollection
|
||||
{
|
||||
{ unlit },
|
||||
{ shadowCaster },
|
||||
{ depthOnly },
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Pass
|
||||
static class UnlitPasses
|
||||
{
|
||||
public static PassDescriptor Unlit = new PassDescriptor
|
||||
{
|
||||
// Definition
|
||||
displayName = "Pass",
|
||||
referenceName = "SHADERPASS_UNLIT",
|
||||
useInPreview = true,
|
||||
|
||||
// Template
|
||||
passTemplatePath = GenerationUtils.GetDefaultTemplatePath("PassMesh.template"),
|
||||
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = CoreBlockMasks.Vertex,
|
||||
validPixelBlocks = CoreBlockMasks.FragmentColorAlpha,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.Default,
|
||||
pragmas = CorePragmas.Forward,
|
||||
keywords = UnlitKeywords.Unlit,
|
||||
includes = UnlitIncludes.Unlit,
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Keywords
|
||||
static class UnlitKeywords
|
||||
{
|
||||
public static KeywordCollection Unlit = new KeywordCollection
|
||||
{
|
||||
{ CoreKeywordDescriptors.Lightmap },
|
||||
{ CoreKeywordDescriptors.DirectionalLightmapCombined },
|
||||
{ CoreKeywordDescriptors.SampleGI },
|
||||
};
|
||||
}
|
||||
#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 },
|
||||
|
||||
// Post-graph
|
||||
{ CoreIncludes.CorePostgraph },
|
||||
{ kUnlitPass, IncludeLocation.Postgraph },
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user