UnityGame/Library/PackageCache/com.unity.render-pipelines.universal/Editor/ShaderGraph/Targets/UniversalDecalSubTarget.cs

1138 lines
52 KiB
C#
Raw Normal View History

2024-10-27 10:53:47 +03:00
using System;
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor.ShaderGraph;
using Unity.Rendering.Universal;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
using UnityEditor.ShaderGraph.Legacy;
using UnityEngine.Rendering.Universal;
using UnityEditor.ShaderGraph.Internal;
using ShaderUtils = Unity.Rendering.Universal.ShaderUtils;
namespace UnityEditor.Rendering.Universal.ShaderGraph
{
sealed class UniversalDecalSubTarget : UniversalSubTarget
{
static readonly GUID kSourceCodeGuid = new GUID("f6cdcb0f9c306bf4895b74013d29ed47"); // UniversalDecalSubTarget.cs
internal class Styles
{
public const string header = "Surface Options";
public static GUIContent affectAlbedoText = new GUIContent("Affect BaseColor", "When enabled, this decal uses its base color. When disabled, the decal has no base color effect.");
public static GUIContent affectNormalText = new GUIContent("Affect Normal", "When enabled, this decal uses its normal. When disabled, the decal has no normal effect.");
public static GUIContent affectNormalBlendText = new GUIContent("Affect Normal Blend", "When enabled, this decal uses its normal blending. When disabled, the decal has no normal blending effect.");
public static GUIContent affectMetalText = new GUIContent("Affect Metal", "When enabled, this decal uses the metallic channel of its Mask Map. When disabled, the decal has no metallic effect.");
public static GUIContent affectAmbientOcclusionText = new GUIContent("Affect Ambient Occlusion", "When enabled, this decal uses the smoothness channel of its Mask Map. When disabled, the decal has no smoothness effect.");
public static GUIContent affectSmoothnessText = new GUIContent("Affect Smoothness", "When enabled, this decal uses the ambient occlusion channel of its Mask Map. When disabled, the decal has no ambient occlusion effect.");
public static GUIContent affectEmissionText = new GUIContent("Affect Emission", "When enabled, this decal becomes emissive and appears self-illuminated. Affect Emission does not support Affects Transparent option on Decal Projector.");
public static GUIContent supportLodCrossFadeText = new GUIContent("Support LOD CrossFade", "When enabled, this decal material supports LOD Cross fade if use on a Mesh.");
}
private const string kMaterial = "Material";
private static FieldDescriptor AffectsAlbedo = new FieldDescriptor(kMaterial, "AffectsAlbedo", "");
private static FieldDescriptor AffectsNormal = new FieldDescriptor(kMaterial, "AffectsNormal", "");
private static FieldDescriptor AffectsNormalBlend = new FieldDescriptor(kMaterial, "AffectsNormalBlend", "");
private static FieldDescriptor AffectsMAOS = new FieldDescriptor(kMaterial, "AffectsAO", "");
private static FieldDescriptor AffectsEmission = new FieldDescriptor(kMaterial, "AffectsEmission", "");
private static FieldDescriptor AffectsDBuffer = new FieldDescriptor(kMaterial, "AffectsDBuffer", "");
private static FieldDescriptor DecalDefault = new FieldDescriptor(kMaterial, "DecalDefault", "");
private static FieldDescriptor AngleFade = new FieldDescriptor(kMaterial, "AngleFade", "");
[System.Serializable]
class DecalData
{
public bool affectsAlbedo = true;
public bool affectsNormalBlend = true;
public bool affectsNormal = true;
public bool affectsMAOS;
public bool affectsEmission;
public int drawOrder;
public bool supportLodCrossFade;
public bool angleFade;
}
[SerializeField]
DecalData m_DecalData;
[SerializeField]
private DecalData decalData
{
get
{
if (m_DecalData == null)
m_DecalData = new DecalData();
return m_DecalData;
}
}
public UniversalDecalSubTarget()
{
displayName = "Decal";
}
public override bool IsActive() => true;
protected override ShaderUtils.ShaderID shaderID => ShaderUtils.ShaderID.SG_Decal;
public override void Setup(ref TargetSetupContext context)
{
base.Setup(ref context);
context.AddAssetDependency(kSourceCodeGuid, AssetCollection.Flags.SourceDependency);
context.AddCustomEditorForRenderPipeline("UnityEditor.Rendering.Universal.DecalShaderGraphGUI", typeof(UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset)); // TODO: This should be owned by URP
{
SubShaderDescriptor subShader = SubShaders.Decal(decalData.supportLodCrossFade ? $"{UnityEditor.ShaderGraph.DisableBatching.LODFading}" : $"{UnityEditor.ShaderGraph.DisableBatching.False}");
var passes = new PassCollection();
foreach (var pass in subShader.passes)
{
var passDescriptor = pass.descriptor;
CollectPassRenderState(ref passDescriptor);
passes.Add(passDescriptor, pass.fieldConditions);
}
subShader.passes = passes;
context.AddSubShader(subShader);
}
}
private void CollectPassRenderState(ref PassDescriptor pass)
{
if (pass.lightMode == DecalShaderPassNames.DecalGBufferProjector ||
pass.lightMode == DecalShaderPassNames.DecalGBufferMesh)
{
// Make copy to avoid overwriting static
pass.renderStates = new RenderStateCollection() { pass.renderStates };
if (decalData.affectsAlbedo)
pass.renderStates.Add(RenderState.ColorMask("ColorMask RGB"));
else
pass.renderStates.Add(RenderState.ColorMask("ColorMask 0"));
pass.renderStates.Add(RenderState.ColorMask("ColorMask 0 1"));
if (decalData.affectsNormal)
pass.renderStates.Add(RenderState.ColorMask("ColorMask RGB 2"));
else
pass.renderStates.Add(RenderState.ColorMask("ColorMask 0 2"));
// GI needs it unconditionaly
pass.renderStates.Add(RenderState.ColorMask("ColorMask RGB 3"));
}
if (pass.lightMode == DecalShaderPassNames.DBufferProjector ||
pass.lightMode == DecalShaderPassNames.DBufferMesh)
{
// Make copy to avoid overwriting static
pass.renderStates = new RenderStateCollection() { pass.renderStates };
if (decalData.affectsAlbedo)
pass.renderStates.Add(DecalColorMasks.ColorMaskRGBA0);
else
pass.renderStates.Add(DecalColorMasks.ColorMaskNone0);
if (decalData.affectsNormal)
pass.renderStates.Add(DecalColorMasks.ColorMaskRGBA1);
else
pass.renderStates.Add(DecalColorMasks.ColorMaskNone1);
if (decalData.affectsMAOS)
pass.renderStates.Add(DecalColorMasks.ColorMaskRGBA2);
else
pass.renderStates.Add(DecalColorMasks.ColorMaskNone2);
}
}
public override void CollectShaderProperties(PropertyCollector collector, GenerationMode generationMode)
{
Vector1ShaderProperty drawOrder = new Vector1ShaderProperty();
drawOrder.overrideReferenceName = "_DrawOrder";
drawOrder.displayName = "Draw Order";
drawOrder.floatType = FloatType.Slider;
drawOrder.rangeValues = new Vector2(-50, 50);
drawOrder.hidden = true;
drawOrder.value = 0;
collector.AddShaderProperty(drawOrder);
collector.AddShaderProperty(new Vector1ShaderProperty
{
overrideReferenceName = "_DecalMeshBiasType",
displayName = "DecalMesh BiasType",
floatType = FloatType.Enum,
value = (int)DecalMeshDepthBiasType.DepthBias,
enumNames = { "Depth Bias", "View Bias" },
enumValues = { (int)DecalMeshDepthBiasType.DepthBias, (int)DecalMeshDepthBiasType.ViewBias },
hidden = true
});
Vector1ShaderProperty decalMeshDepthBias = new Vector1ShaderProperty();
decalMeshDepthBias.overrideReferenceName = "_DecalMeshDepthBias";
decalMeshDepthBias.displayName = "DecalMesh DepthBias";
decalMeshDepthBias.hidden = true;
decalMeshDepthBias.floatType = FloatType.Default;
decalMeshDepthBias.value = 0;
collector.AddShaderProperty(decalMeshDepthBias);
Vector1ShaderProperty decalMeshViewBias = new Vector1ShaderProperty();
decalMeshViewBias.overrideReferenceName = "_DecalMeshViewBias";
decalMeshViewBias.displayName = "DecalMesh ViewBias";
decalMeshViewBias.hidden = true;
decalMeshViewBias.floatType = FloatType.Default;
decalMeshViewBias.value = 0;
collector.AddShaderProperty(decalMeshViewBias);
if (decalData.angleFade)
{
Vector1ShaderProperty decalAngleFadeSupported = new Vector1ShaderProperty();
decalAngleFadeSupported.overrideReferenceName = "_DecalAngleFadeSupported";
decalAngleFadeSupported.displayName = "Decal Angle Fade Supported";
decalAngleFadeSupported.hidden = true;
decalAngleFadeSupported.floatType = FloatType.Default;
decalAngleFadeSupported.value = 1;
collector.AddShaderProperty(decalAngleFadeSupported);
}
}
public override void GetFields(ref TargetFieldContext context)
{
// Decal properties
context.AddField(AffectsAlbedo, decalData.affectsAlbedo);
context.AddField(AffectsNormal, decalData.affectsNormal);
context.AddField(AffectsNormalBlend, decalData.affectsNormalBlend);
context.AddField(AffectsMAOS, decalData.affectsMAOS);
context.AddField(AffectsEmission, decalData.affectsEmission);
context.AddField(AffectsDBuffer, decalData.affectsAlbedo || decalData.affectsNormal || decalData.affectsMAOS);
context.AddField(DecalDefault, decalData.affectsAlbedo || decalData.affectsNormal || decalData.affectsMAOS || decalData.affectsEmission);
context.AddField(Fields.LodCrossFade, decalData.supportLodCrossFade);
context.AddField(AngleFade, decalData.angleFade);
}
public override void GetActiveBlocks(ref TargetActiveBlockContext context)
{
// Vertex
context.AddBlock(BlockFields.VertexDescription.Position);
context.AddBlock(BlockFields.VertexDescription.Normal);
context.AddBlock(BlockFields.VertexDescription.Tangent);
// Decal
context.AddBlock(BlockFields.SurfaceDescription.BaseColor, decalData.affectsAlbedo);
context.AddBlock(BlockFields.SurfaceDescription.Alpha, decalData.affectsAlbedo || decalData.affectsEmission);
context.AddBlock(BlockFields.SurfaceDescription.NormalTS, decalData.affectsNormal);
context.AddBlock(UniversalBlockFields.SurfaceDescription.NormalAlpha, decalData.affectsNormal && decalData.affectsNormalBlend);
context.AddBlock(BlockFields.SurfaceDescription.Metallic, decalData.affectsMAOS);
context.AddBlock(BlockFields.SurfaceDescription.Occlusion, decalData.affectsMAOS);
context.AddBlock(BlockFields.SurfaceDescription.Smoothness, decalData.affectsMAOS);
context.AddBlock(UniversalBlockFields.SurfaceDescription.MAOSAlpha, decalData.affectsMAOS);
context.AddBlock(BlockFields.SurfaceDescription.Emission, decalData.affectsEmission);
}
public override void GetPropertiesGUI(ref TargetPropertyGUIContext context, Action onChange, Action<String> registerUndo)
{
context.AddProperty("Affect BaseColor", new Toggle() { value = decalData.affectsAlbedo }, (evt) =>
{
if (Equals(decalData.affectsAlbedo, evt.newValue))
return;
registerUndo("Change Affect BaseColor");
decalData.affectsAlbedo = (bool)evt.newValue;
onChange();
});
context.AddProperty("Affect Normal", new Toggle() { value = decalData.affectsNormal }, (evt) =>
{
if (Equals(decalData.affectsNormal, evt.newValue))
return;
registerUndo("Change Affects Normal");
decalData.affectsNormal = (bool)evt.newValue;
onChange();
});
context.globalIndentLevel++;
context.AddProperty("Blend", new Toggle() { value = decalData.affectsNormalBlend }, (evt) =>
{
if (Equals(decalData.affectsNormalBlend, evt.newValue))
return;
registerUndo("Change Affects Normal Blend");
decalData.affectsNormalBlend = (bool)evt.newValue;
onChange();
});
context.globalIndentLevel--;
context.AddProperty("Affect MAOS", new Toggle() { value = decalData.affectsMAOS }, (evt) =>
{
if (Equals(decalData.affectsMAOS, evt.newValue))
return;
registerUndo("Change Affect MAOS");
decalData.affectsMAOS = (bool)evt.newValue;
onChange();
});
context.AddProperty("Affect Emission", new Toggle() { value = decalData.affectsEmission }, (evt) =>
{
if (Equals(decalData.affectsEmission, evt.newValue))
return;
registerUndo("Change Affect Emission");
decalData.affectsEmission = (bool)evt.newValue;
onChange();
});
context.AddProperty("Supports LOD Cross Fade", new Toggle() { value = decalData.supportLodCrossFade }, (evt) =>
{
if (Equals(decalData.supportLodCrossFade, evt.newValue))
return;
registerUndo("Change Supports LOD Cross Fade");
decalData.supportLodCrossFade = (bool)evt.newValue;
onChange();
});
context.AddProperty("Angle Fade", new Toggle() { value = decalData.angleFade }, (evt) =>
{
if (Equals(decalData.angleFade, evt.newValue))
return;
registerUndo("Change Angle Fade");
decalData.angleFade = (bool)evt.newValue;
onChange();
});
}
#region SubShader
static class SubShaders
{
public static SubShaderDescriptor Decal(string disableBatchingTag)
{
return new SubShaderDescriptor()
{
pipelineTag = UniversalTarget.kPipelineTag,
customTags = "\"PreviewType\"=\"Plane\"",
disableBatchingTag = disableBatchingTag,
generatesPreview = true,
passes = new PassCollection
{
{ DecalPasses.DBufferProjector, new FieldCondition(AffectsDBuffer, true) },
{ DecalPasses.ForwardEmissiveProjector, new FieldCondition(AffectsEmission, true) },
{ DecalPasses.ScreenSpaceProjector, new FieldCondition(DecalDefault, true) },
{ DecalPasses.GBufferProjector, new FieldCondition(DecalDefault, true) },
{ DecalPasses.DBufferMesh, new FieldCondition(AffectsDBuffer, true) },
{ DecalPasses.ForwardEmissiveMesh, new FieldCondition(AffectsEmission, true) },
{ DecalPasses.ScreenSpaceMesh, new FieldCondition(DecalDefault, true) },
{ DecalPasses.GBufferMesh, new FieldCondition(DecalDefault, true) },
{ DecalPasses.ScenePicking, new FieldCondition(DecalDefault, true) },
},
};
}
}
#endregion
#region Passes
static class DecalPasses
{
public static PassDescriptor ScenePicking = GetScenePicking(DecalPragmas.Instanced);
public static PassDescriptor GetScenePicking(PragmaCollection pragma)
{
return new PassDescriptor
{
// Definition
displayName = "ScenePickingPass",
referenceName = "SHADERPASS_DEPTHONLY",
lightMode = "Picking",
useInPreview = false,
// Template
passTemplatePath = "Packages/com.unity.render-pipelines.universal/Editor/Decal/DecalPass.template",
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
// Collections
renderStates = DecalRenderStates.ScenePicking,
pragmas = pragma,
defines = DecalDefines.ScenePicking,
includes = DecalIncludes.ScenePicking,
structs = CoreStructCollections.Default,
fieldDependencies = CoreFieldDependencies.Default,
};
}
public static PassDescriptor DBufferProjector = new PassDescriptor()
{
// Definition
displayName = DecalShaderPassNames.DBufferProjector,
referenceName = "SHADERPASS_DBUFFER_PROJECTOR",
lightMode = DecalShaderPassNames.DBufferProjector,
useInPreview = false,
// Template
passTemplatePath = "Packages/com.unity.render-pipelines.universal/Editor/Decal/DecalPass.template",
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
// Port mask
validPixelBlocks = DecalBlockMasks.FragmentWithoutEmessive,
//Fields
structs = CoreStructCollections.Default,
fieldDependencies = CoreFieldDependencies.Default,
renderStates = DecalRenderStates.DBufferProjector,
pragmas = DecalPragmas.MultipleRenderTargets,
keywords = DecalKeywords.DBufferProjector,
defines = DecalDefines.Projector,
includes = DecalIncludes.DBuffer,
};
public static PassDescriptor ForwardEmissiveProjector = new PassDescriptor()
{
// Definition
displayName = DecalShaderPassNames.DecalProjectorForwardEmissive,
referenceName = "SHADERPASS_FORWARD_EMISSIVE_PROJECTOR",
lightMode = DecalShaderPassNames.DecalProjectorForwardEmissive,
useInPreview = false,
// Template
passTemplatePath = "Packages/com.unity.render-pipelines.universal/Editor/Decal/DecalPass.template",
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
// Port mask
validPixelBlocks = DecalBlockMasks.ForwardOnlyEmissive,
//Fields
structs = CoreStructCollections.Default,
fieldDependencies = CoreFieldDependencies.Default,
// Conditional State
renderStates = DecalRenderStates.ForwardEmissiveProjector,
pragmas = DecalPragmas.MultipleRenderTargets,
defines = DecalDefines.ProjectorWithEmission,
keywords = DecalKeywords.ForwardEmissiveProjector,
includes = DecalIncludes.DBuffer,
};
public static PassDescriptor ScreenSpaceProjector = GetScreenSpaceProjector(DecalPragmas.ScreenSpace, DecalKeywords.ScreenSpaceProjector);
public static PassDescriptor GetScreenSpaceProjector(PragmaCollection pragma, KeywordCollection keywords)
{
return new PassDescriptor
{
// Definition
displayName = DecalShaderPassNames.DecalScreenSpaceProjector,
referenceName = "SHADERPASS_DECAL_SCREEN_SPACE_PROJECTOR",
lightMode = DecalShaderPassNames.DecalScreenSpaceProjector,
useInPreview = false,
// Template
passTemplatePath = "Packages/com.unity.render-pipelines.universal/Editor/Decal/DecalPass.template",
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
// Port mask
validPixelBlocks = DecalBlockMasks.Fragment,
//Fields
structs = CoreStructCollections.Default,
requiredFields = DecalRequiredFields.ScreenSpaceProjector,
fieldDependencies = CoreFieldDependencies.Default,
renderStates = DecalRenderStates.ScreenSpaceProjector,
pragmas = pragma,
defines = DecalDefines.ProjectorWithEmission,
keywords = keywords,
includes = DecalIncludes.ScreenSpace,
};
}
public static PassDescriptor GBufferProjector = new PassDescriptor()
{
// Definition
displayName = DecalShaderPassNames.DecalGBufferProjector,
referenceName = "SHADERPASS_DECAL_GBUFFER_PROJECTOR",
lightMode = DecalShaderPassNames.DecalGBufferProjector,
useInPreview = false,
// Template
passTemplatePath = "Packages/com.unity.render-pipelines.universal/Editor/Decal/DecalPass.template",
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
// Port mask
validPixelBlocks = DecalBlockMasks.Fragment,
//Fields
structs = CoreStructCollections.Default,
requiredFields = DecalRequiredFields.GBufferProjector,
fieldDependencies = CoreFieldDependencies.Default,
renderStates = DecalRenderStates.GBufferProjector,
pragmas = DecalPragmas.GBuffer,
defines = DecalDefines.ProjectorWithEmission,
keywords = DecalKeywords.GBufferProjector,
includes = DecalIncludes.GBuffer,
};
public static PassDescriptor DBufferMesh = new PassDescriptor()
{
// Definition
displayName = DecalShaderPassNames.DBufferMesh,
referenceName = "SHADERPASS_DBUFFER_MESH",
lightMode = DecalShaderPassNames.DBufferMesh,
useInPreview = false,
// Template
passTemplatePath = "Packages/com.unity.render-pipelines.universal/Editor/Decal/DecalPass.template",
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
// Port mask
validPixelBlocks = DecalBlockMasks.FragmentWithoutEmessive,
//Fields
structs = CoreStructCollections.Default,
requiredFields = DecalRequiredFields.Mesh,
fieldDependencies = CoreFieldDependencies.Default,
// Conditional State
renderStates = DecalRenderStates.DBufferMesh,
pragmas = DecalPragmas.MultipleRenderTargets,
defines = DecalDefines.Mesh,
keywords = DecalKeywords.DBufferMesh,
includes = DecalIncludes.DBuffer,
};
public static PassDescriptor ForwardEmissiveMesh = new PassDescriptor()
{
// Definition
displayName = DecalShaderPassNames.DecalMeshForwardEmissive,
referenceName = "SHADERPASS_FORWARD_EMISSIVE_MESH",
lightMode = DecalShaderPassNames.DecalMeshForwardEmissive,
useInPreview = false,
// Template
passTemplatePath = "Packages/com.unity.render-pipelines.universal/Editor/Decal/DecalPass.template",
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
// Port mask
validPixelBlocks = DecalBlockMasks.Fragment,
//Fields
structs = CoreStructCollections.Default,
requiredFields = DecalRequiredFields.Mesh,
fieldDependencies = CoreFieldDependencies.Default,
// Conditional State
renderStates = DecalRenderStates.ForwardEmissiveMesh,
pragmas = DecalPragmas.MultipleRenderTargets,
defines = DecalDefines.MeshWithEmission,
keywords = DecalKeywords.ForwardEmissiveProjector,
includes = DecalIncludes.DBuffer,
};
public static PassDescriptor ScreenSpaceMesh = GetScreenSpaceMesh(DecalPragmas.ScreenSpace, DecalKeywords.ScreenSpaceMesh);
public static PassDescriptor GetScreenSpaceMesh(PragmaCollection pragma, KeywordCollection keywords)
{
return new PassDescriptor
{
// Definition
displayName = DecalShaderPassNames.DecalScreenSpaceMesh,
referenceName = "SHADERPASS_DECAL_SCREEN_SPACE_MESH",
lightMode = DecalShaderPassNames.DecalScreenSpaceMesh,
useInPreview = true,
// Template
passTemplatePath = "Packages/com.unity.render-pipelines.universal/Editor/Decal/DecalPass.template",
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
// Port mask
validPixelBlocks = DecalBlockMasks.Fragment, // todo
//Fields
structs = CoreStructCollections.Default,
requiredFields = DecalRequiredFields.ScreenSpaceMesh,
fieldDependencies = CoreFieldDependencies.Default,
renderStates = DecalRenderStates.ScreenSpaceMesh,
pragmas = pragma,
defines = DecalDefines.MeshWithEmission,
keywords = keywords,
includes = DecalIncludes.ScreenSpace,
};
}
public static PassDescriptor GBufferMesh = new PassDescriptor()
{
// Definition
displayName = DecalShaderPassNames.DecalGBufferMesh,
referenceName = "SHADERPASS_DECAL_GBUFFER_MESH",
lightMode = DecalShaderPassNames.DecalGBufferMesh,
useInPreview = false,
// Template
passTemplatePath = "Packages/com.unity.render-pipelines.universal/Editor/Decal/DecalPass.template",
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
// Port mask
validPixelBlocks = DecalBlockMasks.Fragment, // todo
//Fields
structs = CoreStructCollections.Default,
requiredFields = DecalRequiredFields.ScreenSpaceMesh,
fieldDependencies = CoreFieldDependencies.Default,
renderStates = DecalRenderStates.GBufferMesh,
pragmas = DecalPragmas.GBuffer,
defines = DecalDefines.MeshWithEmission,
keywords = DecalKeywords.GBufferMesh,
includes = DecalIncludes.GBuffer,
};
}
#endregion
#region PortMasks
static class DecalBlockMasks
{
public static BlockFieldDescriptor[] FragmentWithoutEmessive = new BlockFieldDescriptor[]
{
BlockFields.SurfaceDescription.BaseColor,
BlockFields.SurfaceDescription.Alpha,
BlockFields.SurfaceDescription.NormalTS,
UniversalBlockFields.SurfaceDescription.NormalAlpha,
BlockFields.SurfaceDescription.Metallic,
BlockFields.SurfaceDescription.Occlusion,
BlockFields.SurfaceDescription.Smoothness,
UniversalBlockFields.SurfaceDescription.MAOSAlpha,
};
public static BlockFieldDescriptor[] ForwardOnlyEmissive = new BlockFieldDescriptor[]
{
BlockFields.SurfaceDescription.Alpha,
BlockFields.SurfaceDescription.Emission,
};
public static BlockFieldDescriptor[] Fragment = new BlockFieldDescriptor[]
{
BlockFields.SurfaceDescription.BaseColor,
BlockFields.SurfaceDescription.Alpha,
BlockFields.SurfaceDescription.NormalTS,
UniversalBlockFields.SurfaceDescription.NormalAlpha,
BlockFields.SurfaceDescription.Metallic,
BlockFields.SurfaceDescription.Occlusion,
BlockFields.SurfaceDescription.Smoothness,
UniversalBlockFields.SurfaceDescription.MAOSAlpha,
BlockFields.SurfaceDescription.Emission,
};
}
#endregion
#region RequiredFields
static class DecalRequiredFields
{
public static FieldCollection Mesh = new FieldCollection()
{
StructFields.Attributes.normalOS,
StructFields.Attributes.tangentOS,
StructFields.Attributes.uv1,
StructFields.Attributes.uv2,
StructFields.Varyings.normalWS,
StructFields.Varyings.tangentWS,
StructFields.Varyings.positionWS,
StructFields.Varyings.texCoord0,
};
public static FieldCollection ScreenSpaceProjector = new FieldCollection()
{
StructFields.Varyings.normalWS,
UniversalStructFields.Varyings.staticLightmapUV,
UniversalStructFields.Varyings.dynamicLightmapUV,
UniversalStructFields.Varyings.sh,
UniversalStructFields.Varyings.probeOcclusion,
UniversalStructFields.Varyings.fogFactorAndVertexLight, // fog and vertex lighting, vert input is dependency
// todo
//UniversalStructFields.Varyings.shadowCoord, // shadow coord, vert input is dependency
};
public static FieldCollection GBufferProjector = new FieldCollection()
{
StructFields.Varyings.normalWS,
UniversalStructFields.Varyings.staticLightmapUV,
UniversalStructFields.Varyings.dynamicLightmapUV,
UniversalStructFields.Varyings.sh,
UniversalStructFields.Varyings.probeOcclusion,
// todo
//UniversalStructFields.Varyings.shadowCoord, // shadow coord, vert input is dependency
};
public static FieldCollection ScreenSpaceMesh = new FieldCollection()
{
StructFields.Attributes.normalOS,
StructFields.Attributes.tangentOS,
StructFields.Attributes.uv1,
StructFields.Attributes.uv2,
StructFields.Varyings.normalWS,
StructFields.Varyings.tangentWS,
StructFields.Varyings.positionWS,
StructFields.Varyings.texCoord0,
UniversalStructFields.Varyings.staticLightmapUV,
UniversalStructFields.Varyings.dynamicLightmapUV,
UniversalStructFields.Varyings.sh,
UniversalStructFields.Varyings.probeOcclusion,
UniversalStructFields.Varyings.fogFactorAndVertexLight, // fog and vertex lighting, vert input is dependency
// todo
//UniversalStructFields.Varyings.shadowCoord, // shadow coord, vert input is dependency
};
}
#endregion
#region ColorMask
static class DecalColorMasks
{
public static RenderStateDescriptor ColorMaskRGBA0 = RenderState.ColorMask("ColorMask RGBA");
public static RenderStateDescriptor ColorMaskNone0 = RenderState.ColorMask("ColorMask 0");
public static RenderStateDescriptor ColorMaskRGBA1 = RenderState.ColorMask("ColorMask RGBA 1");
public static RenderStateDescriptor ColorMaskNone1 = RenderState.ColorMask("ColorMask 0 1");
public static RenderStateDescriptor ColorMaskRGBA2 = RenderState.ColorMask("ColorMask RGBA 2");
public static RenderStateDescriptor ColorMaskNone2 = RenderState.ColorMask("ColorMask 0 2");
}
#endregion
#region RenderStates
static class DecalRenderStates
{
private readonly static string[] s_DBufferBlends = new string[]
{
"Blend 0 SrcAlpha OneMinusSrcAlpha, Zero OneMinusSrcAlpha",
"Blend 1 SrcAlpha OneMinusSrcAlpha, Zero OneMinusSrcAlpha",
"Blend 2 SrcAlpha OneMinusSrcAlpha, Zero OneMinusSrcAlpha",
};
private readonly static string[] s_GBufferBlends = new string[]
{
"Blend 0 SrcAlpha OneMinusSrcAlpha",
"Blend 1 SrcAlpha OneMinusSrcAlpha",
"Blend 2 SrcAlpha OneMinusSrcAlpha",
"Blend 3 SrcAlpha OneMinusSrcAlpha",
};
public static RenderStateCollection ScenePicking = new RenderStateCollection
{
{ RenderState.Cull(Cull.Back) },
};
public static RenderStateCollection DBufferProjector = new RenderStateCollection
{
{ RenderState.Blend(s_DBufferBlends[0]) },
{ RenderState.Blend(s_DBufferBlends[1]) },
{ RenderState.Blend(s_DBufferBlends[2]) },
{ RenderState.Cull(Cull.Front) },
{ RenderState.ZTest(ZTest.Greater) },
{ RenderState.ZWrite(ZWrite.Off) },
};
public static RenderStateCollection ForwardEmissiveProjector = new RenderStateCollection
{
{ RenderState.Blend("Blend 0 SrcAlpha One") },
{ RenderState.Cull(Cull.Front) },
{ RenderState.ZTest(ZTest.Greater) },
{ RenderState.ZWrite(ZWrite.Off) },
};
public static RenderStateCollection ScreenSpaceProjector = new RenderStateCollection
{
{ RenderState.Blend("Blend SrcAlpha OneMinusSrcAlpha") },
{ RenderState.Cull(Cull.Front) },
{ RenderState.ZTest(ZTest.Greater) },
{ RenderState.ZWrite(ZWrite.Off) },
};
public static RenderStateCollection GBufferProjector = new RenderStateCollection
{
{ RenderState.Blend(s_GBufferBlends[0]) },
{ RenderState.Blend(s_GBufferBlends[1]) },
{ RenderState.Blend(s_GBufferBlends[2]) },
{ RenderState.Blend(s_GBufferBlends[3]) },
{ RenderState.Cull(Cull.Front) },
{ RenderState.ZTest(ZTest.Greater) },
{ RenderState.ZWrite(ZWrite.Off) },
};
public static RenderStateCollection DBufferMesh = new RenderStateCollection
{
{ RenderState.Blend(s_DBufferBlends[0]) },
{ RenderState.Blend(s_DBufferBlends[1]) },
{ RenderState.Blend(s_DBufferBlends[2]) },
{ RenderState.ZTest(ZTest.LEqual) },
{ RenderState.ZWrite(ZWrite.Off) },
};
public static RenderStateCollection ForwardEmissiveMesh = new RenderStateCollection
{
{ RenderState.Blend("Blend 0 SrcAlpha One") },
{ RenderState.ZTest(ZTest.LEqual) },
{ RenderState.ZWrite(ZWrite.Off) },
};
public static RenderStateCollection ScreenSpaceMesh = new RenderStateCollection
{
{ RenderState.Blend("Blend SrcAlpha OneMinusSrcAlpha") },
{ RenderState.ZTest(ZTest.LEqual) },
{ RenderState.ZWrite(ZWrite.Off) },
};
public static RenderStateCollection GBufferMesh = new RenderStateCollection
{
{ RenderState.Blend(s_GBufferBlends[0]) },
{ RenderState.Blend(s_GBufferBlends[1]) },
{ RenderState.Blend(s_GBufferBlends[2]) },
{ RenderState.Blend(s_GBufferBlends[3]) },
{ RenderState.ZWrite(ZWrite.Off) },
};
}
#endregion
#region Pragmas
static class DecalPragmas
{
public static PragmaCollection ScreenSpace = new PragmaCollection
{
{ Pragma.Target(ShaderModel.Target25) },
{ Pragma.Vertex("Vert") },
{ Pragma.Fragment("Frag") },
{ Pragma.MultiCompileInstancing },
{ Pragma.MultiCompileFog },
{ Pragma.EditorSyncCompilation },
};
public static PragmaCollection GBuffer = new PragmaCollection
{
{ Pragma.Target(ShaderModel.Target45) }, // MRT4
{ Pragma.ExcludeRenderers(new[] { Platform.GLES3, Platform.GLCore }) },
{ Pragma.Vertex("Vert") },
{ Pragma.Fragment("Frag") },
{ Pragma.MultiCompileInstancing },
{ Pragma.MultiCompileFog },
{ Pragma.EditorSyncCompilation },
};
public static PragmaCollection MultipleRenderTargets = new PragmaCollection
{
{ Pragma.Target(ShaderModel.Target45) }, // MRT4
{ Pragma.ExcludeRenderers(new[] { Platform.GLES3, Platform.GLCore }) },
{ Pragma.Vertex("Vert") },
{ Pragma.Fragment("Frag") },
{ Pragma.MultiCompileInstancing },
{ Pragma.EditorSyncCompilation },
};
public static readonly PragmaCollection Instanced = new PragmaCollection
{
{ Pragma.Target(ShaderModel.Target20) },
{ Pragma.MultiCompileInstancing },
{ Pragma.EditorSyncCompilation },
{ Pragma.Vertex("Vert") },
{ Pragma.Fragment("Frag") },
};
}
#endregion
#region Defines
static class DecalDefines
{
private static class Descriptors
{
public static KeywordDescriptor AffectsAlbedo = new KeywordDescriptor()
{
displayName = "Affects Albedo",
referenceName = "_MATERIAL_AFFECTS_ALBEDO",
type = KeywordType.Boolean,
};
public static KeywordDescriptor AffectsNormal = new KeywordDescriptor()
{
displayName = "Affects Normal",
referenceName = "_MATERIAL_AFFECTS_NORMAL",
type = KeywordType.Boolean,
};
public static KeywordDescriptor AffectsNormalBlend = new KeywordDescriptor()
{
displayName = "Affects Normal Blend",
referenceName = "_MATERIAL_AFFECTS_NORMAL_BLEND",
type = KeywordType.Boolean,
};
public static KeywordDescriptor AffectsMAOS = new KeywordDescriptor()
{
displayName = "Affects Metal",
referenceName = "_MATERIAL_AFFECTS_MAOS",
type = KeywordType.Boolean,
};
public static KeywordDescriptor AffectsEmission = new KeywordDescriptor()
{
displayName = "Affects Emission",
referenceName = "_MATERIAL_AFFECTS_EMISSION",
type = KeywordType.Boolean,
};
public static KeywordDescriptor AngleFade = new KeywordDescriptor()
{
displayName = "Angle Fade",
referenceName = "DECAL_ANGLE_FADE",
type = KeywordType.Boolean,
};
public static KeywordDescriptor ScenePickingPass = new KeywordDescriptor()
{
displayName = "Scene Picking Pass",
referenceName = "SCENEPICKINGPASS",
type = KeywordType.Boolean,
};
}
public static DefineCollection Projector = new DefineCollection
{
{ Descriptors.AffectsAlbedo, 1, new FieldCondition(AffectsAlbedo, true) },
{ Descriptors.AffectsNormal, 1, new FieldCondition(AffectsNormal, true) },
{ Descriptors.AffectsNormalBlend, 1, new FieldCondition(AffectsNormalBlend, true) },
{ Descriptors.AffectsMAOS, 1, new FieldCondition(AffectsMAOS, true) },
{ Descriptors.AngleFade, 1, new FieldCondition(AngleFade, true) }
};
public static DefineCollection ProjectorEmission = new DefineCollection
{
{ Descriptors.AngleFade, 1, new FieldCondition(AngleFade, true) },
{ Descriptors.AffectsEmission, 1, new FieldCondition(AffectsEmission, true) },
};
public static DefineCollection ProjectorWithEmission = new DefineCollection
{
{ Projector },
{ Descriptors.AffectsEmission, 1, new FieldCondition(AffectsEmission, true) },
};
public static DefineCollection Mesh = new DefineCollection
{
{ Descriptors.AffectsAlbedo, 1, new FieldCondition(AffectsAlbedo, true) },
{ Descriptors.AffectsNormal, 1, new FieldCondition(AffectsNormal, true) },
{ Descriptors.AffectsNormalBlend, 1, new FieldCondition(AffectsNormalBlend, true) },
{ Descriptors.AffectsMAOS, 1, new FieldCondition(AffectsMAOS, true) },
{ CoreKeywordDescriptors.UseUnityCrossFade, 1, new FieldCondition(Fields.LodCrossFade, true) }
};
public static DefineCollection MeshEmission = new DefineCollection
{
{ Descriptors.AffectsEmission, 1, new FieldCondition(AffectsEmission, true) },
};
public static DefineCollection MeshWithEmission = new DefineCollection
{
{ Mesh },
{ Descriptors.AffectsEmission, 1, new FieldCondition(AffectsEmission, true) },
};
public static DefineCollection ScenePicking = new DefineCollection { { Descriptors.ScenePickingPass, 1 }, };
}
#endregion
#region Keywords
static class DecalKeywords
{
static class Descriptors
{
public static KeywordDescriptor DecalsNormalBlend = new KeywordDescriptor()
{
displayName = "Decal Normal Blend",
referenceName = "_DECAL_NORMAL_BLEND",
type = KeywordType.Enum,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
entries = new KeywordEntry[]
{
new KeywordEntry() { displayName = "LOW", referenceName = "LOW" },
new KeywordEntry() { displayName = "MEDIUM", referenceName = "MEDIUM" },
new KeywordEntry() { displayName = "HIGH", referenceName = "HIGH" },
}
};
public static readonly KeywordDescriptor DecalLayers = new KeywordDescriptor()
{
displayName = "Decal Layers",
referenceName = "_DECAL_LAYERS",
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
};
}
public static KeywordCollection DBufferMesh = new KeywordCollection
{
{ CoreKeywordDescriptors.DBuffer },
{ CoreKeywordDescriptors.LODFadeCrossFade, new FieldCondition(Fields.LodCrossFade, true) },
{ Descriptors.DecalLayers },
};
public static KeywordCollection DBufferProjector = new KeywordCollection
{
{ CoreKeywordDescriptors.DBuffer },
{ Descriptors.DecalLayers },
};
public static KeywordCollection ForwardEmissiveProjector = new KeywordCollection
{
{ Descriptors.DecalLayers },
};
public static readonly KeywordCollection ScreenSpaceMeshGl = new KeywordCollection
{
{ CoreKeywordDescriptors.StaticLightmap },
{ CoreKeywordDescriptors.DynamicLightmap },
{ CoreKeywordDescriptors.DirectionalLightmapCombined },
{ CoreKeywordDescriptors.UseLegacyLightmaps },
{ CoreKeywordDescriptors.MainLightShadows },
{ CoreKeywordDescriptors.AdditionalLights },
{ CoreKeywordDescriptors.AdditionalLightShadows },
{ CoreKeywordDescriptors.ShadowsSoft },
{ CoreKeywordDescriptors.LightmapShadowMixing },
{ CoreKeywordDescriptors.ShadowsShadowmask },
{ CoreKeywordDescriptors.ForwardPlus },
{ Descriptors.DecalsNormalBlend },
{ CoreKeywordDescriptors.LODFadeCrossFade, new FieldCondition(Fields.LodCrossFade, true) },
{ CoreKeywordDescriptors.DebugDisplay },
};
public static readonly KeywordCollection ScreenSpaceMesh = new KeywordCollection
{
{ ScreenSpaceMeshGl },
{ Descriptors.DecalLayers },
};
public static readonly KeywordCollection ScreenSpaceProjector = new KeywordCollection
{
{ CoreKeywordDescriptors.MainLightShadows },
{ CoreKeywordDescriptors.AdditionalLights },
{ CoreKeywordDescriptors.AdditionalLightShadows },
{ CoreKeywordDescriptors.ShadowsSoft },
{ CoreKeywordDescriptors.ForwardPlus },
{ CoreKeywordDescriptors.LightCookies },
{ CoreKeywordDescriptors.DebugDisplay },
{ Descriptors.DecalsNormalBlend },
{ Descriptors.DecalLayers },
};
public static readonly KeywordCollection GBufferMesh = new KeywordCollection
{
{ CoreKeywordDescriptors.StaticLightmap },
{ CoreKeywordDescriptors.DynamicLightmap },
{ CoreKeywordDescriptors.DirectionalLightmapCombined },
{ CoreKeywordDescriptors.UseLegacyLightmaps },
{ CoreKeywordDescriptors.MainLightShadows },
{ CoreKeywordDescriptors.ShadowsSoft },
{ CoreKeywordDescriptors.LightmapShadowMixing },
{ CoreKeywordDescriptors.MixedLightingSubtractive },
{ Descriptors.DecalsNormalBlend },
{ Descriptors.DecalLayers },
{ CoreKeywordDescriptors.GBufferNormalsOct },
{ CoreKeywordDescriptors.RenderPassEnabled },
{ CoreKeywordDescriptors.LODFadeCrossFade, new FieldCondition(Fields.LodCrossFade, true) },
};
public static readonly KeywordCollection GBufferProjector = new KeywordCollection
{
{ CoreKeywordDescriptors.MainLightShadows },
{ CoreKeywordDescriptors.ShadowsSoft },
{ Descriptors.DecalsNormalBlend },
{ Descriptors.DecalLayers },
{ CoreKeywordDescriptors.GBufferNormalsOct },
{ CoreKeywordDescriptors.RenderPassEnabled },
};
}
#endregion
#region Includes
static class DecalIncludes
{
const string kDecalInput = "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DecalInput.hlsl";
const string kShaderVariablesDecal = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/ShaderVariablesDecal.hlsl";
const string kPassDecal = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/ShaderPassDecal.hlsl";
const string kShaderPass = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/ShaderPass.hlsl";
const string kVaryings = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/Varyings.hlsl";
const string kDBuffer = "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DBuffer.hlsl";
const string kGBuffer = "Packages/com.unity.render-pipelines.universal/ShaderLibrary/UnityGBuffer.hlsl";
const string kLODCrossFade = "Packages/com.unity.render-pipelines.universal/ShaderLibrary/LODCrossFade.hlsl";
public static IncludeCollection DecalPregraph = new IncludeCollection
{
{ kShaderPass, IncludeLocation.Pregraph },
{ kDecalInput, IncludeLocation.Pregraph },
{ kShaderVariablesDecal, IncludeLocation.Pregraph },
};
public static IncludeCollection DecalPostgraph = new IncludeCollection
{
{ kVaryings, IncludeLocation.Postgraph },
{ kPassDecal, IncludeLocation.Postgraph },
};
public static IncludeCollection DBuffer = new IncludeCollection
{
// Pre-graph
{ CoreIncludes.DOTSPregraph },
{ CoreIncludes.CorePregraph },
{ CoreIncludes.ShaderGraphPregraph },
{ CoreIncludes.ProbeVolumePregraph },
{ DecalPregraph },
{ kDBuffer, IncludeLocation.Pregraph },
{ kLODCrossFade, IncludeLocation.Pregraph, new FieldCondition(Fields.LodCrossFade, true) },
// Post-graph
{ DecalPostgraph },
};
public static IncludeCollection ScreenSpace = new IncludeCollection
{
// Pre-graph
{ CoreIncludes.DOTSPregraph },
{ CoreIncludes.CorePregraph },
{ CoreIncludes.ShaderGraphPregraph },
{ CoreIncludes.ProbeVolumePregraph },
{ DecalPregraph },
{ kLODCrossFade, IncludeLocation.Pregraph, new FieldCondition(Fields.LodCrossFade, true) },
// Post-graph
{ DecalPostgraph },
};
public static IncludeCollection GBuffer = new IncludeCollection
{
// Pre-graph
{ CoreIncludes.DOTSPregraph },
{ CoreIncludes.CorePregraph },
{ CoreIncludes.ShaderGraphPregraph },
{ CoreIncludes.ProbeVolumePregraph },
{ kGBuffer, IncludeLocation.Pregraph },
{ DecalPregraph },
{ kLODCrossFade, IncludeLocation.Pregraph, new FieldCondition(Fields.LodCrossFade, true) },
// Post-graph
{ DecalPostgraph },
};
public static IncludeCollection ScenePicking = new IncludeCollection
{
// Pre-graph
{ CoreIncludes.CorePregraph },
{ CoreIncludes.ShaderGraphPregraph },
{ DecalPregraph },
// Post-graph
{ DecalPostgraph },
};
}
#endregion
}
}