331 lines
16 KiB
C#
331 lines
16 KiB
C#
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using UnityEditor.Graphing;
|
|
using UnityEngine; // Vector3,4
|
|
using UnityEditor.ShaderGraph;
|
|
using UnityEditor.ShaderGraph.Internal;
|
|
using UnityEngine.Rendering.HighDefinition;
|
|
using UnityEngine.Rendering;
|
|
using UnityEditor.Rendering.HighDefinition.ShaderGraph;
|
|
using UnityEditor.ShaderGraph.Legacy;
|
|
using ShaderPass = UnityEditor.ShaderGraph.PassDescriptor;
|
|
|
|
// Include material common properties names
|
|
using static UnityEngine.Rendering.HighDefinition.HDMaterialProperties;
|
|
|
|
namespace UnityEditor.Rendering.HighDefinition
|
|
{
|
|
internal enum HDRenderTypeTags
|
|
{
|
|
HDLitShader, // For Lit, LayeredLit, LitTesselation, LayeredLitTesselation
|
|
HDUnlitShader, // Unlit
|
|
Opaque, // Used by Terrain
|
|
}
|
|
|
|
static class HDSubShaderUtilities
|
|
{
|
|
// Utils property to add properties to the collector, all hidden because we use a custom UI to display them
|
|
static void AddIntProperty(this PropertyCollector collector, string referenceName, int defaultValue, HLSLDeclaration declarationType = HLSLDeclaration.DoNotDeclare)
|
|
{
|
|
collector.AddShaderProperty(new Vector1ShaderProperty
|
|
{
|
|
floatType = FloatType.Integer,
|
|
value = defaultValue,
|
|
hidden = true,
|
|
overrideHLSLDeclaration = true,
|
|
hlslDeclarationOverride = declarationType,
|
|
overrideReferenceName = referenceName,
|
|
});
|
|
}
|
|
|
|
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,
|
|
overrideReferenceName = referenceName,
|
|
});
|
|
}
|
|
|
|
static void AddFloatProperty(this PropertyCollector collector, string referenceName, string displayName, float defaultValue, HLSLDeclaration declarationType = HLSLDeclaration.DoNotDeclare)
|
|
{
|
|
collector.AddShaderProperty(new Vector1ShaderProperty
|
|
{
|
|
floatType = FloatType.Default,
|
|
value = defaultValue,
|
|
overrideReferenceName = referenceName,
|
|
hidden = true,
|
|
overrideHLSLDeclaration = true,
|
|
hlslDeclarationOverride = declarationType,
|
|
displayName = displayName,
|
|
});
|
|
}
|
|
|
|
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,
|
|
overrideReferenceName = referenceName,
|
|
});
|
|
}
|
|
|
|
public static void AddStencilShaderProperties(PropertyCollector collector, SystemData systemData, LightingData lightingData, bool splitLighting)
|
|
{
|
|
bool ssrStencil = false;
|
|
|
|
if (lightingData != null)
|
|
{
|
|
ssrStencil = systemData.surfaceType == SurfaceType.Opaque ? lightingData.receiveSSR : lightingData.receiveSSRTransparent;
|
|
bool receiveSSROpaque = lightingData.receiveSSR;
|
|
bool receiveSSRTransparent = lightingData.receiveSSRTransparent;
|
|
bool receiveDecals = lightingData.receiveDecals;
|
|
bool blendPreserveSpecular = lightingData.blendPreserveSpecular;
|
|
|
|
// Don't add those property on Unlit
|
|
collector.AddToggleProperty(kUseSplitLighting, splitLighting);
|
|
collector.AddToggleProperty(kReceivesSSR, receiveSSROpaque);
|
|
collector.AddToggleProperty(kReceivesSSRTransparent, receiveSSRTransparent);
|
|
collector.AddToggleProperty(kEnableBlendModePreserveSpecularLighting, blendPreserveSpecular, HLSLDeclaration.UnityPerMaterial);
|
|
collector.AddToggleProperty(kSupportDecals, receiveDecals);
|
|
}
|
|
else
|
|
{
|
|
// We still need to define it on unlit as it is needed to compile when Material.hlsl is used
|
|
collector.AddToggleProperty(kEnableBlendModePreserveSpecularLighting, false, HLSLDeclaration.UnityPerMaterial);
|
|
}
|
|
|
|
// Configure render state
|
|
BaseLitGUI.ComputeStencilProperties(ssrStencil, splitLighting, out int stencilRef, out int stencilWriteMask,
|
|
out int stencilRefDepth, out int stencilWriteMaskDepth, out int stencilRefGBuffer, out int stencilWriteMaskGBuffer,
|
|
out int stencilRefMV, out int stencilWriteMaskMV
|
|
);
|
|
|
|
// All these properties values will be patched with the material keyword update
|
|
collector.AddIntProperty("_StencilRef", stencilRef);
|
|
collector.AddIntProperty("_StencilWriteMask", stencilWriteMask);
|
|
// Depth prepass
|
|
collector.AddIntProperty("_StencilRefDepth", stencilRefDepth); // Nothing
|
|
collector.AddIntProperty("_StencilWriteMaskDepth", stencilWriteMaskDepth); // StencilUsage.TraceReflectionRay
|
|
// Motion vector pass
|
|
collector.AddIntProperty("_StencilRefMV", stencilRefMV); // StencilUsage.ObjectMotionVector
|
|
collector.AddIntProperty("_StencilWriteMaskMV", stencilWriteMaskMV); // StencilUsage.ObjectMotionVector
|
|
// Distortion vector pass
|
|
collector.AddIntProperty("_StencilRefDistortionVec", (int)StencilUsage.DistortionVectors);
|
|
collector.AddIntProperty("_StencilWriteMaskDistortionVec", (int)StencilUsage.DistortionVectors);
|
|
// Gbuffer
|
|
collector.AddIntProperty("_StencilWriteMaskGBuffer", stencilWriteMaskGBuffer);
|
|
collector.AddIntProperty("_StencilRefGBuffer", stencilRefGBuffer);
|
|
collector.AddIntProperty("_ZTestGBuffer", 4);
|
|
}
|
|
|
|
public static void AddBlendingStatesShaderProperties(
|
|
PropertyCollector collector, SurfaceType surface, BlendMode blend, int sortingPriority,
|
|
bool alphaToMask, bool transparentZWrite, TransparentCullMode transparentCullMode,
|
|
OpaqueCullMode opaqueCullMode, CompareFunction zTest,
|
|
bool backThenFrontRendering, bool fogOnTransparent)
|
|
{
|
|
collector.AddFloatProperty("_SurfaceType", (int)surface);
|
|
collector.AddFloatProperty("_BlendMode", (int)blend, HLSLDeclaration.UnityPerMaterial);
|
|
|
|
// All these properties values will be patched with the material keyword update
|
|
collector.AddFloatProperty("_SrcBlend", 1.0f);
|
|
collector.AddFloatProperty("_DstBlend", 0.0f);
|
|
collector.AddFloatProperty("_AlphaSrcBlend", 1.0f);
|
|
collector.AddFloatProperty("_AlphaDstBlend", 0.0f);
|
|
collector.AddToggleProperty("_AlphaToMask", alphaToMask);
|
|
collector.AddToggleProperty("_AlphaToMaskInspectorValue", alphaToMask);
|
|
collector.AddToggleProperty(kZWrite, (surface == SurfaceType.Transparent) ? transparentZWrite : true);
|
|
collector.AddToggleProperty(kTransparentZWrite, transparentZWrite);
|
|
collector.AddFloatProperty("_CullMode", (int)CullMode.Back);
|
|
collector.AddIntProperty(kTransparentSortPriority, sortingPriority);
|
|
collector.AddToggleProperty(kEnableFogOnTransparent, fogOnTransparent);
|
|
collector.AddFloatProperty("_CullModeForward", (int)CullMode.Back);
|
|
collector.AddShaderProperty(new Vector1ShaderProperty
|
|
{
|
|
overrideReferenceName = kTransparentCullMode,
|
|
floatType = FloatType.Enum,
|
|
value = (int)transparentCullMode,
|
|
enumNames = {"Front", "Back"},
|
|
enumValues = {(int)TransparentCullMode.Front, (int)TransparentCullMode.Back},
|
|
hidden = true,
|
|
overrideHLSLDeclaration = true,
|
|
hlslDeclarationOverride = HLSLDeclaration.DoNotDeclare,
|
|
});
|
|
collector.AddShaderProperty(new Vector1ShaderProperty
|
|
{
|
|
overrideReferenceName = kOpaqueCullMode,
|
|
floatType = FloatType.Enum,
|
|
value = (int)opaqueCullMode,
|
|
enumType = EnumType.CSharpEnum,
|
|
cSharpEnumType = typeof(OpaqueCullMode),
|
|
hidden = true,
|
|
overrideHLSLDeclaration = true,
|
|
hlslDeclarationOverride = HLSLDeclaration.DoNotDeclare,
|
|
});
|
|
|
|
// Add ZTest properties:
|
|
collector.AddIntProperty("_ZTestDepthEqualForOpaque", (int)CompareFunction.LessEqual);
|
|
collector.AddShaderProperty(new Vector1ShaderProperty
|
|
{
|
|
overrideReferenceName = kZTestTransparent,
|
|
floatType = FloatType.Enum,
|
|
value = (int)zTest,
|
|
enumType = EnumType.CSharpEnum,
|
|
cSharpEnumType = typeof(CompareFunction),
|
|
hidden = true,
|
|
overrideHLSLDeclaration = true,
|
|
hlslDeclarationOverride = HLSLDeclaration.DoNotDeclare,
|
|
});
|
|
|
|
collector.AddToggleProperty(kTransparentBackfaceEnable, backThenFrontRendering);
|
|
}
|
|
|
|
public static void AddAlphaCutoffShaderProperties(PropertyCollector collector, bool alphaCutoff, bool shadowThreshold)
|
|
{
|
|
collector.AddToggleProperty("_AlphaCutoffEnable", alphaCutoff);
|
|
collector.AddFloatProperty(kTransparentSortPriority, kTransparentSortPriority, 0);
|
|
collector.AddToggleProperty("_UseShadowThreshold", shadowThreshold, HLSLDeclaration.UnityPerMaterial);
|
|
}
|
|
|
|
public static void AddDoubleSidedProperty(PropertyCollector collector, DoubleSidedMode mode = DoubleSidedMode.Enabled)
|
|
{
|
|
var normalMode = ConvertDoubleSidedModeToDoubleSidedNormalMode(mode);
|
|
collector.AddToggleProperty("_DoubleSidedEnable", mode != DoubleSidedMode.Disabled);
|
|
collector.AddShaderProperty(new Vector1ShaderProperty
|
|
{
|
|
enumNames = {"Flip", "Mirror", "None"}, // values will be 0, 1 and 2
|
|
floatType = FloatType.Enum,
|
|
overrideReferenceName = "_DoubleSidedNormalMode",
|
|
hidden = true,
|
|
overrideHLSLDeclaration = true,
|
|
hlslDeclarationOverride = HLSLDeclaration.DoNotDeclare,
|
|
value = (int)normalMode
|
|
});
|
|
collector.AddShaderProperty(new Vector4ShaderProperty
|
|
{
|
|
overrideReferenceName = "_DoubleSidedConstants",
|
|
hidden = true,
|
|
overrideHLSLDeclaration = true,
|
|
hlslDeclarationOverride = HLSLDeclaration.UnityPerMaterial,
|
|
value = new Vector4(1, 1, -1, 0)
|
|
});
|
|
}
|
|
|
|
public static void AddRayTracingProperty(PropertyCollector collector, bool isRayTracing)
|
|
{
|
|
collector.AddToggleProperty("_RayTracing", isRayTracing, HLSLDeclaration.UnityPerMaterial);
|
|
}
|
|
|
|
public static void AddPrePostPassProperties(PropertyCollector collector, bool prepass, bool postpass)
|
|
{
|
|
collector.AddToggleProperty(kTransparentDepthPrepassEnable, prepass);
|
|
collector.AddToggleProperty(kTransparentDepthPostpassEnable, postpass);
|
|
}
|
|
|
|
public static string RenderQueueName(HDRenderQueue.RenderQueueType value)
|
|
{
|
|
switch (value)
|
|
{
|
|
case HDRenderQueue.RenderQueueType.Opaque:
|
|
return "Default";
|
|
case HDRenderQueue.RenderQueueType.AfterPostProcessOpaque:
|
|
return "After Post-process";
|
|
case HDRenderQueue.RenderQueueType.PreRefraction:
|
|
return "Before Refraction";
|
|
case HDRenderQueue.RenderQueueType.Transparent:
|
|
return "Default";
|
|
case HDRenderQueue.RenderQueueType.LowTransparent:
|
|
return "Low Resolution";
|
|
case HDRenderQueue.RenderQueueType.AfterPostprocessTransparent:
|
|
return "After Post-process";
|
|
|
|
default:
|
|
return "None";
|
|
}
|
|
}
|
|
|
|
public static System.Collections.Generic.List<HDRenderQueue.RenderQueueType> GetRenderingPassList(bool opaque, bool needAfterPostProcess)
|
|
{
|
|
// We can't use RenderPipelineManager.currentPipeline here because this is called before HDRP is created by SG window
|
|
var result = new System.Collections.Generic.List<HDRenderQueue.RenderQueueType>();
|
|
if (opaque)
|
|
{
|
|
result.Add(HDRenderQueue.RenderQueueType.Opaque);
|
|
if (needAfterPostProcess)
|
|
result.Add(HDRenderQueue.RenderQueueType.AfterPostProcessOpaque);
|
|
}
|
|
else
|
|
{
|
|
result.Add(HDRenderQueue.RenderQueueType.PreRefraction);
|
|
result.Add(HDRenderQueue.RenderQueueType.Transparent);
|
|
result.Add(HDRenderQueue.RenderQueueType.LowTransparent);
|
|
if (needAfterPostProcess)
|
|
result.Add(HDRenderQueue.RenderQueueType.AfterPostprocessTransparent);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static bool IsValidRenderingPassValue(HDRenderQueue.RenderQueueType value, bool needAfterPostProcess)
|
|
{
|
|
if (!needAfterPostProcess && (value == HDRenderQueue.RenderQueueType.AfterPostProcessOpaque || value == HDRenderQueue.RenderQueueType.AfterPostprocessTransparent))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
public static bool UpgradeLegacyAlphaClip(IMasterNode1 masterNode)
|
|
{
|
|
var clipThresholdId = 8;
|
|
var node = masterNode as AbstractMaterialNode;
|
|
var clipThresholdSlot = node.FindSlot<Vector1MaterialSlot>(clipThresholdId);
|
|
if (clipThresholdSlot == null)
|
|
return false;
|
|
|
|
clipThresholdSlot.owner = node;
|
|
return (clipThresholdSlot.isConnected || clipThresholdSlot.value > 0.0f);
|
|
}
|
|
|
|
public static BlendMode UpgradeLegacyAlphaModeToBlendMode(int alphaMode)
|
|
{
|
|
switch (alphaMode)
|
|
{
|
|
case 0: //AlphaMode.Alpha:
|
|
return BlendMode.Alpha;
|
|
case 1: //AlphaMode.Premultiply:
|
|
return BlendMode.Premultiply;
|
|
case 2: //AlphaMode.Additive:
|
|
return BlendMode.Additive;
|
|
case 3: //AlphaMode.Multiply: // In case of multiply we fall back to Premultiply
|
|
return BlendMode.Premultiply;
|
|
default:
|
|
throw new System.Exception("Unknown AlphaMode at index: " + alphaMode + ": can't convert to BlendMode.");
|
|
}
|
|
}
|
|
|
|
public static DoubleSidedNormalMode ConvertDoubleSidedModeToDoubleSidedNormalMode(DoubleSidedMode shaderGraphMode)
|
|
{
|
|
switch (shaderGraphMode)
|
|
{
|
|
case DoubleSidedMode.FlippedNormals:
|
|
return DoubleSidedNormalMode.Flip;
|
|
case DoubleSidedMode.MirroredNormals:
|
|
return DoubleSidedNormalMode.Mirror;
|
|
case DoubleSidedMode.Enabled:
|
|
case DoubleSidedMode.Disabled:
|
|
default:
|
|
return DoubleSidedNormalMode.None;
|
|
}
|
|
}
|
|
}
|
|
}
|