From a54dca423015da823894e3baca9105a1b4b40c3d Mon Sep 17 00:00:00 2001 From: Sebastien Lagarde Date: Mon, 15 Jun 2020 10:57:45 +0200 Subject: [PATCH 1/2] Fix depth offset and transparent motion vector for unlit transparent --- .../ShaderGraph/Templates/ShaderPass.template | 3 +- .../ShaderPass/ShaderPassForwardUnlit.hlsl | 87 ++++++++++++++++--- 2 files changed, 79 insertions(+), 11 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Editor/Material/ShaderGraph/Templates/ShaderPass.template b/com.unity.render-pipelines.high-definition/Editor/Material/ShaderGraph/Templates/ShaderPass.template index e26fe67edcc..5332a6def6b 100644 --- a/com.unity.render-pipelines.high-definition/Editor/Material/ShaderGraph/Templates/ShaderPass.template +++ b/com.unity.render-pipelines.high-definition/Editor/Material/ShaderGraph/Templates/ShaderPass.template @@ -59,6 +59,7 @@ Pass // Specific Material Define $include("ShaderPassDefine.template.hlsl") + // Caution: we can use the define SHADER_UNLIT onlit after the above Material include as it is the Unlit template who define it #ifndef DEBUG_DISPLAY // In case of opaque we don't want to perform the alpha test, it is done in depth prepass and we use depth equal for ztest (setup from UI) @@ -265,7 +266,6 @@ Pass void GetSurfaceAndBuiltinData(FragInputs fragInputs, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData RAY_TRACING_OPTIONAL_PARAMETERS) { - #ifndef SHADER_UNLIT // Don't dither if displaced tessellation (we're fading out the displacement instead to match the next LOD) #if !defined(SHADER_STAGE_RAY_TRACING) && !defined(_TESSELLATION_DISPLACEMENT) #ifdef LOD_FADE_CROSSFADE // enable dithering LOD transition if user select CrossFade transition in LOD group @@ -273,6 +273,7 @@ Pass #endif #endif + #ifndef SHADER_UNLIT #ifdef _DOUBLESIDED_ON float3 doubleSidedConstants = _DoubleSidedConstants.xyz; #else diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassForwardUnlit.hlsl b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassForwardUnlit.hlsl index 4ef55c8e9d2..dc08c24e91d 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassForwardUnlit.hlsl +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassForwardUnlit.hlsl @@ -2,6 +2,34 @@ #error SHADERPASS_is_not_correctly_define #endif +#ifdef _WRITE_TRANSPARENT_MOTION_VECTOR +#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/MotionVectorVertexShaderCommon.hlsl" + +PackedVaryingsType Vert(AttributesMesh inputMesh, AttributesPass inputPass) +{ + VaryingsType varyingsType; + varyingsType.vmesh = VertMesh(inputMesh); + return MotionVectorVS(varyingsType, inputMesh, inputPass); +} + +#ifdef TESSELLATION_ON + +PackedVaryingsToPS VertTesselation(VaryingsToDS input) +{ + VaryingsToPS output; + output.vmesh = VertMeshTesselation(input.vmesh); + MotionVectorPositionZBias(output); + + output.vpass.positionCS = input.vpass.positionCS; + output.vpass.previousPositionCS = input.vpass.previousPositionCS; + + return PackVaryingsToPS(output); +} + +#endif // TESSELLATION_ON + +#else // _WRITE_TRANSPARENT_MOTION_VECTOR + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/VertMesh.hlsl" PackedVaryingsType Vert(AttributesMesh inputMesh) @@ -20,17 +48,40 @@ PackedVaryingsToPS VertTesselation(VaryingsToDS input) return PackVaryingsToPS(output); } -#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/TessellationShare.hlsl" - #endif // TESSELLATION_ON -void Frag(PackedVaryingsToPS packedInput, - out float4 outResult : SV_Target0 +#endif // _WRITE_TRANSPARENT_MOTION_VECTOR + +#ifdef TESSELLATION_ON +#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/TessellationShare.hlsl" +#endif + #ifdef UNITY_VIRTUAL_TEXTURING - ,out float4 outVTFeedback : SV_Target1 +#define VT_BUFFER_TARGET SV_Target1 +#define EXTRA_BUFFER_TARGET SV_Target2 +#else +#define EXTRA_BUFFER_TARGET SV_Target1 #endif + +void Frag(PackedVaryingsToPS packedInput, + out float4 outColor : SV_Target0 + #ifdef UNITY_VIRTUAL_TEXTURING + ,out float4 outVTFeedback : VT_BUFFER_TARGET + #endif + #ifdef _WRITE_TRANSPARENT_MOTION_VECTOR + , out float4 outMotionVec : EXTRA_BUFFER_TARGET + #endif + #ifdef _DEPTHOFFSET_ON + , out float outputDepth : SV_Depth + #endif ) { +#ifdef _WRITE_TRANSPARENT_MOTION_VECTOR + // Init outMotionVector here to solve compiler warning (potentially unitialized variable) + // It is init to the value of forceNoMotion (with 2.0) + outMotionVec = float4(2.0, 0.0, 0.0, 0.0); +#endif + UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(packedInput); FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh); @@ -52,8 +103,8 @@ void Frag(PackedVaryingsToPS packedInput, BSDFData bsdfData = ConvertSurfaceDataToBSDFData(input.positionSS.xy, surfaceData); // Note: we must not access bsdfData in shader pass, but for unlit we make an exception and assume it should have a color field - float4 outColor = ApplyBlendMode(bsdfData.color + builtinData.emissiveColor * GetCurrentExposureMultiplier(), builtinData.opacity); - outColor = EvaluateAtmosphericScattering(posInput, V, outColor); + float4 outResult = ApplyBlendMode(bsdfData.color + builtinData.emissiveColor * GetCurrentExposureMultiplier(), builtinData.opacity); + outResult = EvaluateAtmosphericScattering(posInput, V, outResult); #ifdef DEBUG_DISPLAY // Same code in ShaderPassForward.shader @@ -86,19 +137,35 @@ void Frag(PackedVaryingsToPS packedInput, if (!needLinearToSRGB) result = SRGBToLinear(max(0, result)); - outColor = float4(result, 1.0); + outResult = float4(result, 1.0); } } if (_DebugFullScreenMode == FULLSCREENDEBUGMODE_TRANSPARENCY_OVERDRAW) { float4 result = _DebugTransparencyOverdrawWeight * float4(TRANSPARENCY_OVERDRAW_COST, TRANSPARENCY_OVERDRAW_COST, TRANSPARENCY_OVERDRAW_COST, TRANSPARENCY_OVERDRAW_A); - outColor = result; + outResult = result; } #endif - outResult = outColor; + outColor = outResult; + +#ifdef _WRITE_TRANSPARENT_MOTION_VECTOR + VaryingsPassToPS inputPass = UnpackVaryingsPassToPS(packedInput.vpass); + bool forceNoMotion = any(unity_MotionVectorsParams.yw == 0.0); + // outMotionVec is already initialize at the value of forceNoMotion (see above) + if (!forceNoMotion) + { + float2 motionVec = CalculateMotionVector(inputPass.positionCS, inputPass.previousPositionCS); + EncodeMotionVector(motionVec * 0.5, outMotionVec); + outMotionVec.zw = 1.0; + } +#endif + +#ifdef _DEPTHOFFSET_ON + outputDepth = posInput.deviceDepth; +#endif #ifdef UNITY_VIRTUAL_TEXTURING outVTFeedback = builtinData.vtPackedFeedback; From ea64ad1db7b30c4a71e9f76efb0cc9250103e124 Mon Sep 17 00:00:00 2001 From: Sebastien Lagarde Date: Mon, 15 Jun 2020 13:37:25 +0200 Subject: [PATCH 2/2] cleanup and fix the shadow pre/post alpha clip --- .../Material/Eye/ShaderGraph/EyeSubTarget.cs | 1 - .../Fabric/ShaderGraph/FabricSubTarget.cs | 1 - .../Hair/ShaderGraph/HairSubTarget.cs | 5 -- .../Lit/ShaderGraph/HDLitSubTarget.cs | 6 --- .../Material/ShaderGraph/SurfaceSubTarget.cs | 46 ++++++++++++------- .../StackLit/ShaderGraph/StackLitSubTarget.cs | 1 - .../Unlit/ShaderGraph/HDUnlitSubTarget.cs | 5 +- 7 files changed, 31 insertions(+), 34 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Editor/Material/Eye/ShaderGraph/EyeSubTarget.cs b/com.unity.render-pipelines.high-definition/Editor/Material/Eye/ShaderGraph/EyeSubTarget.cs index 5eb859d6cbf..ac2009b5c45 100644 --- a/com.unity.render-pipelines.high-definition/Editor/Material/Eye/ShaderGraph/EyeSubTarget.cs +++ b/com.unity.render-pipelines.high-definition/Editor/Material/Eye/ShaderGraph/EyeSubTarget.cs @@ -49,7 +49,6 @@ public override void GetFields(ref TargetFieldContext context) context.AddField(HDFields.Eye, eyeData.materialType == EyeData.MaterialType.Eye); context.AddField(HDFields.EyeCinematic, eyeData.materialType == EyeData.MaterialType.EyeCinematic); context.AddField(HDFields.SubsurfaceScattering, eyeData.subsurfaceScattering && systemData.surfaceType != SurfaceType.Transparent); - context.AddField(HDFields.DoAlphaTest, systemData.alphaTest && context.pass.validPixelBlocks.Contains(BlockFields.SurfaceDescription.AlphaClipThreshold)); } public override void GetActiveBlocks(ref TargetActiveBlockContext context) diff --git a/com.unity.render-pipelines.high-definition/Editor/Material/Fabric/ShaderGraph/FabricSubTarget.cs b/com.unity.render-pipelines.high-definition/Editor/Material/Fabric/ShaderGraph/FabricSubTarget.cs index ae8968613a9..c0633215b11 100644 --- a/com.unity.render-pipelines.high-definition/Editor/Material/Fabric/ShaderGraph/FabricSubTarget.cs +++ b/com.unity.render-pipelines.high-definition/Editor/Material/Fabric/ShaderGraph/FabricSubTarget.cs @@ -58,7 +58,6 @@ public override void GetFields(ref TargetFieldContext context) context.AddField(HDFields.Silk, fabricData.materialType == FabricData.MaterialType.Silk); context.AddField(HDFields.SubsurfaceScattering, fabricData.subsurfaceScattering && systemData.surfaceType != SurfaceType.Transparent); context.AddField(HDFields.Transmission, fabricData.transmission); - context.AddField(HDFields.DoAlphaTest, systemData.alphaTest && context.pass.validPixelBlocks.Contains(BlockFields.SurfaceDescription.AlphaClipThreshold)); context.AddField(HDFields.EnergyConservingSpecular, fabricData.energyConservingSpecular); } diff --git a/com.unity.render-pipelines.high-definition/Editor/Material/Hair/ShaderGraph/HairSubTarget.cs b/com.unity.render-pipelines.high-definition/Editor/Material/Hair/ShaderGraph/HairSubTarget.cs index d9e39a86599..243cce9f0a2 100644 --- a/com.unity.render-pipelines.high-definition/Editor/Material/Hair/ShaderGraph/HairSubTarget.cs +++ b/com.unity.render-pipelines.high-definition/Editor/Material/Hair/ShaderGraph/HairSubTarget.cs @@ -52,11 +52,6 @@ public override void GetFields(ref TargetFieldContext context) context.AddField(HDFields.UseLightFacingNormal, hairData.useLightFacingNormal); context.AddField(HDFields.Transmittance, descs.Contains(HDBlockFields.SurfaceDescription.Transmittance) && context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.Transmittance)); - // All the DoAlphaXXX field drive the generation of which code to use for alpha test in the template - // Do alpha test only if we aren't using the TestShadow one - context.AddField(HDFields.DoAlphaTest, systemData.alphaTest && (context.pass.validPixelBlocks.Contains(BlockFields.SurfaceDescription.AlphaClipThreshold) && - !(builtinData.alphaTestShadow && context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.AlphaClipThresholdShadow)))); - // Misc context.AddField(HDFields.SpecularAA, lightingData.specularAA && context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.SpecularAAThreshold) && diff --git a/com.unity.render-pipelines.high-definition/Editor/Material/Lit/ShaderGraph/HDLitSubTarget.cs b/com.unity.render-pipelines.high-definition/Editor/Material/Lit/ShaderGraph/HDLitSubTarget.cs index 41b7fd988d9..214dd359440 100644 --- a/com.unity.render-pipelines.high-definition/Editor/Material/Lit/ShaderGraph/HDLitSubTarget.cs +++ b/com.unity.render-pipelines.high-definition/Editor/Material/Lit/ShaderGraph/HDLitSubTarget.cs @@ -94,12 +94,6 @@ public override void GetFields(ref TargetFieldContext context) context.AddField(HDFields.RefractionSphere, hasRefraction && litData.refractionModel == ScreenSpaceRefraction.RefractionModel.Sphere); context.AddField(HDFields.RefractionThin, hasRefraction && litData.refractionModel == ScreenSpaceRefraction.RefractionModel.Thin); - // AlphaTest - // All the DoAlphaXXX field drive the generation of which code to use for alpha test in the template - // Do alpha test only if we aren't using the TestShadow one - context.AddField(HDFields.DoAlphaTest, systemData.alphaTest && (context.pass.validPixelBlocks.Contains(BlockFields.SurfaceDescription.AlphaClipThreshold) && - !(builtinData.alphaTestShadow && context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.AlphaClipThresholdShadow)))); - // Misc context.AddField(HDFields.EnergyConservingSpecular, litData.energyConservingSpecular); diff --git a/com.unity.render-pipelines.high-definition/Editor/Material/ShaderGraph/SurfaceSubTarget.cs b/com.unity.render-pipelines.high-definition/Editor/Material/ShaderGraph/SurfaceSubTarget.cs index 5177a046064..4ab715824d0 100644 --- a/com.unity.render-pipelines.high-definition/Editor/Material/ShaderGraph/SurfaceSubTarget.cs +++ b/com.unity.render-pipelines.high-definition/Editor/Material/ShaderGraph/SurfaceSubTarget.cs @@ -213,19 +213,34 @@ public override void GetFields(ref TargetFieldContext context) context.AddField(Fields.BlendAlpha, systemData.surfaceType != SurfaceType.Opaque && systemData.blendMode == BlendMode.Alpha); context.AddField(Fields.BlendPremultiply, systemData.surfaceType != SurfaceType.Opaque && systemData.blendMode == BlendMode.Premultiply); - // We always generate the keyword ALPHATEST_ON - context.AddField(Fields.AlphaTest, systemData.alphaTest - && (context.pass.validPixelBlocks.Contains(BlockFields.SurfaceDescription.AlphaClipThreshold) - || context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.AlphaClipThresholdShadow) - || context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.AlphaClipThresholdDepthPrepass) - || context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.AlphaClipThresholdDepthPostpass))); - // Double Sided - context.AddField(HDFields.DoubleSided, systemData.doubleSidedMode != DoubleSidedMode.Disabled); + context.AddField(HDFields.DoubleSided, systemData.doubleSidedMode != DoubleSidedMode.Disabled); + + // We always generate the keyword ALPHATEST_ON. All the variant of AlphaClip (shadow, pre/postpass) are only available if alpha test is on. + context.AddField(Fields.AlphaTest, systemData.alphaTest + && (context.pass.validPixelBlocks.Contains(BlockFields.SurfaceDescription.AlphaClipThreshold) + || context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.AlphaClipThresholdShadow) + || context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.AlphaClipThresholdDepthPrepass) + || context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.AlphaClipThresholdDepthPostpass))); + + // All the DoAlphaXXX field drive the generation of which code to use for alpha test in the template + // Regular alpha test is only done if artist haven't ask to use the specific alpha test shadow one + bool isShadowPass = context.pass.lightMode == "ShadowCaster"; + bool isTransparentDepthPrepass = context.pass.lightMode == "TransparentDepthPrepass"; + bool isTransparentDepthPostpass = context.pass.lightMode == "TransparentDepthPostpass"; + context.AddField(HDFields.DoAlphaTest, systemData.alphaTest && (context.pass.validPixelBlocks.Contains(BlockFields.SurfaceDescription.AlphaClipThreshold) && + !(isShadowPass && builtinData.alphaTestShadow && context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.AlphaClipThresholdShadow)) + )); + + // Shadow use the specific alpha test only if user have ask to override it + context.AddField(HDFields.DoAlphaTestShadow, systemData.alphaTest && builtinData.alphaTestShadow && isShadowPass && + context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.AlphaClipThresholdShadow)); + // Pre/post pass always use the specific alpha test provided for those pass + context.AddField(HDFields.DoAlphaTestPrepass, systemData.alphaTest && systemData.alphaTestDepthPrepass && isTransparentDepthPrepass && + context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.AlphaClipThresholdDepthPrepass)); + context.AddField(HDFields.DoAlphaTestPostpass, systemData.alphaTest && systemData.alphaTestDepthPostpass && isTransparentDepthPostpass && + context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.AlphaClipThresholdDepthPostpass)); - context.AddField(HDFields.DoAlphaTestPrepass, systemData.alphaTest && systemData.alphaTestDepthPrepass && context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.AlphaClipThresholdDepthPrepass)); - context.AddField(HDFields.DoAlphaTestPostpass, systemData.alphaTest && systemData.alphaTestDepthPostpass && context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.AlphaClipThresholdDepthPostpass)); - context.AddField(HDFields.DoAlphaTestShadow, systemData.alphaTest && builtinData.alphaTestShadow && context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.AlphaClipThresholdShadow)); context.AddField(HDFields.TransparentDepthPrePass, systemData.surfaceType != SurfaceType.Opaque && systemData.alphaTestDepthPrepass); context.AddField(HDFields.TransparentDepthPostPass, systemData.surfaceType != SurfaceType.Opaque && systemData.alphaTestDepthPostpass); @@ -269,14 +284,11 @@ public override void GetActiveBlocks(ref TargetActiveBlockContext context) // Alpha Test context.AddBlock(HDBlockFields.SurfaceDescription.AlphaClipThresholdDepthPrepass, - systemData.surfaceType == SurfaceType.Transparent && systemData.alphaTest && systemData.alphaTestDepthPrepass - && (context.pass != null && context.pass.Value.lightMode == "TransparentDepthPrepass")); + systemData.surfaceType == SurfaceType.Transparent && systemData.alphaTest && systemData.alphaTestDepthPrepass); context.AddBlock(HDBlockFields.SurfaceDescription.AlphaClipThresholdDepthPostpass, - systemData.surfaceType == SurfaceType.Transparent && systemData.alphaTest && systemData.alphaTestDepthPostpass - && (context.pass != null && context.pass.Value.lightMode == "TransparentDepthPostpass")); + systemData.surfaceType == SurfaceType.Transparent && systemData.alphaTest && systemData.alphaTestDepthPostpass); context.AddBlock(HDBlockFields.SurfaceDescription.AlphaClipThresholdShadow, - systemData.alphaTest && builtinData.alphaTestShadow - && (context.pass != null && context.pass.Value.lightMode == "ShadowCaster")); + systemData.alphaTest && builtinData.alphaTestShadow); // Misc context.AddBlock(HDBlockFields.SurfaceDescription.DepthOffset, builtinData.depthOffset); diff --git a/com.unity.render-pipelines.high-definition/Editor/Material/StackLit/ShaderGraph/StackLitSubTarget.cs b/com.unity.render-pipelines.high-definition/Editor/Material/StackLit/ShaderGraph/StackLitSubTarget.cs index 5e39cc0682f..d52d603a4cf 100644 --- a/com.unity.render-pipelines.high-definition/Editor/Material/StackLit/ShaderGraph/StackLitSubTarget.cs +++ b/com.unity.render-pipelines.high-definition/Editor/Material/StackLit/ShaderGraph/StackLitSubTarget.cs @@ -90,7 +90,6 @@ public override void GetFields(ref TargetFieldContext context) stackLitData.dualSpecularLobeParametrization == StackLit.DualSpecularLobeParametrization.HazyGloss); // Misc - context.AddField(HDFields.DoAlphaTest, systemData.alphaTest && context.pass.validPixelBlocks.Contains(BlockFields.SurfaceDescription.AlphaClipThreshold)); context.AddField(HDFields.EnergyConservingSpecular, stackLitData.energyConservingSpecular); context.AddField(HDFields.Tangent, descs.Contains(HDBlockFields.SurfaceDescription.Tangent) && context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.Tangent)); diff --git a/com.unity.render-pipelines.high-definition/Editor/Material/Unlit/ShaderGraph/HDUnlitSubTarget.cs b/com.unity.render-pipelines.high-definition/Editor/Material/Unlit/ShaderGraph/HDUnlitSubTarget.cs index 25c0d263ffc..951e9aecc4f 100644 --- a/com.unity.render-pipelines.high-definition/Editor/Material/Unlit/ShaderGraph/HDUnlitSubTarget.cs +++ b/com.unity.render-pipelines.high-definition/Editor/Material/Unlit/ShaderGraph/HDUnlitSubTarget.cs @@ -75,8 +75,7 @@ public override void GetFields(ref TargetFieldContext context) base.GetFields(ref context); // Unlit specific properties - context.AddField(HDFields.EnableShadowMatte, unlitData.enableShadowMatte); - context.AddField(HDFields.DoAlphaTest, systemData.alphaTest && context.pass.validPixelBlocks.Contains(BlockFields.SurfaceDescription.AlphaClipThreshold)); + context.AddField(HDFields.EnableShadowMatte, unlitData.enableShadowMatte); } public override void GetActiveBlocks(ref TargetActiveBlockContext context) @@ -84,7 +83,7 @@ public override void GetActiveBlocks(ref TargetActiveBlockContext context) base.GetActiveBlocks(ref context); // Unlit specific blocks - context.AddBlock(HDBlockFields.SurfaceDescription.ShadowTint, unlitData.enableShadowMatte); + context.AddBlock(HDBlockFields.SurfaceDescription.ShadowTint, unlitData.enableShadowMatte); } protected override void AddInspectorPropertyBlocks(SubTargetPropertiesGUI blockList)