Skip to content

Commit

Permalink
[2023.2][URP] Fix missing LOD CrossFade and AlphaClip support in the …
Browse files Browse the repository at this point in the history
…motion vector pass

This PR fixes: https://jira.unity3d.com/browse/UUM-25476

Primarily this PR:
- Adds missing `_ALPHATEST_ON` and `LOD_FADE_CROSSFADE` shader variant support to the URP object motion vector shaders (as the added variants are in a new pass, this does not multiply the existing "billions" of variants, and only adds a handful of them)
- Adds a  motion vector pass to each of the basic URP shader types instead of relying on `ObjectMotionVectors.shader` for all materials (doing this as Getting AlphaClip inputs is shader specific (texture/color alpha and sometimes a threshold)
- Adds a material upgrader to disable the newly added `MOTIONVECTORS` pass by adding it to the `disabledShaderPasses` list to avoid performance regressions (i.e. so MVs would not be rendered for static objects; the engine will still draw the pass if the renderer is moving due to skeletal animation and/or if its transform changes between frames - this is built-in behaviour)
- Upgrades the default materials located in URP to the new version

This PR also:
- Makes the object and camera motion vector arithmetic more conservative by avoiding `half` (I was seeing visual discrepancies in background camera motion vectors on Nintendo Switch - were getting rounded to 0)
- Renames the `ObjectMotionVectors.shader` to `ObjectMotionVectorFallback.shader` as it will no longer be used for all materials, it will only be used for user written HLSL shaders which don't provide their own motion vector pass and for our materials which aren't `Lit`, `Unlit`, `Complex Lit`, `Simple Lit`, `Baked Lit`, `ShaderGraph Lit`, or `ShaderGraph Unlit`
- Fixes an issue where `ComplexLit` wasn't ever being upgraded (as it didn't have entries in the `ShaderID` and `ShaderPathID` enums (in `Editor/ShaderUtils.cs` and `Runtime/ShaderUtils.cs`)). However, simply enabling upgrading seemed to in certain cases alter visuals for transparent premultiplied ComplexLit  materials (happened in our Foundation test project), so I also modified the  V5 to V6 upgrade logic so this wouldn't happen (very detailed explanation in the code comments)
  • Loading branch information
Dredhog authored and Evergreen committed Mar 3, 2023
1 parent 35696a5 commit 41845ec
Show file tree
Hide file tree
Showing 148 changed files with 69,528 additions and 409 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class MaterialPostprocessor : AssetPostprocessor
internal static List<string> s_ImportedAssetThatNeedSaving = new List<string>();
internal static bool s_NeedsSavingAssets = false;

internal static readonly Action<Material, ShaderID>[] k_Upgraders = { UpgradeV1, UpgradeV2, UpgradeV3, UpgradeV4, UpgradeV5, UpgradeV6, UpgradeV7 };
internal static readonly Action<Material, ShaderID>[] k_Upgraders = { UpgradeV1, UpgradeV2, UpgradeV3, UpgradeV4, UpgradeV5, UpgradeV6, UpgradeV7, UpgradeV8 };

static internal void SaveAssetsToDisk()
{
Expand Down Expand Up @@ -340,9 +340,26 @@ static void UpgradeV6(Material material, ShaderID shaderID)
var blendModePreserveSpecularPID = Shader.PropertyToID(Property.BlendModePreserveSpecular);
if (material.HasProperty(blendModePreserveSpecularPID))
{
// TL;DR; As Complex Lit was not being versioned before we want to only upgrade it in certain
// cases to not alter visuals
//
// To elaborate, this is needed for the following reasons:
// 1) Premultiplied used to mean something different before V6
// 2) If the update is applied twice it will change visuals
// 3) As Complex Lit was missing form the ShaderID enum it was never being upgraded, so its
// version is not a reliable indicator of which version of Premultiplied alpha the user
// had intended (e.g. the URP Foundation test project is currently at V7 but some
// Complex Lit materials are at V3)
// 5) To determine the intended version we can check which version the project is being upgraded
// from (as we can then know which version it was being actually used as). If the project is
// at version 6 or higher then we know that if the user had selected Premultiplied it is
// already working based on the new interpretation and should not be changed
bool skipChangingBlendMode = shaderID == ShaderID.ComplexLit &&
UniversalProjectSettings.materialVersionForUpgrade >= 6;

var blendModePID = Shader.PropertyToID(Property.BlendMode);
var blendMode = (BaseShaderGUI.BlendMode)material.GetFloat(blendModePID);
if (blendMode == BaseShaderGUI.BlendMode.Premultiply)
if (blendMode == BaseShaderGUI.BlendMode.Premultiply && !skipChangingBlendMode)
{
material.SetFloat(blendModePID, (float)BaseShaderGUI.BlendMode.Alpha);
material.SetFloat(blendModePreserveSpecularPID, 1.0f);
Expand Down Expand Up @@ -376,6 +393,23 @@ static void UpgradeV7(Material material, ShaderID shaderID)
material.SetFloat(alphaToMaskPropertyID, alphaToMask);
}
}

// We need to disable the passes with a { "LightMode" = "MotionVectors" } tag for URP shaders that have them,
// otherwise they'll be rendered for static objects (transform not moving and no skeletal animation) regressing MV perf.
//
// This is now needed as most URP material types have their own dedicated MV pass (this is so they work with
// Alpha-Clipping which needs per material data and not just generic vertex data like for the override shader).
//
// In Unity (both Built-in and SRP), the MV pass will be used even if disabled on frames where the object's
// transform changes or there's skeletal animation. But for URP disabling wasn't necessary before as the single
// object MV override shader was only used when needed (and there wasn't even anything to disable per material)
//
// N.B. the SetShaderPassEnabled API takes a tag value corresponding to the "LightMode" key and not a pass name
static void UpgradeV8(Material material, ShaderID shaderID)
{
if (HasMotionVectorLightModeTag(shaderID))
material.SetShaderPassEnabled(MotionVectorRenderPass.k_MotionVectorsLightModeTag, false);
}
}

// Upgraders v1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -768,6 +768,14 @@ internal static void UpdateMaterialSurfaceOptions(Material material, bool automa
CoreUtils.SetKeyword(material, ShaderKeywordStrings._RECEIVE_SHADOWS_OFF, material.GetFloat(Property.ReceiveShadows) == 0.0f);
}

internal static void UpdateMotionVectorKeywordsAndPass(Material material)
{
bool passShouldBeEnabled = !HasMotionVectorLightModeTag(GetShaderID(material.shader));
// Calling this always as we might be in a situation where the material's shader was just changed to one
// which doesn't have a pass with the { "LightMode" = "MotionVectors" } tag so we want to stop disabling
material.SetShaderPassEnabled(MotionVectorRenderPass.k_MotionVectorsLightModeTag, passShouldBeEnabled);
}

// this function is shared between ShaderGraph and hand-written GUIs
internal static void UpdateMaterialRenderQueueControl(Material material)
{
Expand Down Expand Up @@ -854,6 +862,8 @@ public static void SetMaterialKeywords(Material material, Action<Material> shadi
if (material.HasProperty("_BumpMap"))
CoreUtils.SetKeyword(material, ShaderKeywordStrings._NORMALMAP, material.GetTexture("_BumpMap"));

BaseShaderGUI.UpdateMotionVectorKeywordsAndPass(material);

// Shader specific keyword functions
shadingModelFunc?.Invoke(material);
shaderFunc?.Invoke(material);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public static void UpdateMaterial(Material material, MaterialUpdateType updateTy
bool automaticRenderQueue = GetAutomaticQueueControlSetting(material);
BaseShaderGUI.UpdateMaterialSurfaceOptions(material, automaticRenderQueue);
LitGUI.SetupSpecularWorkflowKeyword(material, out bool isSpecularWorkflow);
BaseShaderGUI.UpdateMotionVectorKeywordsAndPass(material);
}

public override void ValidateMaterial(Material material)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public static void UpdateMaterial(Material material, MaterialUpdateType updateTy
{
bool automaticRenderQueue = GetAutomaticQueueControlSetting(material);
BaseShaderGUI.UpdateMaterialSurfaceOptions(material, automaticRenderQueue);
BaseShaderGUI.UpdateMotionVectorKeywordsAndPass(material);
}

public override void ValidateMaterial(Material material)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#ifndef SG_MOTION_VECTORS_PASS_INCLUDED
#define SG_MOTION_VECTORS_PASS_INCLUDED

#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/MotionVectorsCommon.hlsl"

struct MotionVectorPassAttributes
{
float3 previousPositionOS : TEXCOORD4; // Contains previous frame local vertex position (for skinned meshes)
};

// Note: these will have z == 0.0f in the pixel shader to save on bandwidth
struct MotionVectorPassVaryings
{
float4 positionCSNoJitter;
float4 previousPositionCSNoJitter;
};

struct PackedMotionVectorPassVaryings
{
float3 positionCSNoJitter : CLIP_POSITION_NO_JITTER;
float3 previousPositionCSNoJitter : PREVIOUS_CLIP_POSITION_NO_JITTER;
};

PackedMotionVectorPassVaryings PackMotionVectorVaryings(MotionVectorPassVaryings regularVaryings)
{
PackedMotionVectorPassVaryings packedVaryings;
packedVaryings.positionCSNoJitter = regularVaryings.positionCSNoJitter.xyw;
packedVaryings.previousPositionCSNoJitter = regularVaryings.previousPositionCSNoJitter.xyw;
return packedVaryings;
}

MotionVectorPassVaryings UnpackMotionVectorVaryings(PackedMotionVectorPassVaryings packedVaryings)
{
MotionVectorPassVaryings regularVaryings;
regularVaryings.positionCSNoJitter = float4(packedVaryings.positionCSNoJitter.xy, 0, packedVaryings.positionCSNoJitter.z);
regularVaryings.previousPositionCSNoJitter = float4(packedVaryings.previousPositionCSNoJitter.xy, 0, packedVaryings.previousPositionCSNoJitter.z);
return regularVaryings;
}

// -------------------------------------
// Vertex
void vert(
Attributes input,
MotionVectorPassAttributes passInput,
out PackedMotionVectorPassVaryings packedMvOutput,
out PackedVaryings packedOutput)
{
Varyings output = (Varyings)0;
MotionVectorPassVaryings mvOutput = (MotionVectorPassVaryings)0;
output = BuildVaryings(input);
ApplyMotionVectorZBias(output.positionCS);
packedOutput = PackVaryings(output);

const bool forceNoMotion = unity_MotionVectorsParams.y == 0.0;
if(!forceNoMotion)
{
const bool hasDeformation = unity_MotionVectorsParams.x == 1; // Mesh has skinned deformation
float3 previousPositionOS = hasDeformation ? passInput.previousPositionOS : input.positionOS;

mvOutput.positionCSNoJitter = mul(_NonJitteredViewProjMatrix, mul(UNITY_MATRIX_M, float4(input.positionOS, 1.0f)));
mvOutput.previousPositionCSNoJitter = mul(_PrevViewProjMatrix, mul(UNITY_PREV_MATRIX_M, float4(previousPositionOS, 1.0f)));
}

packedMvOutput = PackMotionVectorVaryings(mvOutput);
}

// -------------------------------------
// Fragment
float4 frag(
// Note: packedMvInput needs to be before packedInput as otherwise we get the following error in the speed tree 8 SG:
// "Non system-generated input signature parameter () cannot appear after a system generated value"
PackedMotionVectorPassVaryings packedMvInput,
PackedVaryings packedInput) : SV_Target
{
Varyings input = UnpackVaryings(packedInput);
MotionVectorPassVaryings mvInput = UnpackMotionVectorVaryings(packedMvInput);
UNITY_SETUP_INSTANCE_ID(input);
SurfaceDescription surfaceDescription = BuildSurfaceDescription(input);

#if _ALPHATEST_ON
clip(surfaceDescription.Alpha - surfaceDescription.AlphaClipThreshold);
#endif

#if defined(LOD_FADE_CROSSFADE) && USE_UNITY_CROSSFADE
LODFadeCrossFade(input.positionCS);
#endif

return float4(CalcNdcMotionVectorFromCsPositions(mvInput.positionCSNoJitter, mvInput.previousPositionCSNoJitter), 0, 0);
}
#endif

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@
#define SHADERPASS_DECAL_GBUFFER_PROJECTOR (19)
#define SHADERPASS_DECAL_GBUFFER_MESH (20)
#define SHADERPASS_DEPTHNORMALS (21)
#define SHADERPASS_MOTION_VECTORS (22)
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ Varyings BuildVaryings(Attributes input)

// Assign modified vertex attributes
input.positionOS = vertexDescription.Position;
#if defined(VARYINGS_NEED_NORMAL_WS)
#if defined(ATTRIBUTES_NEED_NORMAL) && defined(FEATURES_GRAPH_VERTEX_NORMAL_OUTPUT)
input.normalOS = vertexDescription.Normal;
#endif //FEATURES_GRAPH_NORMAL
#if defined(VARYINGS_NEED_TANGENT_WS)
#if defined(ATTRIBUTES_NEED_TANGENT) && defined(FEATURES_GRAPH_VERTEX_TANGENT_OUTPUT)
input.tangentOS.xyz = vertexDescription.Tangent.xyz;
#endif //FEATURES GRAPH TANGENT
#endif //FEATURES_GRAPH_VERTEX
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,8 @@ public static SubShaderDescriptor LitSubShader(UniversalTarget target, WorkflowM
if (target.castShadows || target.allowMaterialOverride)
result.passes.Add(PassVariant(CorePasses.ShadowCaster(target), CorePragmas.Instanced));

result.passes.Add(PassVariant(CorePasses.MotionVectors(target), CorePragmas.MotionVectors));

if (target.mayWriteDepth)
result.passes.Add(PassVariant(CorePasses.DepthOnly(target), CorePragmas.Instanced));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1057,6 +1057,46 @@ public static PassDescriptor ShadowCaster(UniversalTarget target)
return result;
}

public static PassDescriptor MotionVectors(UniversalTarget target)
{
var result = new PassDescriptor()
{
// Definition
displayName = "MotionVectors",
referenceName = "SHADERPASS_MOTION_VECTORS",
lightMode = "MotionVectors",
useInPreview = false,

// Template
passTemplatePath = UniversalTarget.kUberTemplatePath,
sharedTemplateDirectories = UniversalTarget.kSharedTemplateDirectories,

// Port Mask
validVertexBlocks = CoreBlockMasks.MotionVectorVertex,
validPixelBlocks = CoreBlockMasks.FragmentAlphaOnly,

// Fields
structs = CoreStructCollections.Default,
requiredFields = new FieldCollection(),
fieldDependencies = CoreFieldDependencies.Default,

// Conditional State
renderStates = CoreRenderStates.MotionVector(target),
pragmas = CorePragmas.MotionVectors,
defines = new DefineCollection(),
keywords = new KeywordCollection(),
includes = CoreIncludes.MotionVectors,

// Custom Interpolator Support
customInterpolators = CoreCustomInterpDescriptors.Common
};

AddAlphaClipControlToPass(ref result, target);
AddLODCrossFadeControlToPass(ref result, target);

return result;
}

public static PassDescriptor SceneSelection(UniversalTarget target)
{
var result = new PassDescriptor()
Expand Down Expand Up @@ -1214,6 +1254,11 @@ public static PassDescriptor _2DScenePicking(UniversalTarget target)
#region PortMasks
class CoreBlockMasks
{
public static readonly BlockFieldDescriptor[] MotionVectorVertex = new BlockFieldDescriptor[]
{
BlockFields.VertexDescription.Position,
};

public static readonly BlockFieldDescriptor[] Vertex = new BlockFieldDescriptor[]
{
BlockFields.VertexDescription.Position,
Expand Down Expand Up @@ -1406,6 +1451,18 @@ public static RenderStateDescriptor UberSwitchedCullRenderState(UniversalTarget
return RenderState.Cull(RenderFaceToCull(target.renderFace));
}

public static RenderStateCollection MotionVector(UniversalTarget target)
{
var result = new RenderStateCollection
{
{ RenderState.ZTest(ZTest.LEqual) },
{ RenderState.ZWrite(ZWrite.On) },
{ UberSwitchedCullRenderState(target) },
{ RenderState.ColorMask("ColorMask RG") },
};
return result;
}

// used by lit/unlit targets
public static RenderStateCollection ShadowCaster(UniversalTarget target)
{
Expand Down Expand Up @@ -1487,6 +1544,14 @@ static class CorePragmas
{ Pragma.Fragment("frag") },
};

public static readonly PragmaCollection MotionVectors = new PragmaCollection
{
{ Pragma.Target(ShaderModel.Target35) },
{ Pragma.MultiCompileInstancing },
{ Pragma.Vertex("vert") },
{ Pragma.Fragment("frag") },
};

public static readonly PragmaCollection Forward = new PragmaCollection
{
{ Pragma.Target(ShaderModel.Target20) },
Expand Down Expand Up @@ -1532,6 +1597,7 @@ static class CoreIncludes
const string kDepthOnlyPass = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/DepthOnlyPass.hlsl";
const string kDepthNormalsOnlyPass = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/DepthNormalsOnlyPass.hlsl";
const string kShadowCasterPass = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/ShadowCasterPass.hlsl";
const string kMotionVectorPass = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/MotionVectorPass.hlsl";
const string kTextureStack = "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl";
const string kDBuffer = "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DBuffer.hlsl";
const string kSelectionPickingPass = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/SelectionPickingPass.hlsl";
Expand Down Expand Up @@ -1603,6 +1669,19 @@ static class CoreIncludes
{ kDepthNormalsOnlyPass, IncludeLocation.Postgraph },
};

public static readonly IncludeCollection MotionVectors = new IncludeCollection
{
// Pre-graph
{ DOTSPregraph },
{ WriteRenderLayersPregraph },
{ CorePregraph },
{ ShaderGraphPregraph },

//Post-graph
{ CorePostgraph },
{ kMotionVectorPass, IncludeLocation.Postgraph },
};

public static readonly IncludeCollection ShadowCaster = new IncludeCollection
{
// Pre-graph
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ public static SubShaderDescriptor Unlit(UniversalTarget target, string renderTyp
if (target.mayWriteDepth)
result.passes.Add(PassVariant(CorePasses.DepthOnly(target), CorePragmas.Instanced));

result.passes.Add(PassVariant(CorePasses.MotionVectors(target), CorePragmas.MotionVectors));

result.passes.Add(PassVariant(UnlitPasses.DepthNormalOnly(target), CorePragmas.Instanced));

if (target.castShadows || target.allowMaterialOverride)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ $Attributes.uv2: #define ATTRIBUTES_NEED_TEXCOORD2
$Attributes.uv3: #define ATTRIBUTES_NEED_TEXCOORD3
$Attributes.color: #define ATTRIBUTES_NEED_COLOR
$Attributes.vertexID: #define ATTRIBUTES_NEED_VERTEXID
$VertexDescription.Normal: #define FEATURES_GRAPH_VERTEX_NORMAL_OUTPUT
$VertexDescription.Tangent: #define FEATURES_GRAPH_VERTEX_TANGENT_OUTPUT
$Varyings.positionWS: #define VARYINGS_NEED_POSITION_WS
$Varyings.normalWS: #define VARYINGS_NEED_NORMAL_WS
$Varyings.tangentWS: #define VARYINGS_NEED_TANGENT_WS
Expand Down
Loading

0 comments on commit 41845ec

Please sign in to comment.