You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

405 lines
20 KiB

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;
using DoubleSidedGIMode = UnityEngine.Rendering.HighDefinition.DoubleSidedGIMode;
// 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
HDFogVolumeShader, // Fog Volume ShaderGraphs
}
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 AddSliderProperty(this PropertyCollector collector, string referenceName, string displayName, float defaultValue, Vector2 range, HLSLDeclaration declarationType = HLSLDeclaration.DoNotDeclare)
{
collector.AddShaderProperty(new Vector1ShaderProperty
{
floatType = FloatType.Slider,
rangeValues = range,
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 receivesLighting, bool forwardOnly)
{
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);
}
bool excludeFromTUAndAA = systemData?.excludeFromTUAndAA ?? false;
collector.AddToggleProperty(kExcludeFromTUAndAA, excludeFromTUAndAA);
// Configure render state
BaseLitAPI.ComputeStencilProperties(
receivesLighting,
forwardOnly,
ssrStencil,
splitLighting,
false,
excludeFromTUAndAA,
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
if (!forwardOnly)
{
collector.AddIntProperty(kStencilWriteMaskGBuffer, stencilWriteMaskGBuffer);
collector.AddIntProperty(kStencilRefGBuffer, stencilRefGBuffer);
collector.AddIntProperty(kZTestGBuffer, 4);
}
}
public static void AddBlendingStatesShaderProperties(
PropertyCollector collector, SurfaceType surface, BlendingMode blending, int sortingPriority,
bool transparentZWrite, TransparentCullMode transparentCullMode,
OpaqueCullMode opaqueCullMode, CompareFunction zTest,
bool backThenFrontRendering, bool fogOnTransparent, HDRenderQueue.RenderQueueType renderQueueType)
{
collector.AddFloatProperty("_SurfaceType", (int)surface);
collector.AddFloatProperty("_BlendMode", (int)blending, 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("_DstBlend2", 0.0f);
collector.AddFloatProperty("_AlphaSrcBlend", 1.0f);
collector.AddFloatProperty("_AlphaDstBlend", 0.0f);
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 (keep in sync with BaseUnlitAPI opaque ztest setup):
if (surface == SurfaceType.Opaque)
{
if (HDRenderQueue.GetOpaqueEquivalent(renderQueueType) == HDRenderQueue.RenderQueueType.AfterPostProcessOpaque)
collector.AddIntProperty("_ZTestDepthEqualForOpaque", (int)CompareFunction.LessEqual);
else
collector.AddIntProperty("_ZTestDepthEqualForOpaque", (int)CompareFunction.Equal);
}
else
{
collector.AddIntProperty("_ZTestDepthEqualForOpaque", (int)zTest);
}
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 AddTessellationShaderProperties(PropertyCollector collector, TessellationMode tessellationMode,
float tessellationFactorMinDistance, float tessellationFactorMaxDistance, float tessellationFactorTriangleSize,
float tessellationShapeFactor, float tessellationBackFaceCullEpsilon, float tessellationMaxDisplacement)
{
collector.AddShaderProperty(new Vector1ShaderProperty
{
overrideReferenceName = kTessellationMode,
floatType = FloatType.Enum,
value = (int)tessellationMode,
enumNames = { "None", "Phong" },
enumValues = { (int)TessellationMode.None, (int)TessellationMode.Phong },
hidden = true,
overrideHLSLDeclaration = true,
hlslDeclarationOverride = HLSLDeclaration.DoNotDeclare,
});
collector.AddFloatProperty(kTessellationFactorMinDistance, tessellationFactorMinDistance, HLSLDeclaration.UnityPerMaterial);
collector.AddFloatProperty(kTessellationFactorMaxDistance, tessellationFactorMaxDistance, HLSLDeclaration.UnityPerMaterial);
collector.AddFloatProperty(kTessellationFactorTriangleSize, tessellationFactorTriangleSize, HLSLDeclaration.UnityPerMaterial);
collector.AddSliderProperty(kTessellationShapeFactor, "Tessellation shape factor", tessellationShapeFactor, new Vector2(0.0f, 1.0f), HLSLDeclaration.UnityPerMaterial);
collector.AddSliderProperty(kTessellationBackFaceCullEpsilon, "Tessellation back face epsilon", tessellationBackFaceCullEpsilon, new Vector2(-1.0f, 0.0f), HLSLDeclaration.UnityPerMaterial);
collector.AddFloatProperty(kTessellationMaxDisplacement, tessellationMaxDisplacement, HLSLDeclaration.UnityPerMaterial);
}
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, DoubleSidedGIMode giMode = DoubleSidedGIMode.Auto)
{
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)
});
collector.AddShaderProperty(new Vector1ShaderProperty
{
enumNames = { "Auto", "On", "Off" }, // values will be 0, 1 and 2
floatType = FloatType.Enum,
overrideReferenceName = "_DoubleSidedGIMode",
hidden = true,
overrideHLSLDeclaration = true,
hlslDeclarationOverride = HLSLDeclaration.DoNotDeclare,
value = (int)giMode
});
}
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)
{
return needAfterPostProcess || (value != HDRenderQueue.RenderQueueType.AfterPostProcessOpaque && value != HDRenderQueue.RenderQueueType.AfterPostprocessTransparent);
}
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 BlendingMode UpgradeLegacyAlphaModeToBlendMode(int alphaMode)
{
switch (alphaMode)
{
case 0: //AlphaMode.Alpha:
return BlendingMode.Alpha;
case 1: //AlphaMode.Premultiply:
return BlendingMode.Premultiply;
case 2: //AlphaMode.Additive:
return BlendingMode.Additive;
case 3: //AlphaMode.Multiply: // In case of multiply we fall back to Premultiply
return BlendingMode.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;
}
}
}
}