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.
 
 
 
 

410 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);
// WW1MOD: added composition mask on stencil user bit 0
bool compositionMask = systemData?.compositionMask ?? false;
collector.AddToggleProperty(kCompositionMask, compositionMask);
// Configure render state
BaseLitAPI.ComputeStencilProperties(
receivesLighting,
forwardOnly,
ssrStencil,
splitLighting,
false,
excludeFromTUAndAA,
compositionMask, // WW1MOD
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;
}
}
}
}