initial commit
This commit is contained in:
parent
6715289efe
commit
788c3389af
37645 changed files with 2526849 additions and 80 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f6cdcb0f9c306bf4895b74013d29ed47
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,928 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor.ShaderGraph;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.ShaderGraph.Legacy;
|
||||
|
||||
using static UnityEditor.Rendering.Universal.ShaderGraph.SubShaderUtils;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
using static Unity.Rendering.Universal.ShaderUtils;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGraph
|
||||
{
|
||||
sealed class UniversalLitSubTarget : UniversalSubTarget, 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";
|
||||
}
|
||||
|
||||
protected override ShaderID shaderID => ShaderID.SG_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);
|
||||
base.Setup(ref context);
|
||||
|
||||
var universalRPType = typeof(UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset);
|
||||
if (!context.HasCustomEditorForRenderPipeline(universalRPType))
|
||||
{
|
||||
var gui = typeof(ShaderGraphLitGUI);
|
||||
#if HAS_VFX_GRAPH
|
||||
if (TargetsVFX())
|
||||
gui = typeof(VFXShaderGraphLitGUI);
|
||||
#endif
|
||||
context.AddCustomEditorForRenderPipeline(gui.FullName, universalRPType);
|
||||
}
|
||||
|
||||
// Process SubShaders
|
||||
context.AddSubShader(PostProcessSubShader(SubShaders.LitComputeDotsSubShader(target, workflowMode, target.renderType, target.renderQueue, complexLit)));
|
||||
context.AddSubShader(PostProcessSubShader(SubShaders.LitGLESSubShader(target, workflowMode, target.renderType, target.renderQueue, complexLit)));
|
||||
}
|
||||
|
||||
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.SpecularWorkflowMode, (float)workflowMode);
|
||||
material.SetFloat(Property.CastShadows, target.castShadows ? 1.0f : 0.0f);
|
||||
material.SetFloat(Property.ReceiveShadows, target.receiveShadows ? 1.0f : 0.0f);
|
||||
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.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
|
||||
ShaderGraphLitGUI.UpdateMaterial(material, MaterialUpdateType.CreatedNewMaterial);
|
||||
}
|
||||
|
||||
public override void GetFields(ref TargetFieldContext context)
|
||||
{
|
||||
base.GetFields(ref context);
|
||||
|
||||
var descs = context.blocks.Select(x => x.descriptor);
|
||||
|
||||
// Lit -- always controlled by subtarget
|
||||
context.AddField(UniversalFields.NormalDropOffOS, normalDropOffSpace == NormalDropOffSpace.Object);
|
||||
context.AddField(UniversalFields.NormalDropOffTS, normalDropOffSpace == NormalDropOffSpace.Tangent);
|
||||
context.AddField(UniversalFields.NormalDropOffWS, normalDropOffSpace == NormalDropOffSpace.World);
|
||||
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);
|
||||
|
||||
// when the surface options are material controlled, we must show all of these blocks
|
||||
// when target controlled, we can cull the unnecessary blocks
|
||||
context.AddBlock(BlockFields.SurfaceDescription.Specular, (workflowMode == WorkflowMode.Specular) || target.allowMaterialOverride);
|
||||
context.AddBlock(BlockFields.SurfaceDescription.Metallic, (workflowMode == WorkflowMode.Metallic) || target.allowMaterialOverride);
|
||||
context.AddBlock(BlockFields.SurfaceDescription.Alpha, (target.surfaceType == SurfaceType.Transparent || target.alphaClip) || target.allowMaterialOverride);
|
||||
context.AddBlock(BlockFields.SurfaceDescription.AlphaClipThreshold, (target.alphaClip) || target.allowMaterialOverride);
|
||||
|
||||
// always controlled by subtarget clearCoat checkbox (no Material control)
|
||||
context.AddBlock(BlockFields.SurfaceDescription.CoatMask, clearCoat);
|
||||
context.AddBlock(BlockFields.SurfaceDescription.CoatSmoothness, clearCoat);
|
||||
}
|
||||
|
||||
public override void CollectShaderProperties(PropertyCollector collector, GenerationMode generationMode)
|
||||
{
|
||||
// if using material control, add the material property to control workflow mode
|
||||
if (target.allowMaterialOverride)
|
||||
{
|
||||
collector.AddFloatProperty(Property.SpecularWorkflowMode, (float)workflowMode);
|
||||
collector.AddFloatProperty(Property.CastShadows, target.castShadows ? 1.0f : 0.0f);
|
||||
collector.AddFloatProperty(Property.ReceiveShadows, target.receiveShadows ? 1.0f : 0.0f);
|
||||
|
||||
// setup properties using the defaults
|
||||
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, ok to have incorrect values here
|
||||
collector.AddFloatProperty(Property.DstBlend, 0.0f); // always set by material inspector, ok to have incorrect values here
|
||||
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);
|
||||
|
||||
context.AddProperty("Workflow Mode", new EnumField(WorkflowMode.Metallic) { value = workflowMode }, (evt) =>
|
||||
{
|
||||
if (Equals(workflowMode, evt.newValue))
|
||||
return;
|
||||
|
||||
registerUndo("Change Workflow");
|
||||
workflowMode = (WorkflowMode)evt.newValue;
|
||||
onChange();
|
||||
});
|
||||
|
||||
universalTarget.AddDefaultSurfacePropertiesGUI(ref context, onChange, registerUndo, showReceiveShadows: true);
|
||||
|
||||
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();
|
||||
});
|
||||
}
|
||||
|
||||
protected override int ComputeMaterialNeedsUpdateHash()
|
||||
{
|
||||
int hash = base.ComputeMaterialNeedsUpdateHash();
|
||||
hash = hash * 23 + target.allowMaterialOverride.GetHashCode();
|
||||
return hash;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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 },
|
||||
{ BlockFields.SurfaceDescription.Emission, 4 },
|
||||
{ BlockFields.SurfaceDescription.Smoothness, 5 },
|
||||
{ BlockFields.SurfaceDescription.Occlusion, 6 },
|
||||
{ BlockFields.SurfaceDescription.Alpha, 7 },
|
||||
{ BlockFields.SurfaceDescription.AlphaClipThreshold, 8 },
|
||||
};
|
||||
|
||||
// PBRMasterNode adds/removes Metallic/Specular based on settings
|
||||
if (m_WorkflowMode == WorkflowMode.Specular)
|
||||
blockMap.Add(BlockFields.SurfaceDescription.Specular, 3);
|
||||
else if (m_WorkflowMode == WorkflowMode.Metallic)
|
||||
blockMap.Add(BlockFields.SurfaceDescription.Metallic, 2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#region SubShader
|
||||
static class SubShaders
|
||||
{
|
||||
// SM 4.5, compute with dots instancing
|
||||
public static SubShaderDescriptor LitComputeDotsSubShader(UniversalTarget target, WorkflowMode workflowMode, string renderType, string renderQueue, bool complexLit)
|
||||
{
|
||||
SubShaderDescriptor result = new SubShaderDescriptor()
|
||||
{
|
||||
pipelineTag = UniversalTarget.kPipelineTag,
|
||||
customTags = UniversalTarget.kLitMaterialTypeTag,
|
||||
renderType = renderType,
|
||||
renderQueue = renderQueue,
|
||||
generatesPreview = true,
|
||||
passes = new PassCollection()
|
||||
};
|
||||
|
||||
if (complexLit)
|
||||
result.passes.Add(LitPasses.ForwardOnly(target, workflowMode, complexLit, CoreBlockMasks.Vertex, LitBlockMasks.FragmentComplexLit, CorePragmas.DOTSForward));
|
||||
else
|
||||
result.passes.Add(LitPasses.Forward(target, workflowMode, CorePragmas.DOTSForward));
|
||||
|
||||
if (!complexLit)
|
||||
result.passes.Add(LitPasses.GBuffer(target, workflowMode));
|
||||
|
||||
// cull the shadowcaster pass if we know it will never be used
|
||||
if (target.castShadows || target.allowMaterialOverride)
|
||||
result.passes.Add(PassVariant(CorePasses.ShadowCaster(target), CorePragmas.DOTSInstanced));
|
||||
|
||||
if (target.mayWriteDepth)
|
||||
result.passes.Add(PassVariant(CorePasses.DepthOnly(target), CorePragmas.DOTSInstanced));
|
||||
|
||||
if (complexLit)
|
||||
result.passes.Add(PassVariant(LitPasses.DepthNormalOnly(target), CorePragmas.DOTSInstanced));
|
||||
else
|
||||
result.passes.Add(PassVariant(LitPasses.DepthNormal(target), CorePragmas.DOTSInstanced));
|
||||
result.passes.Add(PassVariant(LitPasses.Meta(target), CorePragmas.DOTSDefault));
|
||||
// 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(LitPasses._2D(target), CorePragmas.DOTSDefault));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static SubShaderDescriptor LitGLESSubShader(UniversalTarget target, WorkflowMode workflowMode, string renderType, string renderQueue, bool complexLit)
|
||||
{
|
||||
// SM 2.0, GLES
|
||||
|
||||
// ForwardOnly pass is used as complex Lit SM 2.0 fallback for GLES.
|
||||
// Drops advanced features and renders materials as Lit.
|
||||
|
||||
SubShaderDescriptor result = new SubShaderDescriptor()
|
||||
{
|
||||
pipelineTag = UniversalTarget.kPipelineTag,
|
||||
customTags = UniversalTarget.kLitMaterialTypeTag,
|
||||
renderType = renderType,
|
||||
renderQueue = renderQueue,
|
||||
generatesPreview = true,
|
||||
passes = new PassCollection()
|
||||
};
|
||||
|
||||
if (complexLit)
|
||||
result.passes.Add(LitPasses.ForwardOnly(target, workflowMode, complexLit, CoreBlockMasks.Vertex, LitBlockMasks.FragmentComplexLit, CorePragmas.Forward));
|
||||
else
|
||||
result.passes.Add(LitPasses.Forward(target, workflowMode));
|
||||
|
||||
// cull the shadowcaster pass if we know it will never be used
|
||||
if (target.castShadows || target.allowMaterialOverride)
|
||||
result.passes.Add(CorePasses.ShadowCaster(target));
|
||||
|
||||
if (target.mayWriteDepth)
|
||||
result.passes.Add(CorePasses.DepthOnly(target));
|
||||
|
||||
if (complexLit)
|
||||
result.passes.Add(CorePasses.DepthNormalOnly(target));
|
||||
else
|
||||
result.passes.Add(CorePasses.DepthNormal(target));
|
||||
result.passes.Add(LitPasses.Meta(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(LitPasses._2D(target));
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Passes
|
||||
static class LitPasses
|
||||
{
|
||||
static void AddWorkflowModeControlToPass(ref PassDescriptor pass, UniversalTarget target, WorkflowMode workflowMode)
|
||||
{
|
||||
if (target.allowMaterialOverride)
|
||||
pass.keywords.Add(LitDefines.SpecularSetup);
|
||||
else if (workflowMode == WorkflowMode.Specular)
|
||||
pass.defines.Add(LitDefines.SpecularSetup, 1);
|
||||
}
|
||||
|
||||
static void AddReceiveShadowsControlToPass(ref PassDescriptor pass, UniversalTarget target, bool receiveShadows)
|
||||
{
|
||||
if (target.allowMaterialOverride)
|
||||
pass.keywords.Add(LitKeywords.ReceiveShadowsOff);
|
||||
else if (!receiveShadows)
|
||||
pass.defines.Add(LitKeywords.ReceiveShadowsOff, 1);
|
||||
}
|
||||
|
||||
public static PassDescriptor Forward(UniversalTarget target, WorkflowMode workflowMode, PragmaCollection pragmas = null)
|
||||
{
|
||||
var result = new PassDescriptor()
|
||||
{
|
||||
// Definition
|
||||
displayName = "Universal Forward",
|
||||
referenceName = "SHADERPASS_FORWARD",
|
||||
lightMode = "UniversalForward",
|
||||
useInPreview = true,
|
||||
|
||||
// Template
|
||||
passTemplatePath = UniversalTarget.kUberTemplatePath,
|
||||
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = CoreBlockMasks.Vertex,
|
||||
validPixelBlocks = LitBlockMasks.FragmentLit,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
requiredFields = LitRequiredFields.Forward,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.UberSwitchedRenderState(target),
|
||||
pragmas = pragmas ?? CorePragmas.Forward, // NOTE: SM 2.0 only GL
|
||||
defines = new DefineCollection() { CoreDefines.UseFragmentFog },
|
||||
keywords = new KeywordCollection() { LitKeywords.Forward },
|
||||
includes = LitIncludes.Forward,
|
||||
|
||||
// Custom Interpolator Support
|
||||
customInterpolators = CoreCustomInterpDescriptors.Common
|
||||
};
|
||||
|
||||
CorePasses.AddTargetSurfaceControlsToPass(ref result, target);
|
||||
AddWorkflowModeControlToPass(ref result, target, workflowMode);
|
||||
AddReceiveShadowsControlToPass(ref result, target, target.receiveShadows);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static PassDescriptor ForwardOnly(
|
||||
UniversalTarget target,
|
||||
WorkflowMode workflowMode,
|
||||
bool complexLit,
|
||||
BlockFieldDescriptor[] vertexBlocks,
|
||||
BlockFieldDescriptor[] pixelBlocks,
|
||||
PragmaCollection pragmas)
|
||||
{
|
||||
var result = new PassDescriptor
|
||||
{
|
||||
// Definition
|
||||
displayName = "Universal Forward Only",
|
||||
referenceName = "SHADERPASS_FORWARDONLY",
|
||||
lightMode = "UniversalForwardOnly",
|
||||
useInPreview = true,
|
||||
|
||||
// Template
|
||||
passTemplatePath = UniversalTarget.kUberTemplatePath,
|
||||
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = vertexBlocks,
|
||||
validPixelBlocks = pixelBlocks,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
requiredFields = LitRequiredFields.Forward,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.UberSwitchedRenderState(target),
|
||||
pragmas = pragmas,
|
||||
defines = new DefineCollection() { CoreDefines.UseFragmentFog },
|
||||
keywords = new KeywordCollection() { LitKeywords.Forward },
|
||||
includes = LitIncludes.Forward,
|
||||
|
||||
// Custom Interpolator Support
|
||||
customInterpolators = CoreCustomInterpDescriptors.Common
|
||||
};
|
||||
|
||||
if (complexLit)
|
||||
result.defines.Add(LitDefines.ClearCoat, 1);
|
||||
|
||||
CorePasses.AddTargetSurfaceControlsToPass(ref result, target);
|
||||
AddWorkflowModeControlToPass(ref result, target, workflowMode);
|
||||
AddReceiveShadowsControlToPass(ref result, target, target.receiveShadows);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Deferred only in SM4.5, MRT not supported in GLES2
|
||||
public static PassDescriptor GBuffer(UniversalTarget target, WorkflowMode workflowMode)
|
||||
{
|
||||
var result = new PassDescriptor
|
||||
{
|
||||
// Definition
|
||||
displayName = "GBuffer",
|
||||
referenceName = "SHADERPASS_GBUFFER",
|
||||
lightMode = "UniversalGBuffer",
|
||||
|
||||
// Template
|
||||
passTemplatePath = UniversalTarget.kUberTemplatePath,
|
||||
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = CoreBlockMasks.Vertex,
|
||||
validPixelBlocks = LitBlockMasks.FragmentLit,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
requiredFields = LitRequiredFields.GBuffer,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.UberSwitchedRenderState(target),
|
||||
pragmas = CorePragmas.DOTSGBuffer,
|
||||
defines = new DefineCollection() { CoreDefines.UseFragmentFog },
|
||||
keywords = new KeywordCollection() { LitKeywords.GBuffer },
|
||||
includes = LitIncludes.GBuffer,
|
||||
|
||||
// Custom Interpolator Support
|
||||
customInterpolators = CoreCustomInterpDescriptors.Common
|
||||
};
|
||||
|
||||
CorePasses.AddTargetSurfaceControlsToPass(ref result, target);
|
||||
AddWorkflowModeControlToPass(ref result, target, workflowMode);
|
||||
AddReceiveShadowsControlToPass(ref result, target, target.receiveShadows);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static PassDescriptor Meta(UniversalTarget target)
|
||||
{
|
||||
var result = new PassDescriptor()
|
||||
{
|
||||
// Definition
|
||||
displayName = "Meta",
|
||||
referenceName = "SHADERPASS_META",
|
||||
lightMode = "Meta",
|
||||
|
||||
// Template
|
||||
passTemplatePath = UniversalTarget.kUberTemplatePath,
|
||||
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
|
||||
|
||||
// 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,
|
||||
defines = new DefineCollection() { CoreDefines.UseFragmentFog },
|
||||
keywords = new KeywordCollection() { CoreKeywordDescriptors.EditorVisualization },
|
||||
includes = LitIncludes.Meta,
|
||||
|
||||
// Custom Interpolator Support
|
||||
customInterpolators = CoreCustomInterpDescriptors.Common
|
||||
};
|
||||
|
||||
CorePasses.AddAlphaClipControlToPass(ref result, target);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static PassDescriptor _2D(UniversalTarget target)
|
||||
{
|
||||
var result = new PassDescriptor()
|
||||
{
|
||||
// Definition
|
||||
referenceName = "SHADERPASS_2D",
|
||||
lightMode = "Universal2D",
|
||||
|
||||
// Template
|
||||
passTemplatePath = UniversalTarget.kUberTemplatePath,
|
||||
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = CoreBlockMasks.Vertex,
|
||||
validPixelBlocks = CoreBlockMasks.FragmentColorAlpha,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.UberSwitchedRenderState(target),
|
||||
pragmas = CorePragmas.Instanced,
|
||||
defines = new DefineCollection(),
|
||||
keywords = new KeywordCollection(),
|
||||
includes = LitIncludes._2D,
|
||||
|
||||
// Custom Interpolator Support
|
||||
customInterpolators = CoreCustomInterpDescriptors.Common
|
||||
};
|
||||
|
||||
CorePasses.AddAlphaClipControlToPass(ref result, target);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static PassDescriptor DepthNormal(UniversalTarget target)
|
||||
{
|
||||
var result = new PassDescriptor()
|
||||
{
|
||||
// Definition
|
||||
displayName = "DepthNormals",
|
||||
referenceName = "SHADERPASS_DEPTHNORMALS",
|
||||
lightMode = "DepthNormals",
|
||||
useInPreview = false,
|
||||
|
||||
// Template
|
||||
passTemplatePath = UniversalTarget.kUberTemplatePath,
|
||||
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = CoreBlockMasks.Vertex,
|
||||
validPixelBlocks = CoreBlockMasks.FragmentDepthNormals,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
requiredFields = CoreRequiredFields.DepthNormals,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.DepthNormalsOnly(target),
|
||||
pragmas = CorePragmas.Instanced,
|
||||
defines = new DefineCollection(),
|
||||
keywords = new KeywordCollection(),
|
||||
includes = CoreIncludes.DepthNormalsOnly,
|
||||
|
||||
// Custom Interpolator Support
|
||||
customInterpolators = CoreCustomInterpDescriptors.Common
|
||||
};
|
||||
|
||||
CorePasses.AddAlphaClipControlToPass(ref result, target);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static PassDescriptor DepthNormalOnly(UniversalTarget target)
|
||||
{
|
||||
var result = new PassDescriptor()
|
||||
{
|
||||
// Definition
|
||||
displayName = "DepthNormalsOnly",
|
||||
referenceName = "SHADERPASS_DEPTHNORMALSONLY",
|
||||
lightMode = "DepthNormalsOnly",
|
||||
useInPreview = false,
|
||||
|
||||
// Template
|
||||
passTemplatePath = UniversalTarget.kUberTemplatePath,
|
||||
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = CoreBlockMasks.Vertex,
|
||||
validPixelBlocks = CoreBlockMasks.FragmentDepthNormals,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
requiredFields = CoreRequiredFields.DepthNormals,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.DepthNormalsOnly(target),
|
||||
pragmas = CorePragmas.Instanced,
|
||||
defines = new DefineCollection(),
|
||||
keywords = new KeywordCollection(),
|
||||
includes = CoreIncludes.DepthNormalsOnly,
|
||||
|
||||
// Custom Interpolator Support
|
||||
customInterpolators = CoreCustomInterpDescriptors.Common
|
||||
};
|
||||
|
||||
CorePasses.AddAlphaClipControlToPass(ref result, target);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
#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,
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RequiredFields
|
||||
static class LitRequiredFields
|
||||
{
|
||||
public static readonly FieldCollection Forward = new FieldCollection()
|
||||
{
|
||||
StructFields.Attributes.uv1,
|
||||
StructFields.Attributes.uv2,
|
||||
StructFields.Varyings.positionWS,
|
||||
StructFields.Varyings.normalWS,
|
||||
StructFields.Varyings.tangentWS, // needed for vertex lighting
|
||||
StructFields.Varyings.viewDirectionWS,
|
||||
UniversalStructFields.Varyings.staticLightmapUV,
|
||||
UniversalStructFields.Varyings.dynamicLightmapUV,
|
||||
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,
|
||||
StructFields.Attributes.uv2,
|
||||
StructFields.Varyings.positionWS,
|
||||
StructFields.Varyings.normalWS,
|
||||
StructFields.Varyings.tangentWS, // needed for vertex lighting
|
||||
StructFields.Varyings.viewDirectionWS,
|
||||
UniversalStructFields.Varyings.staticLightmapUV,
|
||||
UniversalStructFields.Varyings.dynamicLightmapUV,
|
||||
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 Meta = new FieldCollection()
|
||||
{
|
||||
StructFields.Attributes.positionOS,
|
||||
StructFields.Attributes.normalOS,
|
||||
StructFields.Attributes.uv0, //
|
||||
StructFields.Attributes.uv1, // needed for meta vertex position
|
||||
StructFields.Attributes.uv2, // needed for meta UVs
|
||||
StructFields.Attributes.instanceID, // needed for rendering instanced terrain
|
||||
StructFields.Varyings.positionCS,
|
||||
StructFields.Varyings.texCoord0, // needed for meta UVs
|
||||
StructFields.Varyings.texCoord1, // VizUV
|
||||
StructFields.Varyings.texCoord2, // LightCoord
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Defines
|
||||
static class LitDefines
|
||||
{
|
||||
public static readonly KeywordDescriptor ClearCoat = new KeywordDescriptor()
|
||||
{
|
||||
displayName = "Clear Coat",
|
||||
referenceName = "_CLEARCOAT",
|
||||
type = KeywordType.Boolean,
|
||||
definition = KeywordDefinition.ShaderFeature,
|
||||
scope = KeywordScope.Local,
|
||||
stages = KeywordShaderStage.Fragment
|
||||
};
|
||||
|
||||
public static readonly KeywordDescriptor SpecularSetup = new KeywordDescriptor()
|
||||
{
|
||||
displayName = "Specular Setup",
|
||||
referenceName = "_SPECULAR_SETUP",
|
||||
type = KeywordType.Boolean,
|
||||
definition = KeywordDefinition.ShaderFeature,
|
||||
scope = KeywordScope.Local,
|
||||
stages = KeywordShaderStage.Fragment
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Keywords
|
||||
static class LitKeywords
|
||||
{
|
||||
public static readonly KeywordDescriptor ReceiveShadowsOff = new KeywordDescriptor()
|
||||
{
|
||||
displayName = "Receive Shadows Off",
|
||||
referenceName = ShaderKeywordStrings._RECEIVE_SHADOWS_OFF,
|
||||
type = KeywordType.Boolean,
|
||||
definition = KeywordDefinition.ShaderFeature,
|
||||
scope = KeywordScope.Local,
|
||||
};
|
||||
|
||||
public static readonly KeywordDescriptor ScreenSpaceAmbientOcclusion = new KeywordDescriptor()
|
||||
{
|
||||
displayName = "Screen Space Ambient Occlusion",
|
||||
referenceName = "_SCREEN_SPACE_OCCLUSION",
|
||||
type = KeywordType.Boolean,
|
||||
definition = KeywordDefinition.MultiCompile,
|
||||
scope = KeywordScope.Global,
|
||||
stages = KeywordShaderStage.Fragment,
|
||||
};
|
||||
|
||||
public static readonly KeywordDescriptor Volumetrics = new KeywordDescriptor()
|
||||
{
|
||||
displayName = "Volumetrics",
|
||||
referenceName = "_VOLUMETRICS_ENABLED",
|
||||
type = KeywordType.Boolean,
|
||||
definition = KeywordDefinition.MultiCompile,
|
||||
scope = KeywordScope.Global,
|
||||
};
|
||||
|
||||
public static readonly KeywordCollection Forward = new KeywordCollection
|
||||
{
|
||||
{ ScreenSpaceAmbientOcclusion },
|
||||
{ Volumetrics },
|
||||
{ CoreKeywordDescriptors.StaticLightmap },
|
||||
{ CoreKeywordDescriptors.DynamicLightmap },
|
||||
{ CoreKeywordDescriptors.DirectionalLightmapCombined },
|
||||
{ CoreKeywordDescriptors.MainLightShadows },
|
||||
{ CoreKeywordDescriptors.AdditionalLights },
|
||||
{ CoreKeywordDescriptors.AdditionalLightShadows },
|
||||
{ CoreKeywordDescriptors.ReflectionProbeBlending },
|
||||
{ CoreKeywordDescriptors.ReflectionProbeBoxProjection },
|
||||
{ CoreKeywordDescriptors.ShadowsSoft },
|
||||
{ CoreKeywordDescriptors.LightmapShadowMixing },
|
||||
{ CoreKeywordDescriptors.ShadowsShadowmask },
|
||||
{ CoreKeywordDescriptors.DBuffer },
|
||||
{ CoreKeywordDescriptors.LightLayers },
|
||||
{ CoreKeywordDescriptors.DebugDisplay },
|
||||
{ CoreKeywordDescriptors.LightCookies },
|
||||
{ CoreKeywordDescriptors.ClusteredRendering },
|
||||
};
|
||||
|
||||
public static readonly KeywordCollection GBuffer = new KeywordCollection
|
||||
{
|
||||
{ CoreKeywordDescriptors.StaticLightmap },
|
||||
{ CoreKeywordDescriptors.DynamicLightmap },
|
||||
{ CoreKeywordDescriptors.DirectionalLightmapCombined },
|
||||
{ CoreKeywordDescriptors.MainLightShadows },
|
||||
{ CoreKeywordDescriptors.ReflectionProbeBlending },
|
||||
{ CoreKeywordDescriptors.ReflectionProbeBoxProjection },
|
||||
{ CoreKeywordDescriptors.ShadowsSoft },
|
||||
{ CoreKeywordDescriptors.LightmapShadowMixing },
|
||||
{ CoreKeywordDescriptors.MixedLightingSubtractive },
|
||||
{ CoreKeywordDescriptors.DBuffer },
|
||||
{ CoreKeywordDescriptors.GBufferNormalsOct },
|
||||
{ CoreKeywordDescriptors.LightLayers },
|
||||
{ CoreKeywordDescriptors.RenderPassEnabled },
|
||||
{ CoreKeywordDescriptors.DebugDisplay },
|
||||
};
|
||||
}
|
||||
#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 },
|
||||
{ CoreIncludes.DBufferPregraph },
|
||||
|
||||
// Post-graph
|
||||
{ CoreIncludes.CorePostgraph },
|
||||
{ kForwardPass, IncludeLocation.Postgraph },
|
||||
};
|
||||
|
||||
public static readonly IncludeCollection GBuffer = new IncludeCollection
|
||||
{
|
||||
// Pre-graph
|
||||
{ CoreIncludes.CorePregraph },
|
||||
{ kShadows, IncludeLocation.Pregraph },
|
||||
{ CoreIncludes.ShaderGraphPregraph },
|
||||
{ CoreIncludes.DBufferPregraph },
|
||||
|
||||
// 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,926 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor.ShaderGraph;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.ShaderGraph.Legacy;
|
||||
|
||||
using static UnityEditor.Rendering.Universal.ShaderGraph.SubShaderUtils;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
using static Unity.Rendering.Universal.ShaderUtils;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGraph
|
||||
{
|
||||
sealed class UniversalLitSubTarget : UniversalSubTarget, 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";
|
||||
}
|
||||
|
||||
protected override ShaderID shaderID => ShaderID.SG_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);
|
||||
base.Setup(ref context);
|
||||
|
||||
var universalRPType = typeof(UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset);
|
||||
if (!context.HasCustomEditorForRenderPipeline(universalRPType))
|
||||
{
|
||||
var gui = typeof(ShaderGraphLitGUI);
|
||||
#if HAS_VFX_GRAPH
|
||||
if (TargetsVFX())
|
||||
gui = typeof(VFXShaderGraphLitGUI);
|
||||
#endif
|
||||
context.AddCustomEditorForRenderPipeline(gui.FullName, universalRPType);
|
||||
}
|
||||
|
||||
// Process SubShaders
|
||||
context.AddSubShader(PostProcessSubShader(SubShaders.LitComputeDotsSubShader(target, workflowMode, target.renderType, target.renderQueue, complexLit)));
|
||||
context.AddSubShader(PostProcessSubShader(SubShaders.LitGLESSubShader(target, workflowMode, target.renderType, target.renderQueue, complexLit)));
|
||||
}
|
||||
|
||||
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.SpecularWorkflowMode, (float)workflowMode);
|
||||
material.SetFloat(Property.CastShadows, target.castShadows ? 1.0f : 0.0f);
|
||||
material.SetFloat(Property.ReceiveShadows, target.receiveShadows ? 1.0f : 0.0f);
|
||||
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.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
|
||||
ShaderGraphLitGUI.UpdateMaterial(material, MaterialUpdateType.CreatedNewMaterial);
|
||||
}
|
||||
|
||||
public override void GetFields(ref TargetFieldContext context)
|
||||
{
|
||||
base.GetFields(ref context);
|
||||
|
||||
var descs = context.blocks.Select(x => x.descriptor);
|
||||
|
||||
// Lit -- always controlled by subtarget
|
||||
context.AddField(UniversalFields.NormalDropOffOS, normalDropOffSpace == NormalDropOffSpace.Object);
|
||||
context.AddField(UniversalFields.NormalDropOffTS, normalDropOffSpace == NormalDropOffSpace.Tangent);
|
||||
context.AddField(UniversalFields.NormalDropOffWS, normalDropOffSpace == NormalDropOffSpace.World);
|
||||
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);
|
||||
|
||||
// when the surface options are material controlled, we must show all of these blocks
|
||||
// when target controlled, we can cull the unnecessary blocks
|
||||
context.AddBlock(BlockFields.SurfaceDescription.Specular, (workflowMode == WorkflowMode.Specular) || target.allowMaterialOverride);
|
||||
context.AddBlock(BlockFields.SurfaceDescription.Metallic, (workflowMode == WorkflowMode.Metallic) || target.allowMaterialOverride);
|
||||
context.AddBlock(BlockFields.SurfaceDescription.Alpha, (target.surfaceType == SurfaceType.Transparent || target.alphaClip) || target.allowMaterialOverride);
|
||||
context.AddBlock(BlockFields.SurfaceDescription.AlphaClipThreshold, (target.alphaClip) || target.allowMaterialOverride);
|
||||
|
||||
// always controlled by subtarget clearCoat checkbox (no Material control)
|
||||
context.AddBlock(BlockFields.SurfaceDescription.CoatMask, clearCoat);
|
||||
context.AddBlock(BlockFields.SurfaceDescription.CoatSmoothness, clearCoat);
|
||||
}
|
||||
|
||||
public override void CollectShaderProperties(PropertyCollector collector, GenerationMode generationMode)
|
||||
{
|
||||
// if using material control, add the material property to control workflow mode
|
||||
if (target.allowMaterialOverride)
|
||||
{
|
||||
collector.AddFloatProperty(Property.SpecularWorkflowMode, (float)workflowMode);
|
||||
collector.AddFloatProperty(Property.CastShadows, target.castShadows ? 1.0f : 0.0f);
|
||||
collector.AddFloatProperty(Property.ReceiveShadows, target.receiveShadows ? 1.0f : 0.0f);
|
||||
|
||||
// setup properties using the defaults
|
||||
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, ok to have incorrect values here
|
||||
collector.AddFloatProperty(Property.DstBlend, 0.0f); // always set by material inspector, ok to have incorrect values here
|
||||
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);
|
||||
|
||||
context.AddProperty("Workflow Mode", new EnumField(WorkflowMode.Metallic) { value = workflowMode }, (evt) =>
|
||||
{
|
||||
if (Equals(workflowMode, evt.newValue))
|
||||
return;
|
||||
|
||||
registerUndo("Change Workflow");
|
||||
workflowMode = (WorkflowMode)evt.newValue;
|
||||
onChange();
|
||||
});
|
||||
|
||||
universalTarget.AddDefaultSurfacePropertiesGUI(ref context, onChange, registerUndo, showReceiveShadows: true);
|
||||
|
||||
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();
|
||||
});
|
||||
}
|
||||
|
||||
protected override int ComputeMaterialNeedsUpdateHash()
|
||||
{
|
||||
int hash = base.ComputeMaterialNeedsUpdateHash();
|
||||
hash = hash * 23 + target.allowMaterialOverride.GetHashCode();
|
||||
return hash;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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 },
|
||||
{ BlockFields.SurfaceDescription.Emission, 4 },
|
||||
{ BlockFields.SurfaceDescription.Smoothness, 5 },
|
||||
{ BlockFields.SurfaceDescription.Occlusion, 6 },
|
||||
{ BlockFields.SurfaceDescription.Alpha, 7 },
|
||||
{ BlockFields.SurfaceDescription.AlphaClipThreshold, 8 },
|
||||
};
|
||||
|
||||
// PBRMasterNode adds/removes Metallic/Specular based on settings
|
||||
if (m_WorkflowMode == WorkflowMode.Specular)
|
||||
blockMap.Add(BlockFields.SurfaceDescription.Specular, 3);
|
||||
else if (m_WorkflowMode == WorkflowMode.Metallic)
|
||||
blockMap.Add(BlockFields.SurfaceDescription.Metallic, 2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#region SubShader
|
||||
static class SubShaders
|
||||
{
|
||||
// SM 4.5, compute with dots instancing
|
||||
public static SubShaderDescriptor LitComputeDotsSubShader(UniversalTarget target, WorkflowMode workflowMode, string renderType, string renderQueue, bool complexLit)
|
||||
{
|
||||
SubShaderDescriptor result = new SubShaderDescriptor()
|
||||
{
|
||||
pipelineTag = UniversalTarget.kPipelineTag,
|
||||
customTags = UniversalTarget.kLitMaterialTypeTag,
|
||||
renderType = renderType,
|
||||
renderQueue = renderQueue,
|
||||
generatesPreview = true,
|
||||
passes = new PassCollection()
|
||||
};
|
||||
|
||||
if (complexLit)
|
||||
result.passes.Add(LitPasses.ForwardOnly(target, workflowMode, complexLit, CoreBlockMasks.Vertex, LitBlockMasks.FragmentComplexLit, CorePragmas.DOTSForward));
|
||||
else
|
||||
result.passes.Add(LitPasses.Forward(target, workflowMode, CorePragmas.DOTSForward));
|
||||
|
||||
if (!complexLit)
|
||||
result.passes.Add(LitPasses.GBuffer(target, workflowMode));
|
||||
|
||||
// cull the shadowcaster pass if we know it will never be used
|
||||
if (target.castShadows || target.allowMaterialOverride)
|
||||
result.passes.Add(PassVariant(CorePasses.ShadowCaster(target), CorePragmas.DOTSInstanced));
|
||||
|
||||
if (target.mayWriteDepth)
|
||||
result.passes.Add(PassVariant(CorePasses.DepthOnly(target), CorePragmas.DOTSInstanced));
|
||||
|
||||
if (complexLit)
|
||||
result.passes.Add(PassVariant(LitPasses.DepthNormalOnly(target), CorePragmas.DOTSInstanced));
|
||||
else
|
||||
result.passes.Add(PassVariant(LitPasses.DepthNormal(target), CorePragmas.DOTSInstanced));
|
||||
result.passes.Add(PassVariant(LitPasses.Meta(target), CorePragmas.DOTSDefault));
|
||||
// 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(LitPasses._2D(target), CorePragmas.DOTSDefault));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static SubShaderDescriptor LitGLESSubShader(UniversalTarget target, WorkflowMode workflowMode, string renderType, string renderQueue, bool complexLit)
|
||||
{
|
||||
// SM 2.0, GLES
|
||||
|
||||
// ForwardOnly pass is used as complex Lit SM 2.0 fallback for GLES.
|
||||
// Drops advanced features and renders materials as Lit.
|
||||
|
||||
SubShaderDescriptor result = new SubShaderDescriptor()
|
||||
{
|
||||
pipelineTag = UniversalTarget.kPipelineTag,
|
||||
customTags = UniversalTarget.kLitMaterialTypeTag,
|
||||
renderType = renderType,
|
||||
renderQueue = renderQueue,
|
||||
generatesPreview = true,
|
||||
passes = new PassCollection()
|
||||
};
|
||||
|
||||
if (complexLit)
|
||||
result.passes.Add(LitPasses.ForwardOnly(target, workflowMode, complexLit, CoreBlockMasks.Vertex, LitBlockMasks.FragmentComplexLit, CorePragmas.Forward));
|
||||
else
|
||||
result.passes.Add(LitPasses.Forward(target, workflowMode));
|
||||
|
||||
// cull the shadowcaster pass if we know it will never be used
|
||||
if (target.castShadows || target.allowMaterialOverride)
|
||||
result.passes.Add(CorePasses.ShadowCaster(target));
|
||||
|
||||
if (target.mayWriteDepth)
|
||||
result.passes.Add(CorePasses.DepthOnly(target));
|
||||
|
||||
if (complexLit)
|
||||
result.passes.Add(CorePasses.DepthNormalOnly(target));
|
||||
else
|
||||
result.passes.Add(CorePasses.DepthNormal(target));
|
||||
result.passes.Add(LitPasses.Meta(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(LitPasses._2D(target));
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Passes
|
||||
static class LitPasses
|
||||
{
|
||||
static void AddWorkflowModeControlToPass(ref PassDescriptor pass, UniversalTarget target, WorkflowMode workflowMode)
|
||||
{
|
||||
if (target.allowMaterialOverride)
|
||||
pass.keywords.Add(LitDefines.SpecularSetup);
|
||||
else if (workflowMode == WorkflowMode.Specular)
|
||||
pass.defines.Add(LitDefines.SpecularSetup, 1);
|
||||
}
|
||||
|
||||
static void AddReceiveShadowsControlToPass(ref PassDescriptor pass, UniversalTarget target, bool receiveShadows)
|
||||
{
|
||||
if (target.allowMaterialOverride)
|
||||
pass.keywords.Add(LitKeywords.ReceiveShadowsOff);
|
||||
else if (!receiveShadows)
|
||||
pass.defines.Add(LitKeywords.ReceiveShadowsOff, 1);
|
||||
}
|
||||
|
||||
public static PassDescriptor Forward(UniversalTarget target, WorkflowMode workflowMode, PragmaCollection pragmas = null)
|
||||
{
|
||||
var result = new PassDescriptor()
|
||||
{
|
||||
// Definition
|
||||
displayName = "Universal Forward",
|
||||
referenceName = "SHADERPASS_FORWARD",
|
||||
lightMode = "UniversalForward",
|
||||
useInPreview = true,
|
||||
|
||||
// Template
|
||||
passTemplatePath = UniversalTarget.kUberTemplatePath,
|
||||
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = CoreBlockMasks.Vertex,
|
||||
validPixelBlocks = LitBlockMasks.FragmentLit,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
requiredFields = LitRequiredFields.Forward,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.UberSwitchedRenderState(target),
|
||||
pragmas = pragmas ?? CorePragmas.Forward, // NOTE: SM 2.0 only GL
|
||||
defines = new DefineCollection() { CoreDefines.UseFragmentFog },
|
||||
keywords = new KeywordCollection() { LitKeywords.Forward },
|
||||
includes = LitIncludes.Forward,
|
||||
|
||||
// Custom Interpolator Support
|
||||
customInterpolators = CoreCustomInterpDescriptors.Common
|
||||
};
|
||||
|
||||
CorePasses.AddTargetSurfaceControlsToPass(ref result, target);
|
||||
AddWorkflowModeControlToPass(ref result, target, workflowMode);
|
||||
AddReceiveShadowsControlToPass(ref result, target, target.receiveShadows);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static PassDescriptor ForwardOnly(
|
||||
UniversalTarget target,
|
||||
WorkflowMode workflowMode,
|
||||
bool complexLit,
|
||||
BlockFieldDescriptor[] vertexBlocks,
|
||||
BlockFieldDescriptor[] pixelBlocks,
|
||||
PragmaCollection pragmas)
|
||||
{
|
||||
var result = new PassDescriptor
|
||||
{
|
||||
// Definition
|
||||
displayName = "Universal Forward Only",
|
||||
referenceName = "SHADERPASS_FORWARDONLY",
|
||||
lightMode = "UniversalForwardOnly",
|
||||
useInPreview = true,
|
||||
|
||||
// Template
|
||||
passTemplatePath = UniversalTarget.kUberTemplatePath,
|
||||
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = vertexBlocks,
|
||||
validPixelBlocks = pixelBlocks,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
requiredFields = LitRequiredFields.Forward,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.UberSwitchedRenderState(target),
|
||||
pragmas = pragmas,
|
||||
defines = new DefineCollection() { CoreDefines.UseFragmentFog },
|
||||
keywords = new KeywordCollection() { LitKeywords.Forward },
|
||||
includes = LitIncludes.Forward,
|
||||
|
||||
// Custom Interpolator Support
|
||||
customInterpolators = CoreCustomInterpDescriptors.Common
|
||||
};
|
||||
|
||||
if (complexLit)
|
||||
result.defines.Add(LitDefines.ClearCoat, 1);
|
||||
|
||||
CorePasses.AddTargetSurfaceControlsToPass(ref result, target);
|
||||
AddWorkflowModeControlToPass(ref result, target, workflowMode);
|
||||
AddReceiveShadowsControlToPass(ref result, target, target.receiveShadows);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Deferred only in SM4.5, MRT not supported in GLES2
|
||||
public static PassDescriptor GBuffer(UniversalTarget target, WorkflowMode workflowMode)
|
||||
{
|
||||
var result = new PassDescriptor
|
||||
{
|
||||
// Definition
|
||||
displayName = "GBuffer",
|
||||
referenceName = "SHADERPASS_GBUFFER",
|
||||
lightMode = "UniversalGBuffer",
|
||||
|
||||
// Template
|
||||
passTemplatePath = UniversalTarget.kUberTemplatePath,
|
||||
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = CoreBlockMasks.Vertex,
|
||||
validPixelBlocks = LitBlockMasks.FragmentLit,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
requiredFields = LitRequiredFields.GBuffer,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.UberSwitchedRenderState(target),
|
||||
pragmas = CorePragmas.DOTSGBuffer,
|
||||
defines = new DefineCollection() { CoreDefines.UseFragmentFog },
|
||||
keywords = new KeywordCollection() { LitKeywords.GBuffer },
|
||||
includes = LitIncludes.GBuffer,
|
||||
|
||||
// Custom Interpolator Support
|
||||
customInterpolators = CoreCustomInterpDescriptors.Common
|
||||
};
|
||||
|
||||
CorePasses.AddTargetSurfaceControlsToPass(ref result, target);
|
||||
AddWorkflowModeControlToPass(ref result, target, workflowMode);
|
||||
AddReceiveShadowsControlToPass(ref result, target, target.receiveShadows);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static PassDescriptor Meta(UniversalTarget target)
|
||||
{
|
||||
var result = new PassDescriptor()
|
||||
{
|
||||
// Definition
|
||||
displayName = "Meta",
|
||||
referenceName = "SHADERPASS_META",
|
||||
lightMode = "Meta",
|
||||
|
||||
// Template
|
||||
passTemplatePath = UniversalTarget.kUberTemplatePath,
|
||||
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
|
||||
|
||||
// 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,
|
||||
defines = new DefineCollection() { CoreDefines.UseFragmentFog },
|
||||
keywords = new KeywordCollection() { CoreKeywordDescriptors.EditorVisualization },
|
||||
includes = LitIncludes.Meta,
|
||||
|
||||
// Custom Interpolator Support
|
||||
customInterpolators = CoreCustomInterpDescriptors.Common
|
||||
};
|
||||
|
||||
CorePasses.AddAlphaClipControlToPass(ref result, target);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static PassDescriptor _2D(UniversalTarget target)
|
||||
{
|
||||
var result = new PassDescriptor()
|
||||
{
|
||||
// Definition
|
||||
referenceName = "SHADERPASS_2D",
|
||||
lightMode = "Universal2D",
|
||||
|
||||
// Template
|
||||
passTemplatePath = UniversalTarget.kUberTemplatePath,
|
||||
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = CoreBlockMasks.Vertex,
|
||||
validPixelBlocks = CoreBlockMasks.FragmentColorAlpha,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.UberSwitchedRenderState(target),
|
||||
pragmas = CorePragmas.Instanced,
|
||||
defines = new DefineCollection(),
|
||||
keywords = new KeywordCollection(),
|
||||
includes = LitIncludes._2D,
|
||||
|
||||
// Custom Interpolator Support
|
||||
customInterpolators = CoreCustomInterpDescriptors.Common
|
||||
};
|
||||
|
||||
CorePasses.AddAlphaClipControlToPass(ref result, target);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static PassDescriptor DepthNormal(UniversalTarget target)
|
||||
{
|
||||
var result = new PassDescriptor()
|
||||
{
|
||||
// Definition
|
||||
displayName = "DepthNormals",
|
||||
referenceName = "SHADERPASS_DEPTHNORMALS",
|
||||
lightMode = "DepthNormals",
|
||||
useInPreview = false,
|
||||
|
||||
// Template
|
||||
passTemplatePath = UniversalTarget.kUberTemplatePath,
|
||||
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = CoreBlockMasks.Vertex,
|
||||
validPixelBlocks = CoreBlockMasks.FragmentDepthNormals,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
requiredFields = CoreRequiredFields.DepthNormals,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.DepthNormalsOnly(target),
|
||||
pragmas = CorePragmas.Instanced,
|
||||
defines = new DefineCollection(),
|
||||
keywords = new KeywordCollection(),
|
||||
includes = CoreIncludes.DepthNormalsOnly,
|
||||
|
||||
// Custom Interpolator Support
|
||||
customInterpolators = CoreCustomInterpDescriptors.Common
|
||||
};
|
||||
|
||||
CorePasses.AddAlphaClipControlToPass(ref result, target);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static PassDescriptor DepthNormalOnly(UniversalTarget target)
|
||||
{
|
||||
var result = new PassDescriptor()
|
||||
{
|
||||
// Definition
|
||||
displayName = "DepthNormalsOnly",
|
||||
referenceName = "SHADERPASS_DEPTHNORMALSONLY",
|
||||
lightMode = "DepthNormalsOnly",
|
||||
useInPreview = false,
|
||||
|
||||
// Template
|
||||
passTemplatePath = UniversalTarget.kUberTemplatePath,
|
||||
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,
|
||||
|
||||
// Port Mask
|
||||
validVertexBlocks = CoreBlockMasks.Vertex,
|
||||
validPixelBlocks = CoreBlockMasks.FragmentDepthNormals,
|
||||
|
||||
// Fields
|
||||
structs = CoreStructCollections.Default,
|
||||
requiredFields = CoreRequiredFields.DepthNormals,
|
||||
fieldDependencies = CoreFieldDependencies.Default,
|
||||
|
||||
// Conditional State
|
||||
renderStates = CoreRenderStates.DepthNormalsOnly(target),
|
||||
pragmas = CorePragmas.Instanced,
|
||||
defines = new DefineCollection(),
|
||||
keywords = new KeywordCollection(),
|
||||
includes = CoreIncludes.DepthNormalsOnly,
|
||||
|
||||
// Custom Interpolator Support
|
||||
customInterpolators = CoreCustomInterpDescriptors.Common
|
||||
};
|
||||
|
||||
CorePasses.AddAlphaClipControlToPass(ref result, target);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
#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,
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RequiredFields
|
||||
static class LitRequiredFields
|
||||
{
|
||||
public static readonly FieldCollection Forward = new FieldCollection()
|
||||
{
|
||||
StructFields.Attributes.uv1,
|
||||
StructFields.Attributes.uv2,
|
||||
StructFields.Varyings.positionWS,
|
||||
StructFields.Varyings.normalWS,
|
||||
StructFields.Varyings.tangentWS, // needed for vertex lighting
|
||||
StructFields.Varyings.viewDirectionWS,
|
||||
UniversalStructFields.Varyings.staticLightmapUV,
|
||||
UniversalStructFields.Varyings.dynamicLightmapUV,
|
||||
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,
|
||||
StructFields.Attributes.uv2,
|
||||
StructFields.Varyings.positionWS,
|
||||
StructFields.Varyings.normalWS,
|
||||
StructFields.Varyings.tangentWS, // needed for vertex lighting
|
||||
StructFields.Varyings.viewDirectionWS,
|
||||
UniversalStructFields.Varyings.staticLightmapUV,
|
||||
UniversalStructFields.Varyings.dynamicLightmapUV,
|
||||
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 Meta = new FieldCollection()
|
||||
{
|
||||
StructFields.Attributes.positionOS,
|
||||
StructFields.Attributes.normalOS,
|
||||
StructFields.Attributes.uv0, //
|
||||
StructFields.Attributes.uv1, // needed for meta vertex position
|
||||
StructFields.Attributes.uv2, // needed for meta UVs
|
||||
StructFields.Attributes.instanceID, // needed for rendering instanced terrain
|
||||
StructFields.Varyings.positionCS,
|
||||
StructFields.Varyings.texCoord0, // needed for meta UVs
|
||||
StructFields.Varyings.texCoord1, // VizUV
|
||||
StructFields.Varyings.texCoord2, // LightCoord
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Defines
|
||||
static class LitDefines
|
||||
{
|
||||
public static readonly KeywordDescriptor ClearCoat = new KeywordDescriptor()
|
||||
{
|
||||
displayName = "Clear Coat",
|
||||
referenceName = "_CLEARCOAT",
|
||||
type = KeywordType.Boolean,
|
||||
definition = KeywordDefinition.ShaderFeature,
|
||||
scope = KeywordScope.Local,
|
||||
};
|
||||
|
||||
public static readonly KeywordDescriptor SpecularSetup = new KeywordDescriptor()
|
||||
{
|
||||
displayName = "Specular Setup",
|
||||
referenceName = "_SPECULAR_SETUP",
|
||||
type = KeywordType.Boolean,
|
||||
definition = KeywordDefinition.ShaderFeature,
|
||||
scope = KeywordScope.Local,
|
||||
stages = KeywordShaderStage.Fragment
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Keywords
|
||||
static class LitKeywords
|
||||
{
|
||||
public static readonly KeywordDescriptor ReceiveShadowsOff = new KeywordDescriptor()
|
||||
{
|
||||
displayName = "Receive Shadows Off",
|
||||
referenceName = ShaderKeywordStrings._RECEIVE_SHADOWS_OFF,
|
||||
type = KeywordType.Boolean,
|
||||
definition = KeywordDefinition.ShaderFeature,
|
||||
scope = KeywordScope.Local,
|
||||
};
|
||||
|
||||
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 KeywordDescriptor Volumetrics = new KeywordDescriptor()
|
||||
{
|
||||
displayName = "Volumetrics",
|
||||
referenceName = "_VOLUMETRICS_ENABLED",
|
||||
type = KeywordType.Boolean,
|
||||
definition = KeywordDefinition.MultiCompile,
|
||||
scope = KeywordScope.Global,
|
||||
};
|
||||
|
||||
public static readonly KeywordCollection Forward = new KeywordCollection
|
||||
{
|
||||
{ ScreenSpaceAmbientOcclusion },
|
||||
{ Volumetrics },
|
||||
{ CoreKeywordDescriptors.StaticLightmap },
|
||||
{ CoreKeywordDescriptors.DynamicLightmap },
|
||||
{ CoreKeywordDescriptors.DirectionalLightmapCombined },
|
||||
{ CoreKeywordDescriptors.MainLightShadows },
|
||||
{ CoreKeywordDescriptors.AdditionalLights },
|
||||
{ CoreKeywordDescriptors.AdditionalLightShadows },
|
||||
{ CoreKeywordDescriptors.ReflectionProbeBlending },
|
||||
{ CoreKeywordDescriptors.ReflectionProbeBoxProjection },
|
||||
{ CoreKeywordDescriptors.ShadowsSoft },
|
||||
{ CoreKeywordDescriptors.LightmapShadowMixing },
|
||||
{ CoreKeywordDescriptors.ShadowsShadowmask },
|
||||
{ CoreKeywordDescriptors.DBuffer },
|
||||
{ CoreKeywordDescriptors.LightLayers },
|
||||
{ CoreKeywordDescriptors.DebugDisplay },
|
||||
{ CoreKeywordDescriptors.LightCookies },
|
||||
{ CoreKeywordDescriptors.ClusteredRendering },
|
||||
};
|
||||
|
||||
public static readonly KeywordCollection GBuffer = new KeywordCollection
|
||||
{
|
||||
{ CoreKeywordDescriptors.StaticLightmap },
|
||||
{ CoreKeywordDescriptors.DynamicLightmap },
|
||||
{ CoreKeywordDescriptors.DirectionalLightmapCombined },
|
||||
{ CoreKeywordDescriptors.MainLightShadows },
|
||||
{ CoreKeywordDescriptors.ReflectionProbeBlending },
|
||||
{ CoreKeywordDescriptors.ReflectionProbeBoxProjection },
|
||||
{ CoreKeywordDescriptors.ShadowsSoft },
|
||||
{ CoreKeywordDescriptors.LightmapShadowMixing },
|
||||
{ CoreKeywordDescriptors.MixedLightingSubtractive },
|
||||
{ CoreKeywordDescriptors.DBuffer },
|
||||
{ CoreKeywordDescriptors.GBufferNormalsOct },
|
||||
{ CoreKeywordDescriptors.LightLayers },
|
||||
{ CoreKeywordDescriptors.RenderPassEnabled },
|
||||
{ CoreKeywordDescriptors.DebugDisplay },
|
||||
};
|
||||
}
|
||||
#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 },
|
||||
{ CoreIncludes.DBufferPregraph },
|
||||
|
||||
// Post-graph
|
||||
{ CoreIncludes.CorePostgraph },
|
||||
{ kForwardPass, IncludeLocation.Postgraph },
|
||||
};
|
||||
|
||||
public static readonly IncludeCollection GBuffer = new IncludeCollection
|
||||
{
|
||||
// Pre-graph
|
||||
{ CoreIncludes.CorePregraph },
|
||||
{ kShadows, IncludeLocation.Pregraph },
|
||||
{ CoreIncludes.ShaderGraphPregraph },
|
||||
{ CoreIncludes.DBufferPregraph },
|
||||
|
||||
// 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,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 24e298b752ccb304b8c3fd3e308d3a6e
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d6c78107b64145745805d963de80cc17
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
using UnityEngine;
|
||||
using UnityEditor.ShaderGraph;
|
||||
using static Unity.Rendering.Universal.ShaderUtils;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
#if HAS_VFX_GRAPH
|
||||
using UnityEditor.VFX;
|
||||
#endif
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGraph
|
||||
{
|
||||
abstract class UniversalSubTarget : SubTarget<UniversalTarget>, IHasMetadata
|
||||
#if HAS_VFX_GRAPH
|
||||
, IRequireVFXContext
|
||||
#endif
|
||||
{
|
||||
static readonly GUID kSourceCodeGuid = new GUID("92228d45c1ff66740bfa9e6d97f7e280"); // UniversalSubTarget.cs
|
||||
|
||||
public override void Setup(ref TargetSetupContext context)
|
||||
{
|
||||
context.AddAssetDependency(kSourceCodeGuid, AssetCollection.Flags.SourceDependency);
|
||||
}
|
||||
|
||||
protected abstract ShaderID shaderID { get; }
|
||||
|
||||
#if HAS_VFX_GRAPH
|
||||
// VFX Properties
|
||||
VFXContext m_ContextVFX = null;
|
||||
VFXContextCompiledData m_ContextDataVFX;
|
||||
protected bool TargetsVFX() => m_ContextVFX != null;
|
||||
|
||||
public void ConfigureContextData(VFXContext context, VFXContextCompiledData data)
|
||||
{
|
||||
m_ContextVFX = context;
|
||||
m_ContextDataVFX = data;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
protected SubShaderDescriptor PostProcessSubShader(SubShaderDescriptor subShaderDescriptor)
|
||||
{
|
||||
#if HAS_VFX_GRAPH
|
||||
if (TargetsVFX())
|
||||
return VFXSubTarget.PostProcessSubShader(subShaderDescriptor, m_ContextVFX, m_ContextDataVFX);
|
||||
#endif
|
||||
return subShaderDescriptor;
|
||||
}
|
||||
|
||||
public override void GetFields(ref TargetFieldContext context)
|
||||
{
|
||||
#if HAS_VFX_GRAPH
|
||||
if (TargetsVFX())
|
||||
VFXSubTarget.GetFields(ref context, m_ContextVFX);
|
||||
#endif
|
||||
}
|
||||
|
||||
public virtual string identifier => GetType().Name;
|
||||
public virtual ScriptableObject GetMetadataObject(GraphDataReadOnly graphData)
|
||||
{
|
||||
var urpMetadata = ScriptableObject.CreateInstance<UniversalMetadata>();
|
||||
urpMetadata.shaderID = shaderID;
|
||||
urpMetadata.allowMaterialOverride = target.allowMaterialOverride;
|
||||
urpMetadata.alphaMode = target.alphaMode;
|
||||
urpMetadata.castShadows = target.castShadows;
|
||||
return urpMetadata;
|
||||
}
|
||||
|
||||
private int lastMaterialNeedsUpdateHash = 0;
|
||||
protected virtual int ComputeMaterialNeedsUpdateHash() => 0;
|
||||
|
||||
public override object saveContext
|
||||
{
|
||||
get
|
||||
{
|
||||
int hash = ComputeMaterialNeedsUpdateHash();
|
||||
bool needsUpdate = hash != lastMaterialNeedsUpdateHash;
|
||||
if (needsUpdate)
|
||||
lastMaterialNeedsUpdateHash = hash;
|
||||
|
||||
return new UniversalShaderGraphSaveContext { updateMaterials = needsUpdate };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static class SubShaderUtils
|
||||
{
|
||||
internal static void AddFloatProperty(this PropertyCollector collector, string referenceName, float defaultValue, HLSLDeclaration declarationType = HLSLDeclaration.DoNotDeclare)
|
||||
{
|
||||
collector.AddShaderProperty(new Vector1ShaderProperty
|
||||
{
|
||||
floatType = FloatType.Default,
|
||||
hidden = true,
|
||||
overrideHLSLDeclaration = true,
|
||||
hlslDeclarationOverride = declarationType,
|
||||
value = defaultValue,
|
||||
displayName = referenceName,
|
||||
overrideReferenceName = referenceName,
|
||||
});
|
||||
}
|
||||
|
||||
internal static void AddToggleProperty(this PropertyCollector collector, string referenceName, bool defaultValue, HLSLDeclaration declarationType = HLSLDeclaration.DoNotDeclare)
|
||||
{
|
||||
collector.AddShaderProperty(new BooleanShaderProperty
|
||||
{
|
||||
value = defaultValue,
|
||||
hidden = true,
|
||||
overrideHLSLDeclaration = true,
|
||||
hlslDeclarationOverride = declarationType,
|
||||
displayName = referenceName,
|
||||
overrideReferenceName = referenceName,
|
||||
});
|
||||
}
|
||||
|
||||
// Overloads to do inline PassDescriptor modifications
|
||||
// NOTE: param order should match PassDescriptor field order for consistency
|
||||
#region PassVariant
|
||||
internal static PassDescriptor PassVariant(in PassDescriptor source, PragmaCollection pragmas)
|
||||
{
|
||||
var result = source;
|
||||
result.pragmas = pragmas;
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
using UnityEngine;
|
||||
using UnityEditor.ShaderGraph;
|
||||
using static Unity.Rendering.Universal.ShaderUtils;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
#if HAS_VFX_GRAPH
|
||||
using UnityEditor.VFX;
|
||||
#endif
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGraph
|
||||
{
|
||||
abstract class UniversalSubTarget : SubTarget<UniversalTarget>, IHasMetadata
|
||||
#if HAS_VFX_GRAPH
|
||||
, IRequireVFXContext
|
||||
#endif
|
||||
{
|
||||
static readonly GUID kSourceCodeGuid = new GUID("92228d45c1ff66740bfa9e6d97f7e280"); // UniversalSubTarget.cs
|
||||
|
||||
public override void Setup(ref TargetSetupContext context)
|
||||
{
|
||||
context.AddAssetDependency(kSourceCodeGuid, AssetCollection.Flags.SourceDependency);
|
||||
}
|
||||
|
||||
protected abstract ShaderID shaderID { get; }
|
||||
|
||||
#if HAS_VFX_GRAPH
|
||||
// VFX Properties
|
||||
VFXContext m_ContextVFX = null;
|
||||
VFXContextCompiledData m_ContextDataVFX;
|
||||
protected bool TargetsVFX() => m_ContextVFX != null;
|
||||
|
||||
public void ConfigureContextData(VFXContext context, VFXContextCompiledData data)
|
||||
{
|
||||
m_ContextVFX = context;
|
||||
m_ContextDataVFX = data;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
protected SubShaderDescriptor PostProcessSubShader(SubShaderDescriptor subShaderDescriptor)
|
||||
{
|
||||
#if HAS_VFX_GRAPH
|
||||
if (TargetsVFX())
|
||||
return VFXSubTarget.PostProcessSubShader(subShaderDescriptor, m_ContextVFX, m_ContextDataVFX);
|
||||
#endif
|
||||
return subShaderDescriptor;
|
||||
}
|
||||
|
||||
public override void GetFields(ref TargetFieldContext context)
|
||||
{
|
||||
#if HAS_VFX_GRAPH
|
||||
if (TargetsVFX())
|
||||
VFXSubTarget.GetFields(ref context, m_ContextVFX);
|
||||
#endif
|
||||
}
|
||||
|
||||
public virtual string identifier => GetType().Name;
|
||||
public virtual ScriptableObject GetMetadataObject()
|
||||
{
|
||||
var urpMetadata = ScriptableObject.CreateInstance<UniversalMetadata>();
|
||||
urpMetadata.shaderID = shaderID;
|
||||
urpMetadata.allowMaterialOverride = target.allowMaterialOverride;
|
||||
urpMetadata.alphaMode = target.alphaMode;
|
||||
urpMetadata.castShadows = target.castShadows;
|
||||
return urpMetadata;
|
||||
}
|
||||
|
||||
private int lastMaterialNeedsUpdateHash = 0;
|
||||
protected virtual int ComputeMaterialNeedsUpdateHash() => 0;
|
||||
|
||||
public override object saveContext
|
||||
{
|
||||
get
|
||||
{
|
||||
int hash = ComputeMaterialNeedsUpdateHash();
|
||||
bool needsUpdate = hash != lastMaterialNeedsUpdateHash;
|
||||
if (needsUpdate)
|
||||
lastMaterialNeedsUpdateHash = hash;
|
||||
|
||||
return new UniversalShaderGraphSaveContext { updateMaterials = needsUpdate };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static class SubShaderUtils
|
||||
{
|
||||
internal static void AddFloatProperty(this PropertyCollector collector, string referenceName, float defaultValue, HLSLDeclaration declarationType = HLSLDeclaration.DoNotDeclare)
|
||||
{
|
||||
collector.AddShaderProperty(new Vector1ShaderProperty
|
||||
{
|
||||
floatType = FloatType.Default,
|
||||
hidden = true,
|
||||
overrideHLSLDeclaration = true,
|
||||
hlslDeclarationOverride = declarationType,
|
||||
value = defaultValue,
|
||||
displayName = referenceName,
|
||||
overrideReferenceName = referenceName,
|
||||
});
|
||||
}
|
||||
|
||||
internal static void AddToggleProperty(this PropertyCollector collector, string referenceName, bool defaultValue, HLSLDeclaration declarationType = HLSLDeclaration.DoNotDeclare)
|
||||
{
|
||||
collector.AddShaderProperty(new BooleanShaderProperty
|
||||
{
|
||||
value = defaultValue,
|
||||
hidden = true,
|
||||
overrideHLSLDeclaration = true,
|
||||
hlslDeclarationOverride = declarationType,
|
||||
displayName = referenceName,
|
||||
overrideReferenceName = referenceName,
|
||||
});
|
||||
}
|
||||
|
||||
// Overloads to do inline PassDescriptor modifications
|
||||
// NOTE: param order should match PassDescriptor field order for consistency
|
||||
#region PassVariant
|
||||
internal static PassDescriptor PassVariant(in PassDescriptor source, PragmaCollection pragmas)
|
||||
{
|
||||
var result = source;
|
||||
result.pragmas = pragmas;
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 453978b0981ea2f4faf4b49b8ac900cf
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 92228d45c1ff66740bfa9e6d97f7e280
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 963e3bda1d7b3524b80cbc4c84489038
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8c72f47fdde33b14a9340e325ce56f4d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,349 @@
|
|||
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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,349 @@
|
|||
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(CorePasses.SceneSelection(target));
|
||||
result.passes.Add(CorePasses.ScenePicking(target));
|
||||
|
||||
result.passes.Add(UnlitPasses.DepthNormalOnly(target));
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 46fb85453ca4dba458e8d63213d4dcd4
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 97c3f7dcb477ec842aa878573640313a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Loading…
Add table
Add a link
Reference in a new issue