From 975b5bbd324c98ef3a9cd9c0f4f1cad8dbc84099 Mon Sep 17 00:00:00 2001 From: Till Davin Date: Thu, 20 Jun 2024 21:47:35 +0200 Subject: [PATCH] feat(hdrp): add sample Lit shader (#37) feat: lower shader target level to 4.5 fix(urp): don't setup urp buffers if screen properties are not yet present fix: prevent asset import errors by adding appropriate shader package requirements and fallbacks refactor: merge render shaders into a single shader asset --- HDRP/Runtime/OitRenderPass.cs | 2 +- HDRP/Shaders.meta | 8 + HDRP/Shaders/OitLitHDRP.shader | 11974 ++++++++++++++++ .../Shaders/OitLitHDRP.shader.meta | 2 +- HDRP/Shaders/OitShaderPassForwardHDRP.hlsl | 267 + .../OitShaderPassForwardHDRP.hlsl.meta | 7 + .../Runtime/OitPostProcess.cs | 2 +- PostProcessingStackV2/Shaders.meta | 8 + .../Shaders}/OitStandard.shader | 13 +- .../Shaders}/OitStandard.shader.meta | 0 .../Shaders}/OitStandardCoreForward.cginc | 4 +- .../OitStandardCoreForward.cginc.meta | 0 README.md | 8 +- .../HDRP Demo/Materials/BlueTransparent.mat | 245 +- .../HDRP Demo/Materials/GreenTransparent.mat | 245 +- .../HDRP Demo/Materials/RedTransparent.mat | 245 +- Samples~/HDRP Demo/Scenes/HDRP Demo.unity | 108 +- Shaders/LinkedListCreation.hlsl | 28 +- Shaders/LinkedListRendering.hlsl | 34 +- Shaders/LinkedListStruct.hlsl | 11 + ...s.hlsl.meta => LinkedListStruct.hlsl.meta} | 0 Shaders/OitUnlit.shader | 9 +- Shaders/OitUtils.hlsl | 48 - Shaders/Resources/OitRender.shader | 136 + ...HDRP.shader.meta => OitRender.shader.meta} | 0 Shaders/Resources/OitRenderHDRP.shader | 46 - Shaders/Resources/OitRenderPPv2.shader | 55 - Shaders/Resources/OitRenderPPv2.shader.meta | 3 - Shaders/Resources/OitRenderURP.shader | 42 - Shared/OitLinkedList.cs | 6 +- URP/Runtime/OitPass.cs | 2 +- URP/Shaders/OitLitURP.shader | 18 +- 32 files changed, 13293 insertions(+), 283 deletions(-) create mode 100644 HDRP/Shaders.meta create mode 100644 HDRP/Shaders/OitLitHDRP.shader rename Shaders/Resources/OitRenderURP.shader.meta => HDRP/Shaders/OitLitHDRP.shader.meta (80%) create mode 100644 HDRP/Shaders/OitShaderPassForwardHDRP.hlsl create mode 100644 HDRP/Shaders/OitShaderPassForwardHDRP.hlsl.meta create mode 100644 PostProcessingStackV2/Shaders.meta rename {Shaders => PostProcessingStackV2/Shaders}/OitStandard.shader (96%) rename {Shaders => PostProcessingStackV2/Shaders}/OitStandard.shader.meta (100%) rename {Shaders => PostProcessingStackV2/Shaders}/OitStandardCoreForward.cginc (90%) rename {Shaders => PostProcessingStackV2/Shaders}/OitStandardCoreForward.cginc.meta (100%) create mode 100644 Shaders/LinkedListStruct.hlsl rename Shaders/{OitUtils.hlsl.meta => LinkedListStruct.hlsl.meta} (100%) delete mode 100644 Shaders/OitUtils.hlsl create mode 100644 Shaders/Resources/OitRender.shader rename Shaders/Resources/{OitRenderHDRP.shader.meta => OitRender.shader.meta} (100%) delete mode 100644 Shaders/Resources/OitRenderHDRP.shader delete mode 100644 Shaders/Resources/OitRenderPPv2.shader delete mode 100644 Shaders/Resources/OitRenderPPv2.shader.meta delete mode 100644 Shaders/Resources/OitRenderURP.shader diff --git a/HDRP/Runtime/OitRenderPass.cs b/HDRP/Runtime/OitRenderPass.cs index e40806c..5d57e8b 100644 --- a/HDRP/Runtime/OitRenderPass.cs +++ b/HDRP/Runtime/OitRenderPass.cs @@ -12,7 +12,7 @@ class OitRenderPass : CustomPass protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd) { - orderIndependentTransparency ??= new OitLinkedList("OitRenderHDRP"); + orderIndependentTransparency ??= new OitLinkedList("OitRender"); } protected override void Execute(CustomPassContext ctx) diff --git a/HDRP/Shaders.meta b/HDRP/Shaders.meta new file mode 100644 index 0000000..15178f5 --- /dev/null +++ b/HDRP/Shaders.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 496d6e4ab9cf9414ea1af20872aec1db +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/HDRP/Shaders/OitLitHDRP.shader b/HDRP/Shaders/OitLitHDRP.shader new file mode 100644 index 0000000..542269a --- /dev/null +++ b/HDRP/Shaders/OitLitHDRP.shader @@ -0,0 +1,11974 @@ +Shader "OrderIndependentTransparency/HDRP/Lit" +{ + Properties + { + _Color("Color", Color) = (0, 0, 0, 0) + [HideInInspector]_EmissionColor("Color", Color) = (1, 1, 1, 1) + [HideInInspector]_RenderQueueType("Float", Float) = 4 + [HideInInspector][ToggleUI]_AddPrecomputedVelocity("Boolean", Float) = 0 + [HideInInspector][ToggleUI]_DepthOffsetEnable("Boolean", Float) = 0 + [HideInInspector][ToggleUI]_ConservativeDepthOffsetEnable("Boolean", Float) = 0 + [HideInInspector][ToggleUI]_TransparentWritingMotionVec("Boolean", Float) = 0 + [HideInInspector][ToggleUI]_AlphaCutoffEnable("Boolean", Float) = 0 + [HideInInspector]_TransparentSortPriority("_TransparentSortPriority", Float) = 0 + [HideInInspector][ToggleUI]_UseShadowThreshold("Boolean", Float) = 0 + [HideInInspector][ToggleUI]_DoubleSidedEnable("Boolean", Float) = 0 + [HideInInspector][Enum(Flip, 0, Mirror, 1, None, 2)]_DoubleSidedNormalMode("Float", Float) = 2 + [HideInInspector]_DoubleSidedConstants("Vector4", Vector) = (1, 1, -1, 0) + [HideInInspector][Enum(Auto, 0, On, 1, Off, 2)]_DoubleSidedGIMode("Float", Float) = 0 + [HideInInspector][ToggleUI]_TransparentDepthPrepassEnable("Boolean", Float) = 0 + [HideInInspector][ToggleUI]_TransparentDepthPostpassEnable("Boolean", Float) = 0 + [HideInInspector]_SurfaceType("Float", Float) = 1 + [HideInInspector]_BlendMode("Float", Float) = 0 + [HideInInspector]_SrcBlend("Float", Float) = 1 + [HideInInspector]_DstBlend("Float", Float) = 0 + [HideInInspector]_AlphaSrcBlend("Float", Float) = 1 + [HideInInspector]_AlphaDstBlend("Float", Float) = 0 + [HideInInspector][ToggleUI]_ZWrite("Boolean", Float) = 0 + [HideInInspector][ToggleUI]_TransparentZWrite("Boolean", Float) = 0 + [HideInInspector]_CullMode("Float", Float) = 2 + [HideInInspector][ToggleUI]_EnableFogOnTransparent("Boolean", Float) = 1 + [HideInInspector]_CullModeForward("Float", Float) = 2 + [HideInInspector][Enum(Front, 1, Back, 2)]_TransparentCullMode("Float", Float) = 2 + [HideInInspector][Enum(UnityEditor.Rendering.HighDefinition.OpaqueCullMode)]_OpaqueCullMode("Float", Float) = 2 + [HideInInspector]_ZTestDepthEqualForOpaque("Float", Int) = 4 + [HideInInspector][Enum(UnityEngine.Rendering.CompareFunction)]_ZTestTransparent("Float", Float) = 4 + [HideInInspector][ToggleUI]_TransparentBackfaceEnable("Boolean", Float) = 0 + [HideInInspector][ToggleUI]_RequireSplitLighting("Boolean", Float) = 0 + [HideInInspector][ToggleUI]_ReceivesSSR("Boolean", Float) = 1 + [HideInInspector][ToggleUI]_ReceivesSSRTransparent("Boolean", Float) = 0 + [HideInInspector][ToggleUI]_EnableBlendModePreserveSpecularLighting("Boolean", Float) = 1 + [HideInInspector][ToggleUI]_SupportDecals("Boolean", Float) = 1 + [HideInInspector]_StencilRef("Float", Int) = 0 + [HideInInspector]_StencilWriteMask("Float", Int) = 6 + [HideInInspector]_StencilRefDepth("Float", Int) = 0 + [HideInInspector]_StencilWriteMaskDepth("Float", Int) = 9 + [HideInInspector]_StencilRefMV("Float", Int) = 32 + [HideInInspector]_StencilWriteMaskMV("Float", Int) = 41 + [HideInInspector]_StencilRefDistortionVec("Float", Int) = 4 + [HideInInspector]_StencilWriteMaskDistortionVec("Float", Int) = 4 + [HideInInspector]_StencilWriteMaskGBuffer("Float", Int) = 15 + [HideInInspector]_StencilRefGBuffer("Float", Int) = 2 + [HideInInspector]_ZTestGBuffer("Float", Int) = 4 + [HideInInspector][ToggleUI]_RayTracing("Boolean", Float) = 0 + [HideInInspector][Enum(None, 0, Planar, 1, Sphere, 2, Thin, 3)]_RefractionModel("Float", Float) = 0 + [HideInInspector][NoScaleOffset]unity_Lightmaps("unity_Lightmaps", 2DArray) = "" {} + [HideInInspector][NoScaleOffset]unity_LightmapsInd("unity_LightmapsInd", 2DArray) = "" {} + [HideInInspector][NoScaleOffset]unity_ShadowMasks("unity_ShadowMasks", 2DArray) = "" {} + } + SubShader + { + PackageRequirements { + "org.happy-turtle.order-independent-transparency" + "com.unity.render-pipelines.high-definition" + } + + Tags + { + "RenderPipeline"="HDRenderPipeline" + "RenderType"="HDLitShader" + "Queue"="Transparent+0" + "DisableBatching"="False" + "ShaderGraphShader"="true" + "ShaderGraphTargetId"="HDLitSubTarget" + } + Pass + { + Name "ShadowCaster" + Tags + { + "LightMode" = "ShadowCaster" + } + + // Render State + Cull [_CullMode] + ZWrite On + ColorMask 0 + ZClip [_ZClip] + + // Debug + // + + // -------------------------------------------------- + // Pass + + HLSLPROGRAM + + // Pragmas + #pragma multi_compile _ DOTS_INSTANCING_ON + #pragma instancing_options renderinglayer + #pragma target 4.5 + #pragma vertex Vert + #pragma fragment Frag + #pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch + #pragma multi_compile_instancing + + // Keywords + #pragma shader_feature _ _SURFACE_TYPE_TRANSPARENT + #pragma shader_feature_local _ _DOUBLESIDED_ON + #pragma shader_feature_local _ _ADD_PRECOMPUTED_VELOCITY + #pragma shader_feature_local _ _TRANSPARENT_WRITES_MOTION_VEC + #pragma shader_feature_local_fragment _ _ENABLE_FOG_ON_TRANSPARENT + #pragma shader_feature_local_fragment _ _DISABLE_DECALS + #pragma shader_feature_local_raytracing _ _DISABLE_DECALS + #pragma shader_feature_local_fragment _ _DISABLE_SSR + #pragma shader_feature_local_raytracing _ _DISABLE_SSR + #pragma shader_feature_local_fragment _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local_raytracing _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local _ _REFRACTION_PLANE _REFRACTION_SPHERE _REFRACTION_THIN + // GraphKeywords: + + // For custom interpolators to inject a substruct definition before FragInputs definition, + // allowing for FragInputs to capture CI's intended for ShaderGraph's SDI. + struct CustomInterpolators + { + }; + #define USE_CUSTOMINTERP_SUBSTRUCT + + + + // TODO: Merge FragInputsVFX substruct with CustomInterpolators. + #ifdef HAVE_VFX_MODIFICATION + struct FragInputsVFX + { + /* WARNING: $splice Could not find named fragment 'FragInputsVFX' */ + }; + #endif + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl" // Required by Tessellation.hlsl + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Tessellation.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Texture.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl" // Required to be include before we include properties as it define DECLARE_STACK_CB + // Always include Shader Graph version + // Always include last to avoid double macros + #include "Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl" // Need to be here for Gradient struct definition + + // -------------------------------------------------- + // Defines + + // Attribute + #define ATTRIBUTES_NEED_NORMAL + #define ATTRIBUTES_NEED_TANGENT + + #define HAVE_MESH_MODIFICATION + + //Strip down the FragInputs.hlsl (on graphics), so we can only optimize the interpolators we use. + //if by accident something requests contents of FragInputs.hlsl, it will be caught as a compiler error + //Frag inputs stripping is only enabled when FRAG_INPUTS_ENABLE_STRIPPING is set + #if !defined(SHADER_STAGE_RAY_TRACING) && SHADERPASS != SHADERPASS_RAYTRACING_GBUFFER && SHADERPASS != SHADERPASS_FULL_SCREEN_DEBUG + #define FRAG_INPUTS_ENABLE_STRIPPING + #endif + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl" + + + + #define SHADERPASS SHADERPASS_SHADOWS + + + // Following two define are a workaround introduce in 10.1.x for RaytracingQualityNode + // The ShaderGraph don't support correctly migration of this node as it serialize all the node data + // in the json file making it impossible to uprgrade. Until we get a fix, we do a workaround here + // to still allow us to rename the field and keyword of this node without breaking existing code. + #ifdef RAYTRACING_SHADER_GRAPH_DEFAULT + #define RAYTRACING_SHADER_GRAPH_HIGH + #endif + + #ifdef RAYTRACING_SHADER_GRAPH_RAYTRACED + #define RAYTRACING_SHADER_GRAPH_LOW + #endif + // end + + #ifndef SHADER_UNLIT + // We need isFrontFace when using double sided - it is not required for unlit as in case of unlit double sided only drive the cullmode + // VARYINGS_NEED_CULLFACE can be define by VaryingsMeshToPS.FaceSign input if a IsFrontFace Node is included in the shader graph. + #if defined(_DOUBLESIDED_ON) && !defined(VARYINGS_NEED_CULLFACE) + #define VARYINGS_NEED_CULLFACE + #endif + #endif + + // Specific Material Define + #define _SPECULAR_OCCLUSION_FROM_AO 1 + #define _ENERGY_CONSERVING_SPECULAR 1 + + // If we use subsurface scattering, enable output split lighting (for forward pass) + #if defined(_MATERIAL_FEATURE_SUBSURFACE_SCATTERING) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define OUTPUT_SPLIT_LIGHTING + #endif + + // This shader support recursive rendering for raytracing + #define HAVE_RECURSIVE_RENDERING + + // In Path Tracing, For all single-sided, refractive materials, we want to force a thin refraction model + #if (SHADERPASS == SHADERPASS_PATH_TRACING) && !defined(_DOUBLESIDED_ON) && (defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE)) + #undef _REFRACTION_PLANE + #undef _REFRACTION_SPHERE + #define _REFRACTION_THIN + #endif + // Caution: we can use the define SHADER_UNLIT onlit after the above Material include as it is the Unlit template who define it + + // To handle SSR on transparent correctly with a possibility to enable/disable it per framesettings + // we should have a code like this: + // if !defined(_DISABLE_SSR_TRANSPARENT) + // pragma multi_compile _ WRITE_NORMAL_BUFFER + // endif + // i.e we enable the multicompile only if we can receive SSR or not, and then C# code drive + // it based on if SSR transparent in frame settings and not (and stripper can strip it). + // this is currently not possible with our current preprocessor as _DISABLE_SSR_TRANSPARENT is a keyword not a define + // so instead we used this and chose to pay the extra cost of normal write even if SSR transaprent is disabled. + // Ideally the shader graph generator should handle it but condition below can't be handle correctly for now. + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + #if !defined(_DISABLE_SSR_TRANSPARENT) && !defined(SHADER_UNLIT) + #define WRITE_NORMAL_BUFFER + #endif + #endif + + #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) + // Don't do it with debug display mode as it is possible there is no depth prepass in this case + #if !defined(_SURFACE_TYPE_TRANSPARENT) + #if SHADERPASS == SHADERPASS_FORWARD + #define SHADERPASS_FORWARD_BYPASS_ALPHA_TEST + #elif SHADERPASS == SHADERPASS_GBUFFER + #define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST + #endif + #endif + #endif + + // Define _DEFERRED_CAPABLE_MATERIAL for shader capable to run in deferred pass + #if defined(SHADER_LIT) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define _DEFERRED_CAPABLE_MATERIAL + #endif + + // Translate transparent motion vector define + #if defined(_TRANSPARENT_WRITES_MOTION_VEC) && defined(_SURFACE_TYPE_TRANSPARENT) + #define _WRITE_TRANSPARENT_MOTION_VECTOR + #endif + + // -- Graph Properties + CBUFFER_START(UnityPerMaterial) + float4 _Color; + float4 _EmissionColor; + float _UseShadowThreshold; + float4 _DoubleSidedConstants; + float _BlendMode; + float _EnableBlendModePreserveSpecularLighting; + float _RayTracing; + float _RefractionModel; + CBUFFER_END + + + // Object and Global properties + + // -- Property used by ScenePickingPass + #ifdef SCENEPICKINGPASS + float4 _SelectionID; + #endif + + // -- Properties used by SceneSelectionPass + #ifdef SCENESELECTIONPASS + int _ObjectId; + int _PassValue; + #endif + + // Includes + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugDisplay.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/NormalSurfaceGradient.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/Lit.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/BuiltinUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/MaterialUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Decal/DecalUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitDecalData.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderGraphFunctions.hlsl" + // GraphIncludes: + + // -------------------------------------------------- + // Structs and Packing + + struct AttributesMesh + { + float3 positionOS : POSITION; + float3 normalOS : NORMAL; + float4 tangentOS : TANGENT; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : INSTANCEID_SEMANTIC; + #endif + }; + struct VaryingsMeshToPS + { + SV_POSITION_QUALIFIERS float4 positionCS : SV_POSITION; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : CUSTOM_INSTANCE_ID; + #endif + }; + struct VertexDescriptionInputs + { + float3 ObjectSpaceNormal; + float3 ObjectSpaceTangent; + float3 ObjectSpacePosition; + }; + struct SurfaceDescriptionInputs + { + }; + struct PackedVaryingsMeshToPS + { + SV_POSITION_QUALIFIERS float4 positionCS : SV_POSITION; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : CUSTOM_INSTANCE_ID; + #endif + }; + + PackedVaryingsMeshToPS PackVaryingsMeshToPS (VaryingsMeshToPS input) + { + PackedVaryingsMeshToPS output; + ZERO_INITIALIZE(PackedVaryingsMeshToPS, output); + output.positionCS = input.positionCS; + #if UNITY_ANY_INSTANCING_ENABLED + output.instanceID = input.instanceID; + #endif + return output; + } + + VaryingsMeshToPS UnpackVaryingsMeshToPS (PackedVaryingsMeshToPS input) + { + VaryingsMeshToPS output; + output.positionCS = input.positionCS; + #if UNITY_ANY_INSTANCING_ENABLED + output.instanceID = input.instanceID; + #endif + return output; + } + + + // -------------------------------------------------- + // Graph + + + // Graph Functions + // GraphFunctions: + + // Graph Vertex + struct VertexDescription + { + float3 Position; + float3 Normal; + float3 Tangent; + }; + + VertexDescription VertexDescriptionFunction(VertexDescriptionInputs IN) + { + VertexDescription description = (VertexDescription)0; + description.Position = IN.ObjectSpacePosition; + description.Normal = IN.ObjectSpaceNormal; + description.Tangent = IN.ObjectSpaceTangent; + return description; + } + + // Graph Pixel + struct SurfaceDescription + { + float Alpha; + }; + + SurfaceDescription SurfaceDescriptionFunction(SurfaceDescriptionInputs IN) + { + SurfaceDescription surface = (SurfaceDescription)0; + float4 _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4 = _Color; + float _Split_cace9cff304a4c5d84b5305897d09aa9_R_1_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[0]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_G_2_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[1]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_B_3_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[2]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[3]; + surface.Alpha = _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float; + return surface; + } + + // -------------------------------------------------- + // Build Graph Inputs + #ifdef HAVE_VFX_MODIFICATION + #define VFX_SRP_ATTRIBUTES AttributesMesh + #define VaryingsMeshType VaryingsMeshToPS + #define VFX_SRP_VARYINGS VaryingsMeshType + #define VFX_SRP_SURFACE_INPUTS FragInputs + #endif + + VertexDescriptionInputs AttributesMeshToVertexDescriptionInputs(AttributesMesh input) + { + VertexDescriptionInputs output; + ZERO_INITIALIZE(VertexDescriptionInputs, output); + + output.ObjectSpaceNormal = input.normalOS; + output.ObjectSpaceTangent = input.tangentOS.xyz; + output.ObjectSpacePosition = input.positionOS; + + return output; + } + + VertexDescription GetVertexDescription(AttributesMesh input, float3 timeParameters + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + // build graph inputs + VertexDescriptionInputs vertexDescriptionInputs = AttributesMeshToVertexDescriptionInputs(input); + // Override time parameters with used one (This is required to correctly handle motion vectors for vertex animation based on time) + + // evaluate vertex graph + #ifdef HAVE_VFX_MODIFICATION + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + // Fetch the vertex graph properties for the particle instance. + GetElementVertexProperties(element, properties); + + VertexDescription vertexDescription = VertexDescriptionFunction(vertexDescriptionInputs, properties); + #else + VertexDescription vertexDescription = VertexDescriptionFunction(vertexDescriptionInputs); + #endif + return vertexDescription; + + } + + AttributesMesh ApplyMeshModification(AttributesMesh input, float3 timeParameters + #ifdef USE_CUSTOMINTERP_SUBSTRUCT + #ifdef TESSELLATION_ON + , inout VaryingsMeshToDS varyings + #else + , inout VaryingsMeshToPS varyings + #endif + #endif + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + VertexDescription vertexDescription = GetVertexDescription(input, timeParameters + #ifdef HAVE_VFX_MODIFICATION + , element + #endif + ); + + // copy graph output to the results + input.positionOS = vertexDescription.Position; + input.normalOS = vertexDescription.Normal; + input.tangentOS.xyz = vertexDescription.Tangent; + + + + return input; + } + + #if defined(_ADD_CUSTOM_VELOCITY) // For shader graph custom velocity + // Return precomputed Velocity in object space + float3 GetCustomVelocity(AttributesMesh input + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + VertexDescription vertexDescription = GetVertexDescription(input, _TimeParameters.xyz + #ifdef HAVE_VFX_MODIFICATION + , element + #endif + ); + return vertexDescription.CustomVelocity; + } + #endif + + FragInputs BuildFragInputs(VaryingsMeshToPS input) + { + FragInputs output; + ZERO_INITIALIZE(FragInputs, output); + + // Init to some default value to make the computer quiet (else it output 'divide by zero' warning even if value is not used). + // TODO: this is a really poor workaround, but the variable is used in a bunch of places + // to compute normals which are then passed on elsewhere to compute other values... + output.tangentToWorld = k_identity3x3; + output.positionSS = input.positionCS; // input.positionCS is SV_Position + + + #ifdef HAVE_VFX_MODIFICATION + // FragInputs from VFX come from two places: Interpolator or CBuffer. + #if VFX_USE_GRAPH_VALUES + uint instanceActiveIndex = asuint(UNITY_ACCESS_INSTANCED_PROP(PerInstance, _InstanceActiveIndex)); + /* WARNING: $splice Could not find named fragment 'VFXLoadGraphValues' */ + #endif + + /* WARNING: $splice Could not find named fragment 'VFXSetFragInputs' */ + + #endif + + // splice point to copy custom interpolator fields from varyings to frag inputs + + + return output; + } + + // existing HDRP code uses the combined function to go directly from packed to frag inputs + FragInputs UnpackVaryingsMeshToFragInputs(PackedVaryingsMeshToPS input) + { + UNITY_SETUP_INSTANCE_ID(input); + #if defined(HAVE_VFX_MODIFICATION) && defined(UNITY_INSTANCING_ENABLED) + unity_InstanceID = input.instanceID; + #endif + VaryingsMeshToPS unpacked = UnpackVaryingsMeshToPS(input); + return BuildFragInputs(unpacked); + } + SurfaceDescriptionInputs FragInputsToSurfaceDescriptionInputs(FragInputs input, float3 viewWS) + { + SurfaceDescriptionInputs output; + ZERO_INITIALIZE(SurfaceDescriptionInputs, output); + + #if defined(SHADER_STAGE_RAY_TRACING) + #else + #endif + + #if UNITY_UV_STARTS_AT_TOP + #else + #endif + + + + // splice point to copy frag inputs custom interpolator pack into the SDI + + + return output; + } + + // -------------------------------------------------- + // Build Surface Data (Specific Material) + + void ApplyDecalToSurfaceDataNoNormal(DecalSurfaceData decalSurfaceData, inout SurfaceData surfaceData); + + void ApplyDecalAndGetNormal(FragInputs fragInputs, PositionInputs posInput, SurfaceDescription surfaceDescription, + inout SurfaceData surfaceData) + { + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + #ifdef DECAL_NORMAL_BLENDING + // SG nodes don't ouptut surface gradients, so if decals require surf grad blending, we have to convert + // the normal to gradient before applying the decal. We then have to resolve the gradient back to world space + float3 normalTS; + + + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, fragInputs.tangentToWorld[2], normalTS); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + + GetNormalWS_SG(fragInputs, normalTS, surfaceData.normalWS, doubleSidedConstants); + #else + // normal delivered to master node + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + // Both uses and modifies 'surfaceData.normalWS'. + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, surfaceData.normalWS.xyz); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + #endif + } + void BuildSurfaceData(FragInputs fragInputs, inout SurfaceDescription surfaceDescription, float3 V, PositionInputs posInput, out SurfaceData surfaceData, out float3 bentNormalWS) + { + ZERO_INITIALIZE(SurfaceData, surfaceData); + + // specularOcclusion need to be init ahead of decal to quiet the compiler that modify the SurfaceData struct + // however specularOcclusion can come from the graph, so need to be init here so it can be override. + surfaceData.specularOcclusion = 1.0; + + + #if defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE) || defined(_REFRACTION_THIN) + if (_EnableSSRefraction) + { + + surfaceData.transmittanceMask = (1.0 - surfaceDescription.Alpha); + surfaceDescription.Alpha = 1.0; + } + else + { + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + surfaceDescription.Alpha = 1.0; + } + #else + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + #endif + + // These static material feature allow compile time optimization + surfaceData.materialFeatures = MATERIALFEATUREFLAGS_LIT_STANDARD; + #ifdef _MATERIAL_FEATURE_SUBSURFACE_SCATTERING + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING; + #endif + + #ifdef _MATERIAL_FEATURE_TRANSMISSION + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_TRANSMISSION; + #endif + + #ifdef _MATERIAL_FEATURE_ANISOTROPY + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_ANISOTROPY; + + // Initialize the normal to something non-zero to avoid a div-zero warning for anisotropy. + surfaceData.normalWS = float3(0, 1, 0); + #endif + + #ifdef _MATERIAL_FEATURE_IRIDESCENCE + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_IRIDESCENCE; + #endif + + #ifdef _MATERIAL_FEATURE_SPECULAR_COLOR + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR; + #endif + + #ifdef _MATERIAL_FEATURE_CLEAR_COAT + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_CLEAR_COAT; + #endif + + #if defined (_MATERIAL_FEATURE_SPECULAR_COLOR) && defined (_ENERGY_CONSERVING_SPECULAR) + // Require to have setup baseColor + // Reproduce the energy conservation done in legacy Unity. Not ideal but better for compatibility and users can unchek it + surfaceData.baseColor *= (1.0 - Max3(surfaceData.specularColor.r, surfaceData.specularColor.g, surfaceData.specularColor.b)); + #endif + + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + ApplyDecalAndGetNormal(fragInputs, posInput, surfaceDescription, surfaceData); + + surfaceData.geomNormalWS = fragInputs.tangentToWorld[2]; + + surfaceData.tangentWS = normalize(fragInputs.tangentToWorld[0].xyz); // The tangent is not normalize in tangentToWorld for mikkt. TODO: Check if it expected that we normalize with Morten. Tag: SURFACE_GRADIENT + + + bentNormalWS = surfaceData.normalWS; + + surfaceData.tangentWS = Orthonormalize(surfaceData.tangentWS, surfaceData.normalWS); + + #ifdef DEBUG_DISPLAY + if (_DebugMipMapMode != DEBUGMIPMAPMODE_NONE) + { + // TODO: need to update mip info + surfaceData.metallic = 0; + } + + // We need to call ApplyDebugToSurfaceData after filling the surfarcedata and before filling builtinData + // as it can modify attribute use for static lighting + ApplyDebugToSurfaceData(fragInputs.tangentToWorld, surfaceData); + #endif + + // By default we use the ambient occlusion with Tri-ace trick (apply outside) for specular occlusion. + // If user provide bent normal then we process a better term + #if defined(_SPECULAR_OCCLUSION_CUSTOM) + // Just use the value passed through via the slot (not active otherwise) + #elif defined(_SPECULAR_OCCLUSION_FROM_AO_BENT_NORMAL) + // If we have bent normal and ambient occlusion, process a specular occlusion + surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData.normalWS, surfaceData.ambientOcclusion, PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness)); + #elif defined(_AMBIENT_OCCLUSION) && defined(_SPECULAR_OCCLUSION_FROM_AO) + surfaceData.specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(ClampNdotV(dot(surfaceData.normalWS, V)), surfaceData.ambientOcclusion, PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness)); + #endif + + #if defined(_ENABLE_GEOMETRIC_SPECULAR_AA) && !defined(SHADER_STAGE_RAY_TRACING) + surfaceData.perceptualSmoothness = GeometricNormalFiltering(surfaceData.perceptualSmoothness, fragInputs.tangentToWorld[2], surfaceDescription.SpecularAAScreenSpaceVariance, surfaceDescription.SpecularAAThreshold); + #endif + } + + // -------------------------------------------------- + // Get Surface And BuiltinData + + void GetSurfaceAndBuiltinData(FragInputs fragInputs, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData RAY_TRACING_OPTIONAL_PARAMETERS) + { + // 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 + LODDitheringTransition(ComputeFadeMaskSeed(V, posInput.positionSS), unity_LODFade.x); + #endif + #endif + + #ifndef SHADER_UNLIT + #ifdef _DOUBLESIDED_ON + float3 doubleSidedConstants = _DoubleSidedConstants.xyz; + #else + float3 doubleSidedConstants = float3(1.0, 1.0, 1.0); + #endif + + ApplyDoubleSidedFlipOrMirror(fragInputs, doubleSidedConstants); // Apply double sided flip on the vertex normal + #endif // SHADER_UNLIT + + SurfaceDescriptionInputs surfaceDescriptionInputs = FragInputsToSurfaceDescriptionInputs(fragInputs, V); + + #if defined(HAVE_VFX_MODIFICATION) + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + GetElementPixelProperties(fragInputs, properties); + + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs, properties); + #else + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs); + #endif + + // Perform alpha test very early to save performance (a killed pixel will not sample textures) + // TODO: split graph evaluation to grab just alpha dependencies first? tricky.. + #ifdef _ALPHATEST_ON + float alphaCutoff = surfaceDescription.AlphaClipThreshold; + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + // The TransparentDepthPrepass is also used with SSR transparent. + // If an artists enable transaprent SSR but not the TransparentDepthPrepass itself, then we use AlphaClipThreshold + // otherwise if TransparentDepthPrepass is enabled we use AlphaClipThresholdDepthPrepass + #elif SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_POSTPASS + // DepthPostpass always use its own alpha threshold + alphaCutoff = surfaceDescription.AlphaClipThresholdDepthPostpass; + #elif (SHADERPASS == SHADERPASS_SHADOWS) || (SHADERPASS == SHADERPASS_RAYTRACING_VISIBILITY) + // If use shadow threshold isn't enable we don't allow any test + #endif + + GENERIC_ALPHA_TEST(surfaceDescription.Alpha, alphaCutoff); + #endif + + #if !defined(SHADER_STAGE_RAY_TRACING) && _DEPTHOFFSET_ON + ApplyDepthOffsetPositionInput(V, surfaceDescription.DepthOffset, GetViewForwardDir(), GetWorldToHClipMatrix(), posInput); + #endif + + #ifndef SHADER_UNLIT + float3 bentNormalWS; + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData, bentNormalWS); + + #ifdef FRAG_INPUTS_USE_TEXCOORD1 + float4 lightmapTexCoord1 = fragInputs.texCoord1; + #else + float4 lightmapTexCoord1 = float4(0,0,0,0); + #endif + + #ifdef FRAG_INPUTS_USE_TEXCOORD2 + float4 lightmapTexCoord2 = fragInputs.texCoord2; + #else + float4 lightmapTexCoord2 = float4(0,0,0,0); + #endif + + // Builtin Data + // For back lighting we use the oposite vertex normal + InitBuiltinData(posInput, surfaceDescription.Alpha, bentNormalWS, -fragInputs.tangentToWorld[2], lightmapTexCoord1, lightmapTexCoord2, builtinData); + + #else + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData); + + ZERO_BUILTIN_INITIALIZE(builtinData); // No call to InitBuiltinData as we don't have any lighting + builtinData.opacity = surfaceDescription.Alpha; + + #if defined(DEBUG_DISPLAY) + // Light Layers are currently not used for the Unlit shader (because it is not lit) + // But Unlit objects do cast shadows according to their rendering layer mask, which is what we want to + // display in the light layers visualization mode, therefore we need the renderingLayers + builtinData.renderingLayers = GetMeshRenderingLightLayer(); + #endif + + #endif // SHADER_UNLIT + + #ifdef _ALPHATEST_ON + // Used for sharpening by alpha to mask - Alpha to covertage is only used with depth only and forward pass (no shadow pass, no transparent pass) + builtinData.alphaClipTreshold = alphaCutoff; + #endif + + // override sampleBakedGI - not used by Unlit + + + // Note this will not fully work on transparent surfaces (can check with _SURFACE_TYPE_TRANSPARENT define) + // We will always overwrite vt feeback with the nearest. So behind transparent surfaces vt will not be resolved + // This is a limitation of the current MRT approach. + #ifdef UNITY_VIRTUAL_TEXTURING + #endif + + #if _DEPTHOFFSET_ON + builtinData.depthOffset = surfaceDescription.DepthOffset; + #endif + + // TODO: We should generate distortion / distortionBlur for non distortion pass + #if (SHADERPASS == SHADERPASS_DISTORTION) + builtinData.distortion = surfaceDescription.Distortion; + builtinData.distortionBlur = surfaceDescription.DistortionBlur; + #endif + + #ifndef SHADER_UNLIT + // PostInitBuiltinData call ApplyDebugToBuiltinData + PostInitBuiltinData(V, posInput, surfaceData, builtinData); + #else + ApplyDebugToBuiltinData(builtinData); + #endif + + RAY_TRACING_OPTIONAL_ALPHA_TEST_PASS + } + + // -------------------------------------------------- + // Main + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassDepthOnly.hlsl" + + // -------------------------------------------------- + // Visual Effect Vertex Invocations + + #ifdef HAVE_VFX_MODIFICATION + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/VisualEffectVertex.hlsl" + #endif + + ENDHLSL + } + Pass + { + Name "META" + Tags + { + "LightMode" = "META" + } + + // Render State + Cull Off + + // Debug + // + + // -------------------------------------------------- + // Pass + + HLSLPROGRAM + + // Pragmas + #pragma multi_compile _ DOTS_INSTANCING_ON + #pragma instancing_options renderinglayer + #pragma target 4.5 + #pragma vertex Vert + #pragma fragment Frag + #pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch + #pragma multi_compile_instancing + + // Keywords + #pragma shader_feature _ EDITOR_VISUALIZATION + #pragma shader_feature _ _SURFACE_TYPE_TRANSPARENT + #pragma shader_feature_local _ _DOUBLESIDED_ON + #pragma shader_feature_local _ _ADD_PRECOMPUTED_VELOCITY + #pragma shader_feature_local _ _TRANSPARENT_WRITES_MOTION_VEC + #pragma shader_feature_local_fragment _ _ENABLE_FOG_ON_TRANSPARENT + #pragma shader_feature_local_fragment _ _DISABLE_DECALS + #pragma shader_feature_local_raytracing _ _DISABLE_DECALS + #pragma shader_feature_local_fragment _ _DISABLE_SSR + #pragma shader_feature_local_raytracing _ _DISABLE_SSR + #pragma shader_feature_local_fragment _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local_raytracing _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local _ _REFRACTION_PLANE _REFRACTION_SPHERE _REFRACTION_THIN + // GraphKeywords: + + // For custom interpolators to inject a substruct definition before FragInputs definition, + // allowing for FragInputs to capture CI's intended for ShaderGraph's SDI. + /* WARNING: $splice Could not find named fragment 'CustomInterpolatorPreInclude' */ + + + // TODO: Merge FragInputsVFX substruct with CustomInterpolators. + #ifdef HAVE_VFX_MODIFICATION + struct FragInputsVFX + { + /* WARNING: $splice Could not find named fragment 'FragInputsVFX' */ + }; + #endif + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl" // Required by Tessellation.hlsl + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Tessellation.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Texture.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl" // Required to be include before we include properties as it define DECLARE_STACK_CB + // Always include Shader Graph version + // Always include last to avoid double macros + #include "Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl" // Need to be here for Gradient struct definition + + // -------------------------------------------------- + // Defines + + // Attribute + #define ATTRIBUTES_NEED_NORMAL + #define ATTRIBUTES_NEED_TEXCOORD0 + #define ATTRIBUTES_NEED_TEXCOORD1 + #define ATTRIBUTES_NEED_TEXCOORD2 + #define ATTRIBUTES_NEED_TEXCOORD3 + #define VARYINGS_NEED_POSITION_WS + #define VARYINGS_NEED_POSITIONPREDISPLACEMENT_WS + #define VARYINGS_NEED_TEXCOORD0 + #define VARYINGS_NEED_TEXCOORD1 + #define VARYINGS_NEED_TEXCOORD2 + #define VARYINGS_NEED_TEXCOORD3 + + #define HAVE_MESH_MODIFICATION + + //Strip down the FragInputs.hlsl (on graphics), so we can only optimize the interpolators we use. + //if by accident something requests contents of FragInputs.hlsl, it will be caught as a compiler error + //Frag inputs stripping is only enabled when FRAG_INPUTS_ENABLE_STRIPPING is set + #if !defined(SHADER_STAGE_RAY_TRACING) && SHADERPASS != SHADERPASS_RAYTRACING_GBUFFER && SHADERPASS != SHADERPASS_FULL_SCREEN_DEBUG + #define FRAG_INPUTS_ENABLE_STRIPPING + #endif + #define FRAG_INPUTS_USE_TEXCOORD0 + #define FRAG_INPUTS_USE_TEXCOORD1 + #define FRAG_INPUTS_USE_TEXCOORD2 + #define FRAG_INPUTS_USE_TEXCOORD3 + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl" + + + + #define SHADERPASS SHADERPASS_LIGHT_TRANSPORT + #define RAYTRACING_SHADER_GRAPH_DEFAULT + #define SCENEPICKINGPASS 1 + + + // Following two define are a workaround introduce in 10.1.x for RaytracingQualityNode + // The ShaderGraph don't support correctly migration of this node as it serialize all the node data + // in the json file making it impossible to uprgrade. Until we get a fix, we do a workaround here + // to still allow us to rename the field and keyword of this node without breaking existing code. + #ifdef RAYTRACING_SHADER_GRAPH_DEFAULT + #define RAYTRACING_SHADER_GRAPH_HIGH + #endif + + #ifdef RAYTRACING_SHADER_GRAPH_RAYTRACED + #define RAYTRACING_SHADER_GRAPH_LOW + #endif + // end + + #ifndef SHADER_UNLIT + // We need isFrontFace when using double sided - it is not required for unlit as in case of unlit double sided only drive the cullmode + // VARYINGS_NEED_CULLFACE can be define by VaryingsMeshToPS.FaceSign input if a IsFrontFace Node is included in the shader graph. + #if defined(_DOUBLESIDED_ON) && !defined(VARYINGS_NEED_CULLFACE) + #define VARYINGS_NEED_CULLFACE + #endif + #endif + + // Specific Material Define + #define _SPECULAR_OCCLUSION_FROM_AO 1 + #define _ENERGY_CONSERVING_SPECULAR 1 + + // If we use subsurface scattering, enable output split lighting (for forward pass) + #if defined(_MATERIAL_FEATURE_SUBSURFACE_SCATTERING) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define OUTPUT_SPLIT_LIGHTING + #endif + + // This shader support recursive rendering for raytracing + #define HAVE_RECURSIVE_RENDERING + + // In Path Tracing, For all single-sided, refractive materials, we want to force a thin refraction model + #if (SHADERPASS == SHADERPASS_PATH_TRACING) && !defined(_DOUBLESIDED_ON) && (defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE)) + #undef _REFRACTION_PLANE + #undef _REFRACTION_SPHERE + #define _REFRACTION_THIN + #endif + // Caution: we can use the define SHADER_UNLIT onlit after the above Material include as it is the Unlit template who define it + + // To handle SSR on transparent correctly with a possibility to enable/disable it per framesettings + // we should have a code like this: + // if !defined(_DISABLE_SSR_TRANSPARENT) + // pragma multi_compile _ WRITE_NORMAL_BUFFER + // endif + // i.e we enable the multicompile only if we can receive SSR or not, and then C# code drive + // it based on if SSR transparent in frame settings and not (and stripper can strip it). + // this is currently not possible with our current preprocessor as _DISABLE_SSR_TRANSPARENT is a keyword not a define + // so instead we used this and chose to pay the extra cost of normal write even if SSR transaprent is disabled. + // Ideally the shader graph generator should handle it but condition below can't be handle correctly for now. + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + #if !defined(_DISABLE_SSR_TRANSPARENT) && !defined(SHADER_UNLIT) + #define WRITE_NORMAL_BUFFER + #endif + #endif + + #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) + // Don't do it with debug display mode as it is possible there is no depth prepass in this case + #if !defined(_SURFACE_TYPE_TRANSPARENT) + #if SHADERPASS == SHADERPASS_FORWARD + #define SHADERPASS_FORWARD_BYPASS_ALPHA_TEST + #elif SHADERPASS == SHADERPASS_GBUFFER + #define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST + #endif + #endif + #endif + + // Define _DEFERRED_CAPABLE_MATERIAL for shader capable to run in deferred pass + #if defined(SHADER_LIT) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define _DEFERRED_CAPABLE_MATERIAL + #endif + + // Translate transparent motion vector define + #if defined(_TRANSPARENT_WRITES_MOTION_VEC) && defined(_SURFACE_TYPE_TRANSPARENT) + #define _WRITE_TRANSPARENT_MOTION_VECTOR + #endif + + // -- Graph Properties + CBUFFER_START(UnityPerMaterial) + float4 _Color; + float4 _EmissionColor; + float _UseShadowThreshold; + float4 _DoubleSidedConstants; + float _BlendMode; + float _EnableBlendModePreserveSpecularLighting; + float _RayTracing; + float _RefractionModel; + CBUFFER_END + + + // Object and Global properties + + // -- Property used by ScenePickingPass + #ifdef SCENEPICKINGPASS + float4 _SelectionID; + #endif + + // -- Properties used by SceneSelectionPass + #ifdef SCENESELECTIONPASS + int _ObjectId; + int _PassValue; + #endif + + // Includes + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/PickingSpaceTransforms.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugDisplay.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/NormalSurfaceGradient.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/Lit.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/BuiltinUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/MaterialUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Decal/DecalUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitDecalData.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderGraphFunctions.hlsl" + // GraphIncludes: + + // -------------------------------------------------- + // Structs and Packing + + struct AttributesMesh + { + float3 positionOS : POSITION; + float3 normalOS : NORMAL; + float4 uv0 : TEXCOORD0; + float4 uv1 : TEXCOORD1; + float4 uv2 : TEXCOORD2; + float4 uv3 : TEXCOORD3; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : INSTANCEID_SEMANTIC; + #endif + }; + struct VaryingsMeshToPS + { + SV_POSITION_QUALIFIERS float4 positionCS : SV_POSITION; + float3 positionRWS; + float3 positionPredisplacementRWS; + float4 texCoord0; + float4 texCoord1; + float4 texCoord2; + float4 texCoord3; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : CUSTOM_INSTANCE_ID; + #endif + }; + struct VertexDescriptionInputs + { + }; + struct SurfaceDescriptionInputs + { + float3 TangentSpaceNormal; + }; + struct PackedVaryingsMeshToPS + { + SV_POSITION_QUALIFIERS float4 positionCS : SV_POSITION; + float4 texCoord0 : INTERP0; + float4 texCoord1 : INTERP1; + float4 texCoord2 : INTERP2; + float4 texCoord3 : INTERP3; + float3 positionRWS : INTERP4; + float3 positionPredisplacementRWS : INTERP5; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : CUSTOM_INSTANCE_ID; + #endif + }; + + PackedVaryingsMeshToPS PackVaryingsMeshToPS (VaryingsMeshToPS input) + { + PackedVaryingsMeshToPS output; + ZERO_INITIALIZE(PackedVaryingsMeshToPS, output); + output.positionCS = input.positionCS; + output.texCoord0.xyzw = input.texCoord0; + output.texCoord1.xyzw = input.texCoord1; + output.texCoord2.xyzw = input.texCoord2; + output.texCoord3.xyzw = input.texCoord3; + output.positionRWS.xyz = input.positionRWS; + output.positionPredisplacementRWS.xyz = input.positionPredisplacementRWS; + #if UNITY_ANY_INSTANCING_ENABLED + output.instanceID = input.instanceID; + #endif + return output; + } + + VaryingsMeshToPS UnpackVaryingsMeshToPS (PackedVaryingsMeshToPS input) + { + VaryingsMeshToPS output; + output.positionCS = input.positionCS; + output.texCoord0 = input.texCoord0.xyzw; + output.texCoord1 = input.texCoord1.xyzw; + output.texCoord2 = input.texCoord2.xyzw; + output.texCoord3 = input.texCoord3.xyzw; + output.positionRWS = input.positionRWS.xyz; + output.positionPredisplacementRWS = input.positionPredisplacementRWS.xyz; + #if UNITY_ANY_INSTANCING_ENABLED + output.instanceID = input.instanceID; + #endif + return output; + } + + + // -------------------------------------------------- + // Graph + + + // Graph Functions + // GraphFunctions: + + // Graph Vertex + struct VertexDescription + { + }; + + VertexDescription VertexDescriptionFunction(VertexDescriptionInputs IN) + { + VertexDescription description = (VertexDescription)0; + return description; + } + + // Graph Pixel + struct SurfaceDescription + { + float3 BaseColor; + float3 Emission; + float Alpha; + float3 BentNormal; + float Smoothness; + float Occlusion; + float3 NormalTS; + float Metallic; + }; + + SurfaceDescription SurfaceDescriptionFunction(SurfaceDescriptionInputs IN) + { + SurfaceDescription surface = (SurfaceDescription)0; + float4 _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4 = _Color; + float _Split_cace9cff304a4c5d84b5305897d09aa9_R_1_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[0]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_G_2_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[1]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_B_3_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[2]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[3]; + surface.BaseColor = (_Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4.xyz); + surface.Emission = float3(0, 0, 0); + surface.Alpha = _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float; + surface.BentNormal = IN.TangentSpaceNormal; + surface.Smoothness = 0.5; + surface.Occlusion = 1; + surface.NormalTS = IN.TangentSpaceNormal; + surface.Metallic = 0; + return surface; + } + + // -------------------------------------------------- + // Build Graph Inputs + #ifdef HAVE_VFX_MODIFICATION + #define VFX_SRP_ATTRIBUTES AttributesMesh + #define VaryingsMeshType VaryingsMeshToPS + #define VFX_SRP_VARYINGS VaryingsMeshType + #define VFX_SRP_SURFACE_INPUTS FragInputs + #endif + + VertexDescriptionInputs AttributesMeshToVertexDescriptionInputs(AttributesMesh input) + { + VertexDescriptionInputs output; + ZERO_INITIALIZE(VertexDescriptionInputs, output); + + + return output; + } + + VertexDescription GetVertexDescription(AttributesMesh input, float3 timeParameters + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + // build graph inputs + VertexDescriptionInputs vertexDescriptionInputs = AttributesMeshToVertexDescriptionInputs(input); + // Override time parameters with used one (This is required to correctly handle motion vectors for vertex animation based on time) + + // evaluate vertex graph + #ifdef HAVE_VFX_MODIFICATION + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + // Fetch the vertex graph properties for the particle instance. + GetElementVertexProperties(element, properties); + + VertexDescription vertexDescription = VertexDescriptionFunction(vertexDescriptionInputs, properties); + #else + VertexDescription vertexDescription = VertexDescriptionFunction(vertexDescriptionInputs); + #endif + return vertexDescription; + + } + + AttributesMesh ApplyMeshModification(AttributesMesh input, float3 timeParameters + #ifdef USE_CUSTOMINTERP_SUBSTRUCT + #ifdef TESSELLATION_ON + , inout VaryingsMeshToDS varyings + #else + , inout VaryingsMeshToPS varyings + #endif + #endif + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + VertexDescription vertexDescription = GetVertexDescription(input, timeParameters + #ifdef HAVE_VFX_MODIFICATION + , element + #endif + ); + + // copy graph output to the results + + /* WARNING: $splice Could not find named fragment 'CustomInterpolatorVertMeshCustomInterpolation' */ + + return input; + } + + #if defined(_ADD_CUSTOM_VELOCITY) // For shader graph custom velocity + // Return precomputed Velocity in object space + float3 GetCustomVelocity(AttributesMesh input + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + VertexDescription vertexDescription = GetVertexDescription(input, _TimeParameters.xyz + #ifdef HAVE_VFX_MODIFICATION + , element + #endif + ); + return vertexDescription.CustomVelocity; + } + #endif + + FragInputs BuildFragInputs(VaryingsMeshToPS input) + { + FragInputs output; + ZERO_INITIALIZE(FragInputs, output); + + // Init to some default value to make the computer quiet (else it output 'divide by zero' warning even if value is not used). + // TODO: this is a really poor workaround, but the variable is used in a bunch of places + // to compute normals which are then passed on elsewhere to compute other values... + output.tangentToWorld = k_identity3x3; + output.positionSS = input.positionCS; // input.positionCS is SV_Position + + output.positionRWS = input.positionRWS; + output.positionPredisplacementRWS = input.positionPredisplacementRWS; + output.texCoord0 = input.texCoord0; + output.texCoord1 = input.texCoord1; + output.texCoord2 = input.texCoord2; + output.texCoord3 = input.texCoord3; + + #ifdef HAVE_VFX_MODIFICATION + // FragInputs from VFX come from two places: Interpolator or CBuffer. + #if VFX_USE_GRAPH_VALUES + uint instanceActiveIndex = asuint(UNITY_ACCESS_INSTANCED_PROP(PerInstance, _InstanceActiveIndex)); + /* WARNING: $splice Could not find named fragment 'VFXLoadGraphValues' */ + #endif + + /* WARNING: $splice Could not find named fragment 'VFXSetFragInputs' */ + + #endif + + // splice point to copy custom interpolator fields from varyings to frag inputs + /* WARNING: $splice Could not find named fragment 'CustomInterpolatorVaryingsToFragInputs' */ + + return output; + } + + // existing HDRP code uses the combined function to go directly from packed to frag inputs + FragInputs UnpackVaryingsMeshToFragInputs(PackedVaryingsMeshToPS input) + { + UNITY_SETUP_INSTANCE_ID(input); + #if defined(HAVE_VFX_MODIFICATION) && defined(UNITY_INSTANCING_ENABLED) + unity_InstanceID = input.instanceID; + #endif + VaryingsMeshToPS unpacked = UnpackVaryingsMeshToPS(input); + return BuildFragInputs(unpacked); + } + SurfaceDescriptionInputs FragInputsToSurfaceDescriptionInputs(FragInputs input, float3 viewWS) + { + SurfaceDescriptionInputs output; + ZERO_INITIALIZE(SurfaceDescriptionInputs, output); + + #if defined(SHADER_STAGE_RAY_TRACING) + #else + #endif + output.TangentSpaceNormal = float3(0.0f, 0.0f, 1.0f); + + #if UNITY_UV_STARTS_AT_TOP + #else + #endif + + + + // splice point to copy frag inputs custom interpolator pack into the SDI + /* WARNING: $splice Could not find named fragment 'CustomInterpolatorCopyToSDI' */ + + return output; + } + + // -------------------------------------------------- + // Build Surface Data (Specific Material) + + void ApplyDecalToSurfaceDataNoNormal(DecalSurfaceData decalSurfaceData, inout SurfaceData surfaceData); + + void ApplyDecalAndGetNormal(FragInputs fragInputs, PositionInputs posInput, SurfaceDescription surfaceDescription, + inout SurfaceData surfaceData) + { + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + #ifdef DECAL_NORMAL_BLENDING + // SG nodes don't ouptut surface gradients, so if decals require surf grad blending, we have to convert + // the normal to gradient before applying the decal. We then have to resolve the gradient back to world space + float3 normalTS; + + normalTS = SurfaceGradientFromTangentSpaceNormalAndFromTBN(surfaceDescription.NormalTS, + fragInputs.tangentToWorld[0], fragInputs.tangentToWorld[1]); + + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, fragInputs.tangentToWorld[2], normalTS); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + + GetNormalWS_SG(fragInputs, normalTS, surfaceData.normalWS, doubleSidedConstants); + #else + // normal delivered to master node + GetNormalWS(fragInputs, surfaceDescription.NormalTS, surfaceData.normalWS, doubleSidedConstants); + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + // Both uses and modifies 'surfaceData.normalWS'. + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, surfaceData.normalWS.xyz); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + #endif + } + void BuildSurfaceData(FragInputs fragInputs, inout SurfaceDescription surfaceDescription, float3 V, PositionInputs posInput, out SurfaceData surfaceData, out float3 bentNormalWS) + { + ZERO_INITIALIZE(SurfaceData, surfaceData); + + // specularOcclusion need to be init ahead of decal to quiet the compiler that modify the SurfaceData struct + // however specularOcclusion can come from the graph, so need to be init here so it can be override. + surfaceData.specularOcclusion = 1.0; + + surfaceData.baseColor = surfaceDescription.BaseColor; + surfaceData.perceptualSmoothness = surfaceDescription.Smoothness; + surfaceData.ambientOcclusion = surfaceDescription.Occlusion; + surfaceData.metallic = surfaceDescription.Metallic; + + #if defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE) || defined(_REFRACTION_THIN) + if (_EnableSSRefraction) + { + + surfaceData.transmittanceMask = (1.0 - surfaceDescription.Alpha); + surfaceDescription.Alpha = 1.0; + } + else + { + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + surfaceDescription.Alpha = 1.0; + } + #else + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + #endif + + // These static material feature allow compile time optimization + surfaceData.materialFeatures = MATERIALFEATUREFLAGS_LIT_STANDARD; + #ifdef _MATERIAL_FEATURE_SUBSURFACE_SCATTERING + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING; + #endif + + #ifdef _MATERIAL_FEATURE_TRANSMISSION + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_TRANSMISSION; + #endif + + #ifdef _MATERIAL_FEATURE_ANISOTROPY + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_ANISOTROPY; + + // Initialize the normal to something non-zero to avoid a div-zero warning for anisotropy. + surfaceData.normalWS = float3(0, 1, 0); + #endif + + #ifdef _MATERIAL_FEATURE_IRIDESCENCE + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_IRIDESCENCE; + #endif + + #ifdef _MATERIAL_FEATURE_SPECULAR_COLOR + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR; + #endif + + #ifdef _MATERIAL_FEATURE_CLEAR_COAT + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_CLEAR_COAT; + #endif + + #if defined (_MATERIAL_FEATURE_SPECULAR_COLOR) && defined (_ENERGY_CONSERVING_SPECULAR) + // Require to have setup baseColor + // Reproduce the energy conservation done in legacy Unity. Not ideal but better for compatibility and users can unchek it + surfaceData.baseColor *= (1.0 - Max3(surfaceData.specularColor.r, surfaceData.specularColor.g, surfaceData.specularColor.b)); + #endif + + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + ApplyDecalAndGetNormal(fragInputs, posInput, surfaceDescription, surfaceData); + + surfaceData.geomNormalWS = fragInputs.tangentToWorld[2]; + + surfaceData.tangentWS = normalize(fragInputs.tangentToWorld[0].xyz); // The tangent is not normalize in tangentToWorld for mikkt. TODO: Check if it expected that we normalize with Morten. Tag: SURFACE_GRADIENT + + + bentNormalWS = surfaceData.normalWS; + + surfaceData.tangentWS = Orthonormalize(surfaceData.tangentWS, surfaceData.normalWS); + + #ifdef DEBUG_DISPLAY + if (_DebugMipMapMode != DEBUGMIPMAPMODE_NONE) + { + // TODO: need to update mip info + surfaceData.metallic = 0; + } + + // We need to call ApplyDebugToSurfaceData after filling the surfarcedata and before filling builtinData + // as it can modify attribute use for static lighting + ApplyDebugToSurfaceData(fragInputs.tangentToWorld, surfaceData); + #endif + + // By default we use the ambient occlusion with Tri-ace trick (apply outside) for specular occlusion. + // If user provide bent normal then we process a better term + #if defined(_SPECULAR_OCCLUSION_CUSTOM) + // Just use the value passed through via the slot (not active otherwise) + #elif defined(_SPECULAR_OCCLUSION_FROM_AO_BENT_NORMAL) + // If we have bent normal and ambient occlusion, process a specular occlusion + surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData.normalWS, surfaceData.ambientOcclusion, PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness)); + #elif defined(_AMBIENT_OCCLUSION) && defined(_SPECULAR_OCCLUSION_FROM_AO) + surfaceData.specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(ClampNdotV(dot(surfaceData.normalWS, V)), surfaceData.ambientOcclusion, PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness)); + #endif + + #if defined(_ENABLE_GEOMETRIC_SPECULAR_AA) && !defined(SHADER_STAGE_RAY_TRACING) + surfaceData.perceptualSmoothness = GeometricNormalFiltering(surfaceData.perceptualSmoothness, fragInputs.tangentToWorld[2], surfaceDescription.SpecularAAScreenSpaceVariance, surfaceDescription.SpecularAAThreshold); + #endif + } + + // -------------------------------------------------- + // Get Surface And BuiltinData + + void GetSurfaceAndBuiltinData(FragInputs fragInputs, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData RAY_TRACING_OPTIONAL_PARAMETERS) + { + // 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 + LODDitheringTransition(ComputeFadeMaskSeed(V, posInput.positionSS), unity_LODFade.x); + #endif + #endif + + #ifndef SHADER_UNLIT + #ifdef _DOUBLESIDED_ON + float3 doubleSidedConstants = _DoubleSidedConstants.xyz; + #else + float3 doubleSidedConstants = float3(1.0, 1.0, 1.0); + #endif + + ApplyDoubleSidedFlipOrMirror(fragInputs, doubleSidedConstants); // Apply double sided flip on the vertex normal + #endif // SHADER_UNLIT + + SurfaceDescriptionInputs surfaceDescriptionInputs = FragInputsToSurfaceDescriptionInputs(fragInputs, V); + + #if defined(HAVE_VFX_MODIFICATION) + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + GetElementPixelProperties(fragInputs, properties); + + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs, properties); + #else + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs); + #endif + + // Perform alpha test very early to save performance (a killed pixel will not sample textures) + // TODO: split graph evaluation to grab just alpha dependencies first? tricky.. + #ifdef _ALPHATEST_ON + float alphaCutoff = surfaceDescription.AlphaClipThreshold; + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + // The TransparentDepthPrepass is also used with SSR transparent. + // If an artists enable transaprent SSR but not the TransparentDepthPrepass itself, then we use AlphaClipThreshold + // otherwise if TransparentDepthPrepass is enabled we use AlphaClipThresholdDepthPrepass + #elif SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_POSTPASS + // DepthPostpass always use its own alpha threshold + alphaCutoff = surfaceDescription.AlphaClipThresholdDepthPostpass; + #elif (SHADERPASS == SHADERPASS_SHADOWS) || (SHADERPASS == SHADERPASS_RAYTRACING_VISIBILITY) + // If use shadow threshold isn't enable we don't allow any test + #endif + + GENERIC_ALPHA_TEST(surfaceDescription.Alpha, alphaCutoff); + #endif + + #if !defined(SHADER_STAGE_RAY_TRACING) && _DEPTHOFFSET_ON + ApplyDepthOffsetPositionInput(V, surfaceDescription.DepthOffset, GetViewForwardDir(), GetWorldToHClipMatrix(), posInput); + #endif + + #ifndef SHADER_UNLIT + float3 bentNormalWS; + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData, bentNormalWS); + + #ifdef FRAG_INPUTS_USE_TEXCOORD1 + float4 lightmapTexCoord1 = fragInputs.texCoord1; + #else + float4 lightmapTexCoord1 = float4(0,0,0,0); + #endif + + #ifdef FRAG_INPUTS_USE_TEXCOORD2 + float4 lightmapTexCoord2 = fragInputs.texCoord2; + #else + float4 lightmapTexCoord2 = float4(0,0,0,0); + #endif + + // Builtin Data + // For back lighting we use the oposite vertex normal + InitBuiltinData(posInput, surfaceDescription.Alpha, bentNormalWS, -fragInputs.tangentToWorld[2], lightmapTexCoord1, lightmapTexCoord2, builtinData); + + #else + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData); + + ZERO_BUILTIN_INITIALIZE(builtinData); // No call to InitBuiltinData as we don't have any lighting + builtinData.opacity = surfaceDescription.Alpha; + + #if defined(DEBUG_DISPLAY) + // Light Layers are currently not used for the Unlit shader (because it is not lit) + // But Unlit objects do cast shadows according to their rendering layer mask, which is what we want to + // display in the light layers visualization mode, therefore we need the renderingLayers + builtinData.renderingLayers = GetMeshRenderingLightLayer(); + #endif + + #endif // SHADER_UNLIT + + #ifdef _ALPHATEST_ON + // Used for sharpening by alpha to mask - Alpha to covertage is only used with depth only and forward pass (no shadow pass, no transparent pass) + builtinData.alphaClipTreshold = alphaCutoff; + #endif + + // override sampleBakedGI - not used by Unlit + + builtinData.emissiveColor = surfaceDescription.Emission; + + // Note this will not fully work on transparent surfaces (can check with _SURFACE_TYPE_TRANSPARENT define) + // We will always overwrite vt feeback with the nearest. So behind transparent surfaces vt will not be resolved + // This is a limitation of the current MRT approach. + #ifdef UNITY_VIRTUAL_TEXTURING + #endif + + #if _DEPTHOFFSET_ON + builtinData.depthOffset = surfaceDescription.DepthOffset; + #endif + + // TODO: We should generate distortion / distortionBlur for non distortion pass + #if (SHADERPASS == SHADERPASS_DISTORTION) + builtinData.distortion = surfaceDescription.Distortion; + builtinData.distortionBlur = surfaceDescription.DistortionBlur; + #endif + + #ifndef SHADER_UNLIT + // PostInitBuiltinData call ApplyDebugToBuiltinData + PostInitBuiltinData(V, posInput, surfaceData, builtinData); + #else + ApplyDebugToBuiltinData(builtinData); + #endif + + RAY_TRACING_OPTIONAL_ALPHA_TEST_PASS + } + + // -------------------------------------------------- + // Main + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassLightTransport.hlsl" + + // -------------------------------------------------- + // Visual Effect Vertex Invocations + + #ifdef HAVE_VFX_MODIFICATION + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/VisualEffectVertex.hlsl" + #endif + + ENDHLSL + } + Pass + { + Name "ScenePickingPass" + Tags + { + "LightMode" = "Picking" + } + + // Render State + Cull [_CullMode] + + // Debug + // + + // -------------------------------------------------- + // Pass + + HLSLPROGRAM + + // Pragmas + #pragma multi_compile _ DOTS_INSTANCING_ON + #pragma editor_sync_compilation + #pragma instancing_options renderinglayer + #pragma target 4.5 + #pragma vertex Vert + #pragma fragment Frag + #pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch + #pragma multi_compile_instancing + + // Keywords + #pragma shader_feature _ _SURFACE_TYPE_TRANSPARENT + #pragma shader_feature_local _ _DOUBLESIDED_ON + #pragma shader_feature_local _ _ADD_PRECOMPUTED_VELOCITY + #pragma shader_feature_local _ _TRANSPARENT_WRITES_MOTION_VEC + #pragma shader_feature_local_fragment _ _ENABLE_FOG_ON_TRANSPARENT + #pragma shader_feature_local_fragment _ _DISABLE_DECALS + #pragma shader_feature_local_raytracing _ _DISABLE_DECALS + #pragma shader_feature_local_fragment _ _DISABLE_SSR + #pragma shader_feature_local_raytracing _ _DISABLE_SSR + #pragma shader_feature_local_fragment _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local_raytracing _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local _ _REFRACTION_PLANE _REFRACTION_SPHERE _REFRACTION_THIN + // GraphKeywords: + + // For custom interpolators to inject a substruct definition before FragInputs definition, + // allowing for FragInputs to capture CI's intended for ShaderGraph's SDI. + struct CustomInterpolators + { + }; + #define USE_CUSTOMINTERP_SUBSTRUCT + + + + // TODO: Merge FragInputsVFX substruct with CustomInterpolators. + #ifdef HAVE_VFX_MODIFICATION + struct FragInputsVFX + { + /* WARNING: $splice Could not find named fragment 'FragInputsVFX' */ + }; + #endif + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl" // Required by Tessellation.hlsl + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Tessellation.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Texture.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl" // Required to be include before we include properties as it define DECLARE_STACK_CB + // Always include Shader Graph version + // Always include last to avoid double macros + #include "Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl" // Need to be here for Gradient struct definition + + // -------------------------------------------------- + // Defines + + // Attribute + #define ATTRIBUTES_NEED_NORMAL + #define ATTRIBUTES_NEED_TANGENT + #define VARYINGS_NEED_TANGENT_TO_WORLD + + #define HAVE_MESH_MODIFICATION + + //Strip down the FragInputs.hlsl (on graphics), so we can only optimize the interpolators we use. + //if by accident something requests contents of FragInputs.hlsl, it will be caught as a compiler error + //Frag inputs stripping is only enabled when FRAG_INPUTS_ENABLE_STRIPPING is set + #if !defined(SHADER_STAGE_RAY_TRACING) && SHADERPASS != SHADERPASS_RAYTRACING_GBUFFER && SHADERPASS != SHADERPASS_FULL_SCREEN_DEBUG + #define FRAG_INPUTS_ENABLE_STRIPPING + #endif + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl" + + + + #define SHADERPASS SHADERPASS_DEPTH_ONLY + #define SCENEPICKINGPASS 1 + + + // Following two define are a workaround introduce in 10.1.x for RaytracingQualityNode + // The ShaderGraph don't support correctly migration of this node as it serialize all the node data + // in the json file making it impossible to uprgrade. Until we get a fix, we do a workaround here + // to still allow us to rename the field and keyword of this node without breaking existing code. + #ifdef RAYTRACING_SHADER_GRAPH_DEFAULT + #define RAYTRACING_SHADER_GRAPH_HIGH + #endif + + #ifdef RAYTRACING_SHADER_GRAPH_RAYTRACED + #define RAYTRACING_SHADER_GRAPH_LOW + #endif + // end + + #ifndef SHADER_UNLIT + // We need isFrontFace when using double sided - it is not required for unlit as in case of unlit double sided only drive the cullmode + // VARYINGS_NEED_CULLFACE can be define by VaryingsMeshToPS.FaceSign input if a IsFrontFace Node is included in the shader graph. + #if defined(_DOUBLESIDED_ON) && !defined(VARYINGS_NEED_CULLFACE) + #define VARYINGS_NEED_CULLFACE + #endif + #endif + + // Specific Material Define + #define _SPECULAR_OCCLUSION_FROM_AO 1 + #define _ENERGY_CONSERVING_SPECULAR 1 + + // If we use subsurface scattering, enable output split lighting (for forward pass) + #if defined(_MATERIAL_FEATURE_SUBSURFACE_SCATTERING) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define OUTPUT_SPLIT_LIGHTING + #endif + + // This shader support recursive rendering for raytracing + #define HAVE_RECURSIVE_RENDERING + + // In Path Tracing, For all single-sided, refractive materials, we want to force a thin refraction model + #if (SHADERPASS == SHADERPASS_PATH_TRACING) && !defined(_DOUBLESIDED_ON) && (defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE)) + #undef _REFRACTION_PLANE + #undef _REFRACTION_SPHERE + #define _REFRACTION_THIN + #endif + // Caution: we can use the define SHADER_UNLIT onlit after the above Material include as it is the Unlit template who define it + + // To handle SSR on transparent correctly with a possibility to enable/disable it per framesettings + // we should have a code like this: + // if !defined(_DISABLE_SSR_TRANSPARENT) + // pragma multi_compile _ WRITE_NORMAL_BUFFER + // endif + // i.e we enable the multicompile only if we can receive SSR or not, and then C# code drive + // it based on if SSR transparent in frame settings and not (and stripper can strip it). + // this is currently not possible with our current preprocessor as _DISABLE_SSR_TRANSPARENT is a keyword not a define + // so instead we used this and chose to pay the extra cost of normal write even if SSR transaprent is disabled. + // Ideally the shader graph generator should handle it but condition below can't be handle correctly for now. + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + #if !defined(_DISABLE_SSR_TRANSPARENT) && !defined(SHADER_UNLIT) + #define WRITE_NORMAL_BUFFER + #endif + #endif + + #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) + // Don't do it with debug display mode as it is possible there is no depth prepass in this case + #if !defined(_SURFACE_TYPE_TRANSPARENT) + #if SHADERPASS == SHADERPASS_FORWARD + #define SHADERPASS_FORWARD_BYPASS_ALPHA_TEST + #elif SHADERPASS == SHADERPASS_GBUFFER + #define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST + #endif + #endif + #endif + + // Define _DEFERRED_CAPABLE_MATERIAL for shader capable to run in deferred pass + #if defined(SHADER_LIT) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define _DEFERRED_CAPABLE_MATERIAL + #endif + + // Translate transparent motion vector define + #if defined(_TRANSPARENT_WRITES_MOTION_VEC) && defined(_SURFACE_TYPE_TRANSPARENT) + #define _WRITE_TRANSPARENT_MOTION_VECTOR + #endif + + // -- Graph Properties + CBUFFER_START(UnityPerMaterial) + float4 _Color; + float4 _EmissionColor; + float _UseShadowThreshold; + float4 _DoubleSidedConstants; + float _BlendMode; + float _EnableBlendModePreserveSpecularLighting; + float _RayTracing; + float _RefractionModel; + CBUFFER_END + + + // Object and Global properties + + // -- Property used by ScenePickingPass + #ifdef SCENEPICKINGPASS + float4 _SelectionID; + #endif + + // -- Properties used by SceneSelectionPass + #ifdef SCENESELECTIONPASS + int _ObjectId; + int _PassValue; + #endif + + // Includes + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/PickingSpaceTransforms.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugDisplay.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/NormalSurfaceGradient.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/Lit.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/BuiltinUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/MaterialUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Decal/DecalUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderGraphFunctions.hlsl" + // GraphIncludes: + + // -------------------------------------------------- + // Structs and Packing + + struct AttributesMesh + { + float3 positionOS : POSITION; + float3 normalOS : NORMAL; + float4 tangentOS : TANGENT; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : INSTANCEID_SEMANTIC; + #endif + }; + struct VaryingsMeshToPS + { + SV_POSITION_QUALIFIERS float4 positionCS : SV_POSITION; + float3 normalWS; + float4 tangentWS; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : CUSTOM_INSTANCE_ID; + #endif + }; + struct VertexDescriptionInputs + { + float3 ObjectSpaceNormal; + float3 ObjectSpaceTangent; + float3 ObjectSpacePosition; + }; + struct SurfaceDescriptionInputs + { + float3 TangentSpaceNormal; + }; + struct PackedVaryingsMeshToPS + { + SV_POSITION_QUALIFIERS float4 positionCS : SV_POSITION; + float4 tangentWS : INTERP0; + float3 normalWS : INTERP1; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : CUSTOM_INSTANCE_ID; + #endif + }; + + PackedVaryingsMeshToPS PackVaryingsMeshToPS (VaryingsMeshToPS input) + { + PackedVaryingsMeshToPS output; + ZERO_INITIALIZE(PackedVaryingsMeshToPS, output); + output.positionCS = input.positionCS; + output.tangentWS.xyzw = input.tangentWS; + output.normalWS.xyz = input.normalWS; + #if UNITY_ANY_INSTANCING_ENABLED + output.instanceID = input.instanceID; + #endif + return output; + } + + VaryingsMeshToPS UnpackVaryingsMeshToPS (PackedVaryingsMeshToPS input) + { + VaryingsMeshToPS output; + output.positionCS = input.positionCS; + output.tangentWS = input.tangentWS.xyzw; + output.normalWS = input.normalWS.xyz; + #if UNITY_ANY_INSTANCING_ENABLED + output.instanceID = input.instanceID; + #endif + return output; + } + + + // -------------------------------------------------- + // Graph + + + // Graph Functions + // GraphFunctions: + + // Graph Vertex + struct VertexDescription + { + float3 Position; + float3 Normal; + float3 Tangent; + }; + + VertexDescription VertexDescriptionFunction(VertexDescriptionInputs IN) + { + VertexDescription description = (VertexDescription)0; + description.Position = IN.ObjectSpacePosition; + description.Normal = IN.ObjectSpaceNormal; + description.Tangent = IN.ObjectSpaceTangent; + return description; + } + + // Graph Pixel + struct SurfaceDescription + { + float3 BaseColor; + float3 Emission; + float Alpha; + float3 BentNormal; + float Smoothness; + float Occlusion; + float3 NormalTS; + float Metallic; + }; + + SurfaceDescription SurfaceDescriptionFunction(SurfaceDescriptionInputs IN) + { + SurfaceDescription surface = (SurfaceDescription)0; + float4 _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4 = _Color; + float _Split_cace9cff304a4c5d84b5305897d09aa9_R_1_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[0]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_G_2_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[1]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_B_3_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[2]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[3]; + surface.BaseColor = (_Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4.xyz); + surface.Emission = float3(0, 0, 0); + surface.Alpha = _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float; + surface.BentNormal = IN.TangentSpaceNormal; + surface.Smoothness = 0.5; + surface.Occlusion = 1; + surface.NormalTS = IN.TangentSpaceNormal; + surface.Metallic = 0; + return surface; + } + + // -------------------------------------------------- + // Build Graph Inputs + #ifdef HAVE_VFX_MODIFICATION + #define VFX_SRP_ATTRIBUTES AttributesMesh + #define VaryingsMeshType VaryingsMeshToPS + #define VFX_SRP_VARYINGS VaryingsMeshType + #define VFX_SRP_SURFACE_INPUTS FragInputs + #endif + + VertexDescriptionInputs AttributesMeshToVertexDescriptionInputs(AttributesMesh input) + { + VertexDescriptionInputs output; + ZERO_INITIALIZE(VertexDescriptionInputs, output); + + output.ObjectSpaceNormal = input.normalOS; + output.ObjectSpaceTangent = input.tangentOS.xyz; + output.ObjectSpacePosition = input.positionOS; + + return output; + } + + VertexDescription GetVertexDescription(AttributesMesh input, float3 timeParameters + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + // build graph inputs + VertexDescriptionInputs vertexDescriptionInputs = AttributesMeshToVertexDescriptionInputs(input); + // Override time parameters with used one (This is required to correctly handle motion vectors for vertex animation based on time) + + // evaluate vertex graph + #ifdef HAVE_VFX_MODIFICATION + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + // Fetch the vertex graph properties for the particle instance. + GetElementVertexProperties(element, properties); + + VertexDescription vertexDescription = VertexDescriptionFunction(vertexDescriptionInputs, properties); + #else + VertexDescription vertexDescription = VertexDescriptionFunction(vertexDescriptionInputs); + #endif + return vertexDescription; + + } + + AttributesMesh ApplyMeshModification(AttributesMesh input, float3 timeParameters + #ifdef USE_CUSTOMINTERP_SUBSTRUCT + #ifdef TESSELLATION_ON + , inout VaryingsMeshToDS varyings + #else + , inout VaryingsMeshToPS varyings + #endif + #endif + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + VertexDescription vertexDescription = GetVertexDescription(input, timeParameters + #ifdef HAVE_VFX_MODIFICATION + , element + #endif + ); + + // copy graph output to the results + input.positionOS = vertexDescription.Position; + input.normalOS = vertexDescription.Normal; + input.tangentOS.xyz = vertexDescription.Tangent; + + + + return input; + } + + #if defined(_ADD_CUSTOM_VELOCITY) // For shader graph custom velocity + // Return precomputed Velocity in object space + float3 GetCustomVelocity(AttributesMesh input + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + VertexDescription vertexDescription = GetVertexDescription(input, _TimeParameters.xyz + #ifdef HAVE_VFX_MODIFICATION + , element + #endif + ); + return vertexDescription.CustomVelocity; + } + #endif + + FragInputs BuildFragInputs(VaryingsMeshToPS input) + { + FragInputs output; + ZERO_INITIALIZE(FragInputs, output); + + // Init to some default value to make the computer quiet (else it output 'divide by zero' warning even if value is not used). + // TODO: this is a really poor workaround, but the variable is used in a bunch of places + // to compute normals which are then passed on elsewhere to compute other values... + output.tangentToWorld = k_identity3x3; + output.positionSS = input.positionCS; // input.positionCS is SV_Position + + output.tangentToWorld = BuildTangentToWorld(input.tangentWS, input.normalWS); + + #ifdef HAVE_VFX_MODIFICATION + // FragInputs from VFX come from two places: Interpolator or CBuffer. + #if VFX_USE_GRAPH_VALUES + uint instanceActiveIndex = asuint(UNITY_ACCESS_INSTANCED_PROP(PerInstance, _InstanceActiveIndex)); + /* WARNING: $splice Could not find named fragment 'VFXLoadGraphValues' */ + #endif + + /* WARNING: $splice Could not find named fragment 'VFXSetFragInputs' */ + + #endif + + // splice point to copy custom interpolator fields from varyings to frag inputs + + + return output; + } + + // existing HDRP code uses the combined function to go directly from packed to frag inputs + FragInputs UnpackVaryingsMeshToFragInputs(PackedVaryingsMeshToPS input) + { + UNITY_SETUP_INSTANCE_ID(input); + #if defined(HAVE_VFX_MODIFICATION) && defined(UNITY_INSTANCING_ENABLED) + unity_InstanceID = input.instanceID; + #endif + VaryingsMeshToPS unpacked = UnpackVaryingsMeshToPS(input); + return BuildFragInputs(unpacked); + } + SurfaceDescriptionInputs FragInputsToSurfaceDescriptionInputs(FragInputs input, float3 viewWS) + { + SurfaceDescriptionInputs output; + ZERO_INITIALIZE(SurfaceDescriptionInputs, output); + + #if defined(SHADER_STAGE_RAY_TRACING) + #else + #endif + output.TangentSpaceNormal = float3(0.0f, 0.0f, 1.0f); + + #if UNITY_UV_STARTS_AT_TOP + #else + #endif + + + + // splice point to copy frag inputs custom interpolator pack into the SDI + + + return output; + } + + // -------------------------------------------------- + // Build Surface Data (Specific Material) + + void ApplyDecalToSurfaceDataNoNormal(DecalSurfaceData decalSurfaceData, inout SurfaceData surfaceData); + + void ApplyDecalAndGetNormal(FragInputs fragInputs, PositionInputs posInput, SurfaceDescription surfaceDescription, + inout SurfaceData surfaceData) + { + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + #ifdef DECAL_NORMAL_BLENDING + // SG nodes don't ouptut surface gradients, so if decals require surf grad blending, we have to convert + // the normal to gradient before applying the decal. We then have to resolve the gradient back to world space + float3 normalTS; + + normalTS = SurfaceGradientFromTangentSpaceNormalAndFromTBN(surfaceDescription.NormalTS, + fragInputs.tangentToWorld[0], fragInputs.tangentToWorld[1]); + + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, fragInputs.tangentToWorld[2], normalTS); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + + GetNormalWS_SG(fragInputs, normalTS, surfaceData.normalWS, doubleSidedConstants); + #else + // normal delivered to master node + GetNormalWS(fragInputs, surfaceDescription.NormalTS, surfaceData.normalWS, doubleSidedConstants); + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + // Both uses and modifies 'surfaceData.normalWS'. + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, surfaceData.normalWS.xyz); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + #endif + } + void BuildSurfaceData(FragInputs fragInputs, inout SurfaceDescription surfaceDescription, float3 V, PositionInputs posInput, out SurfaceData surfaceData, out float3 bentNormalWS) + { + ZERO_INITIALIZE(SurfaceData, surfaceData); + + // specularOcclusion need to be init ahead of decal to quiet the compiler that modify the SurfaceData struct + // however specularOcclusion can come from the graph, so need to be init here so it can be override. + surfaceData.specularOcclusion = 1.0; + + surfaceData.baseColor = surfaceDescription.BaseColor; + surfaceData.perceptualSmoothness = surfaceDescription.Smoothness; + surfaceData.ambientOcclusion = surfaceDescription.Occlusion; + surfaceData.metallic = surfaceDescription.Metallic; + + #if defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE) || defined(_REFRACTION_THIN) + if (_EnableSSRefraction) + { + + surfaceData.transmittanceMask = (1.0 - surfaceDescription.Alpha); + surfaceDescription.Alpha = 1.0; + } + else + { + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + surfaceDescription.Alpha = 1.0; + } + #else + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + #endif + + // These static material feature allow compile time optimization + surfaceData.materialFeatures = MATERIALFEATUREFLAGS_LIT_STANDARD; + #ifdef _MATERIAL_FEATURE_SUBSURFACE_SCATTERING + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING; + #endif + + #ifdef _MATERIAL_FEATURE_TRANSMISSION + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_TRANSMISSION; + #endif + + #ifdef _MATERIAL_FEATURE_ANISOTROPY + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_ANISOTROPY; + + // Initialize the normal to something non-zero to avoid a div-zero warning for anisotropy. + surfaceData.normalWS = float3(0, 1, 0); + #endif + + #ifdef _MATERIAL_FEATURE_IRIDESCENCE + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_IRIDESCENCE; + #endif + + #ifdef _MATERIAL_FEATURE_SPECULAR_COLOR + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR; + #endif + + #ifdef _MATERIAL_FEATURE_CLEAR_COAT + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_CLEAR_COAT; + #endif + + #if defined (_MATERIAL_FEATURE_SPECULAR_COLOR) && defined (_ENERGY_CONSERVING_SPECULAR) + // Require to have setup baseColor + // Reproduce the energy conservation done in legacy Unity. Not ideal but better for compatibility and users can unchek it + surfaceData.baseColor *= (1.0 - Max3(surfaceData.specularColor.r, surfaceData.specularColor.g, surfaceData.specularColor.b)); + #endif + + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + ApplyDecalAndGetNormal(fragInputs, posInput, surfaceDescription, surfaceData); + + surfaceData.geomNormalWS = fragInputs.tangentToWorld[2]; + + surfaceData.tangentWS = normalize(fragInputs.tangentToWorld[0].xyz); // The tangent is not normalize in tangentToWorld for mikkt. TODO: Check if it expected that we normalize with Morten. Tag: SURFACE_GRADIENT + + + bentNormalWS = surfaceData.normalWS; + + surfaceData.tangentWS = Orthonormalize(surfaceData.tangentWS, surfaceData.normalWS); + + #ifdef DEBUG_DISPLAY + if (_DebugMipMapMode != DEBUGMIPMAPMODE_NONE) + { + // TODO: need to update mip info + surfaceData.metallic = 0; + } + + // We need to call ApplyDebugToSurfaceData after filling the surfarcedata and before filling builtinData + // as it can modify attribute use for static lighting + ApplyDebugToSurfaceData(fragInputs.tangentToWorld, surfaceData); + #endif + + // By default we use the ambient occlusion with Tri-ace trick (apply outside) for specular occlusion. + // If user provide bent normal then we process a better term + #if defined(_SPECULAR_OCCLUSION_CUSTOM) + // Just use the value passed through via the slot (not active otherwise) + #elif defined(_SPECULAR_OCCLUSION_FROM_AO_BENT_NORMAL) + // If we have bent normal and ambient occlusion, process a specular occlusion + surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData.normalWS, surfaceData.ambientOcclusion, PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness)); + #elif defined(_AMBIENT_OCCLUSION) && defined(_SPECULAR_OCCLUSION_FROM_AO) + surfaceData.specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(ClampNdotV(dot(surfaceData.normalWS, V)), surfaceData.ambientOcclusion, PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness)); + #endif + + #if defined(_ENABLE_GEOMETRIC_SPECULAR_AA) && !defined(SHADER_STAGE_RAY_TRACING) + surfaceData.perceptualSmoothness = GeometricNormalFiltering(surfaceData.perceptualSmoothness, fragInputs.tangentToWorld[2], surfaceDescription.SpecularAAScreenSpaceVariance, surfaceDescription.SpecularAAThreshold); + #endif + } + + // -------------------------------------------------- + // Get Surface And BuiltinData + + void GetSurfaceAndBuiltinData(FragInputs fragInputs, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData RAY_TRACING_OPTIONAL_PARAMETERS) + { + // 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 + LODDitheringTransition(ComputeFadeMaskSeed(V, posInput.positionSS), unity_LODFade.x); + #endif + #endif + + #ifndef SHADER_UNLIT + #ifdef _DOUBLESIDED_ON + float3 doubleSidedConstants = _DoubleSidedConstants.xyz; + #else + float3 doubleSidedConstants = float3(1.0, 1.0, 1.0); + #endif + + ApplyDoubleSidedFlipOrMirror(fragInputs, doubleSidedConstants); // Apply double sided flip on the vertex normal + #endif // SHADER_UNLIT + + SurfaceDescriptionInputs surfaceDescriptionInputs = FragInputsToSurfaceDescriptionInputs(fragInputs, V); + + #if defined(HAVE_VFX_MODIFICATION) + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + GetElementPixelProperties(fragInputs, properties); + + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs, properties); + #else + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs); + #endif + + // Perform alpha test very early to save performance (a killed pixel will not sample textures) + // TODO: split graph evaluation to grab just alpha dependencies first? tricky.. + #ifdef _ALPHATEST_ON + float alphaCutoff = surfaceDescription.AlphaClipThreshold; + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + // The TransparentDepthPrepass is also used with SSR transparent. + // If an artists enable transaprent SSR but not the TransparentDepthPrepass itself, then we use AlphaClipThreshold + // otherwise if TransparentDepthPrepass is enabled we use AlphaClipThresholdDepthPrepass + #elif SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_POSTPASS + // DepthPostpass always use its own alpha threshold + alphaCutoff = surfaceDescription.AlphaClipThresholdDepthPostpass; + #elif (SHADERPASS == SHADERPASS_SHADOWS) || (SHADERPASS == SHADERPASS_RAYTRACING_VISIBILITY) + // If use shadow threshold isn't enable we don't allow any test + #endif + + GENERIC_ALPHA_TEST(surfaceDescription.Alpha, alphaCutoff); + #endif + + #if !defined(SHADER_STAGE_RAY_TRACING) && _DEPTHOFFSET_ON + ApplyDepthOffsetPositionInput(V, surfaceDescription.DepthOffset, GetViewForwardDir(), GetWorldToHClipMatrix(), posInput); + #endif + + #ifndef SHADER_UNLIT + float3 bentNormalWS; + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData, bentNormalWS); + + #ifdef FRAG_INPUTS_USE_TEXCOORD1 + float4 lightmapTexCoord1 = fragInputs.texCoord1; + #else + float4 lightmapTexCoord1 = float4(0,0,0,0); + #endif + + #ifdef FRAG_INPUTS_USE_TEXCOORD2 + float4 lightmapTexCoord2 = fragInputs.texCoord2; + #else + float4 lightmapTexCoord2 = float4(0,0,0,0); + #endif + + // Builtin Data + // For back lighting we use the oposite vertex normal + InitBuiltinData(posInput, surfaceDescription.Alpha, bentNormalWS, -fragInputs.tangentToWorld[2], lightmapTexCoord1, lightmapTexCoord2, builtinData); + + #else + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData); + + ZERO_BUILTIN_INITIALIZE(builtinData); // No call to InitBuiltinData as we don't have any lighting + builtinData.opacity = surfaceDescription.Alpha; + + #if defined(DEBUG_DISPLAY) + // Light Layers are currently not used for the Unlit shader (because it is not lit) + // But Unlit objects do cast shadows according to their rendering layer mask, which is what we want to + // display in the light layers visualization mode, therefore we need the renderingLayers + builtinData.renderingLayers = GetMeshRenderingLightLayer(); + #endif + + #endif // SHADER_UNLIT + + #ifdef _ALPHATEST_ON + // Used for sharpening by alpha to mask - Alpha to covertage is only used with depth only and forward pass (no shadow pass, no transparent pass) + builtinData.alphaClipTreshold = alphaCutoff; + #endif + + // override sampleBakedGI - not used by Unlit + + builtinData.emissiveColor = surfaceDescription.Emission; + + // Note this will not fully work on transparent surfaces (can check with _SURFACE_TYPE_TRANSPARENT define) + // We will always overwrite vt feeback with the nearest. So behind transparent surfaces vt will not be resolved + // This is a limitation of the current MRT approach. + #ifdef UNITY_VIRTUAL_TEXTURING + #endif + + #if _DEPTHOFFSET_ON + builtinData.depthOffset = surfaceDescription.DepthOffset; + #endif + + // TODO: We should generate distortion / distortionBlur for non distortion pass + #if (SHADERPASS == SHADERPASS_DISTORTION) + builtinData.distortion = surfaceDescription.Distortion; + builtinData.distortionBlur = surfaceDescription.DistortionBlur; + #endif + + #ifndef SHADER_UNLIT + // PostInitBuiltinData call ApplyDebugToBuiltinData + PostInitBuiltinData(V, posInput, surfaceData, builtinData); + #else + ApplyDebugToBuiltinData(builtinData); + #endif + + RAY_TRACING_OPTIONAL_ALPHA_TEST_PASS + } + + // -------------------------------------------------- + // Main + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassDepthOnly.hlsl" + + // -------------------------------------------------- + // Visual Effect Vertex Invocations + + #ifdef HAVE_VFX_MODIFICATION + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/VisualEffectVertex.hlsl" + #endif + + ENDHLSL + } + Pass + { + Name "SceneSelectionPass" + Tags + { + "LightMode" = "SceneSelectionPass" + } + + // Render State + Cull Off + + // Debug + // + + // -------------------------------------------------- + // Pass + + HLSLPROGRAM + + // Pragmas + #pragma multi_compile _ DOTS_INSTANCING_ON + #pragma editor_sync_compilation + #pragma instancing_options renderinglayer + #pragma target 4.5 + #pragma vertex Vert + #pragma fragment Frag + #pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch + #pragma multi_compile_instancing + + // Keywords + #pragma shader_feature _ _SURFACE_TYPE_TRANSPARENT + #pragma shader_feature_local _ _DOUBLESIDED_ON + #pragma shader_feature_local _ _ADD_PRECOMPUTED_VELOCITY + #pragma shader_feature_local _ _TRANSPARENT_WRITES_MOTION_VEC + #pragma shader_feature_local_fragment _ _ENABLE_FOG_ON_TRANSPARENT + #pragma shader_feature_local_fragment _ _DISABLE_DECALS + #pragma shader_feature_local_raytracing _ _DISABLE_DECALS + #pragma shader_feature_local_fragment _ _DISABLE_SSR + #pragma shader_feature_local_raytracing _ _DISABLE_SSR + #pragma shader_feature_local_fragment _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local_raytracing _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local _ _REFRACTION_PLANE _REFRACTION_SPHERE _REFRACTION_THIN + // GraphKeywords: + + // For custom interpolators to inject a substruct definition before FragInputs definition, + // allowing for FragInputs to capture CI's intended for ShaderGraph's SDI. + struct CustomInterpolators + { + }; + #define USE_CUSTOMINTERP_SUBSTRUCT + + + + // TODO: Merge FragInputsVFX substruct with CustomInterpolators. + #ifdef HAVE_VFX_MODIFICATION + struct FragInputsVFX + { + /* WARNING: $splice Could not find named fragment 'FragInputsVFX' */ + }; + #endif + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl" // Required by Tessellation.hlsl + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Tessellation.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Texture.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl" // Required to be include before we include properties as it define DECLARE_STACK_CB + // Always include Shader Graph version + // Always include last to avoid double macros + #include "Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl" // Need to be here for Gradient struct definition + + // -------------------------------------------------- + // Defines + + // Attribute + #define ATTRIBUTES_NEED_NORMAL + #define ATTRIBUTES_NEED_TANGENT + + #define HAVE_MESH_MODIFICATION + + //Strip down the FragInputs.hlsl (on graphics), so we can only optimize the interpolators we use. + //if by accident something requests contents of FragInputs.hlsl, it will be caught as a compiler error + //Frag inputs stripping is only enabled when FRAG_INPUTS_ENABLE_STRIPPING is set + #if !defined(SHADER_STAGE_RAY_TRACING) && SHADERPASS != SHADERPASS_RAYTRACING_GBUFFER && SHADERPASS != SHADERPASS_FULL_SCREEN_DEBUG + #define FRAG_INPUTS_ENABLE_STRIPPING + #endif + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl" + + + + #define SHADERPASS SHADERPASS_DEPTH_ONLY + #define RAYTRACING_SHADER_GRAPH_DEFAULT + #define SCENESELECTIONPASS 1 + + + // Following two define are a workaround introduce in 10.1.x for RaytracingQualityNode + // The ShaderGraph don't support correctly migration of this node as it serialize all the node data + // in the json file making it impossible to uprgrade. Until we get a fix, we do a workaround here + // to still allow us to rename the field and keyword of this node without breaking existing code. + #ifdef RAYTRACING_SHADER_GRAPH_DEFAULT + #define RAYTRACING_SHADER_GRAPH_HIGH + #endif + + #ifdef RAYTRACING_SHADER_GRAPH_RAYTRACED + #define RAYTRACING_SHADER_GRAPH_LOW + #endif + // end + + #ifndef SHADER_UNLIT + // We need isFrontFace when using double sided - it is not required for unlit as in case of unlit double sided only drive the cullmode + // VARYINGS_NEED_CULLFACE can be define by VaryingsMeshToPS.FaceSign input if a IsFrontFace Node is included in the shader graph. + #if defined(_DOUBLESIDED_ON) && !defined(VARYINGS_NEED_CULLFACE) + #define VARYINGS_NEED_CULLFACE + #endif + #endif + + // Specific Material Define + #define _SPECULAR_OCCLUSION_FROM_AO 1 + #define _ENERGY_CONSERVING_SPECULAR 1 + + // If we use subsurface scattering, enable output split lighting (for forward pass) + #if defined(_MATERIAL_FEATURE_SUBSURFACE_SCATTERING) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define OUTPUT_SPLIT_LIGHTING + #endif + + // This shader support recursive rendering for raytracing + #define HAVE_RECURSIVE_RENDERING + + // In Path Tracing, For all single-sided, refractive materials, we want to force a thin refraction model + #if (SHADERPASS == SHADERPASS_PATH_TRACING) && !defined(_DOUBLESIDED_ON) && (defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE)) + #undef _REFRACTION_PLANE + #undef _REFRACTION_SPHERE + #define _REFRACTION_THIN + #endif + // Caution: we can use the define SHADER_UNLIT onlit after the above Material include as it is the Unlit template who define it + + // To handle SSR on transparent correctly with a possibility to enable/disable it per framesettings + // we should have a code like this: + // if !defined(_DISABLE_SSR_TRANSPARENT) + // pragma multi_compile _ WRITE_NORMAL_BUFFER + // endif + // i.e we enable the multicompile only if we can receive SSR or not, and then C# code drive + // it based on if SSR transparent in frame settings and not (and stripper can strip it). + // this is currently not possible with our current preprocessor as _DISABLE_SSR_TRANSPARENT is a keyword not a define + // so instead we used this and chose to pay the extra cost of normal write even if SSR transaprent is disabled. + // Ideally the shader graph generator should handle it but condition below can't be handle correctly for now. + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + #if !defined(_DISABLE_SSR_TRANSPARENT) && !defined(SHADER_UNLIT) + #define WRITE_NORMAL_BUFFER + #endif + #endif + + #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) + // Don't do it with debug display mode as it is possible there is no depth prepass in this case + #if !defined(_SURFACE_TYPE_TRANSPARENT) + #if SHADERPASS == SHADERPASS_FORWARD + #define SHADERPASS_FORWARD_BYPASS_ALPHA_TEST + #elif SHADERPASS == SHADERPASS_GBUFFER + #define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST + #endif + #endif + #endif + + // Define _DEFERRED_CAPABLE_MATERIAL for shader capable to run in deferred pass + #if defined(SHADER_LIT) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define _DEFERRED_CAPABLE_MATERIAL + #endif + + // Translate transparent motion vector define + #if defined(_TRANSPARENT_WRITES_MOTION_VEC) && defined(_SURFACE_TYPE_TRANSPARENT) + #define _WRITE_TRANSPARENT_MOTION_VECTOR + #endif + + // -- Graph Properties + CBUFFER_START(UnityPerMaterial) + float4 _Color; + float4 _EmissionColor; + float _UseShadowThreshold; + float4 _DoubleSidedConstants; + float _BlendMode; + float _EnableBlendModePreserveSpecularLighting; + float _RayTracing; + float _RefractionModel; + CBUFFER_END + + + // Object and Global properties + + // -- Property used by ScenePickingPass + #ifdef SCENEPICKINGPASS + float4 _SelectionID; + #endif + + // -- Properties used by SceneSelectionPass + #ifdef SCENESELECTIONPASS + int _ObjectId; + int _PassValue; + #endif + + // Includes + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/PickingSpaceTransforms.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugDisplay.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/NormalSurfaceGradient.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/Lit.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/BuiltinUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/MaterialUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Decal/DecalUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitDecalData.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderGraphFunctions.hlsl" + // GraphIncludes: + + // -------------------------------------------------- + // Structs and Packing + + struct AttributesMesh + { + float3 positionOS : POSITION; + float3 normalOS : NORMAL; + float4 tangentOS : TANGENT; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : INSTANCEID_SEMANTIC; + #endif + }; + struct VaryingsMeshToPS + { + SV_POSITION_QUALIFIERS float4 positionCS : SV_POSITION; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : CUSTOM_INSTANCE_ID; + #endif + }; + struct VertexDescriptionInputs + { + float3 ObjectSpaceNormal; + float3 ObjectSpaceTangent; + float3 ObjectSpacePosition; + }; + struct SurfaceDescriptionInputs + { + float3 TangentSpaceNormal; + }; + struct PackedVaryingsMeshToPS + { + SV_POSITION_QUALIFIERS float4 positionCS : SV_POSITION; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : CUSTOM_INSTANCE_ID; + #endif + }; + + PackedVaryingsMeshToPS PackVaryingsMeshToPS (VaryingsMeshToPS input) + { + PackedVaryingsMeshToPS output; + ZERO_INITIALIZE(PackedVaryingsMeshToPS, output); + output.positionCS = input.positionCS; + #if UNITY_ANY_INSTANCING_ENABLED + output.instanceID = input.instanceID; + #endif + return output; + } + + VaryingsMeshToPS UnpackVaryingsMeshToPS (PackedVaryingsMeshToPS input) + { + VaryingsMeshToPS output; + output.positionCS = input.positionCS; + #if UNITY_ANY_INSTANCING_ENABLED + output.instanceID = input.instanceID; + #endif + return output; + } + + + // -------------------------------------------------- + // Graph + + + // Graph Functions + // GraphFunctions: + + // Graph Vertex + struct VertexDescription + { + float3 Position; + float3 Normal; + float3 Tangent; + }; + + VertexDescription VertexDescriptionFunction(VertexDescriptionInputs IN) + { + VertexDescription description = (VertexDescription)0; + description.Position = IN.ObjectSpacePosition; + description.Normal = IN.ObjectSpaceNormal; + description.Tangent = IN.ObjectSpaceTangent; + return description; + } + + // Graph Pixel + struct SurfaceDescription + { + float3 BaseColor; + float3 Emission; + float Alpha; + float3 BentNormal; + float Smoothness; + float Occlusion; + float3 NormalTS; + float Metallic; + }; + + SurfaceDescription SurfaceDescriptionFunction(SurfaceDescriptionInputs IN) + { + SurfaceDescription surface = (SurfaceDescription)0; + float4 _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4 = _Color; + float _Split_cace9cff304a4c5d84b5305897d09aa9_R_1_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[0]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_G_2_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[1]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_B_3_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[2]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[3]; + surface.BaseColor = (_Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4.xyz); + surface.Emission = float3(0, 0, 0); + surface.Alpha = _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float; + surface.BentNormal = IN.TangentSpaceNormal; + surface.Smoothness = 0.5; + surface.Occlusion = 1; + surface.NormalTS = IN.TangentSpaceNormal; + surface.Metallic = 0; + return surface; + } + + // -------------------------------------------------- + // Build Graph Inputs + #ifdef HAVE_VFX_MODIFICATION + #define VFX_SRP_ATTRIBUTES AttributesMesh + #define VaryingsMeshType VaryingsMeshToPS + #define VFX_SRP_VARYINGS VaryingsMeshType + #define VFX_SRP_SURFACE_INPUTS FragInputs + #endif + + VertexDescriptionInputs AttributesMeshToVertexDescriptionInputs(AttributesMesh input) + { + VertexDescriptionInputs output; + ZERO_INITIALIZE(VertexDescriptionInputs, output); + + output.ObjectSpaceNormal = input.normalOS; + output.ObjectSpaceTangent = input.tangentOS.xyz; + output.ObjectSpacePosition = input.positionOS; + + return output; + } + + VertexDescription GetVertexDescription(AttributesMesh input, float3 timeParameters + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + // build graph inputs + VertexDescriptionInputs vertexDescriptionInputs = AttributesMeshToVertexDescriptionInputs(input); + // Override time parameters with used one (This is required to correctly handle motion vectors for vertex animation based on time) + + // evaluate vertex graph + #ifdef HAVE_VFX_MODIFICATION + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + // Fetch the vertex graph properties for the particle instance. + GetElementVertexProperties(element, properties); + + VertexDescription vertexDescription = VertexDescriptionFunction(vertexDescriptionInputs, properties); + #else + VertexDescription vertexDescription = VertexDescriptionFunction(vertexDescriptionInputs); + #endif + return vertexDescription; + + } + + AttributesMesh ApplyMeshModification(AttributesMesh input, float3 timeParameters + #ifdef USE_CUSTOMINTERP_SUBSTRUCT + #ifdef TESSELLATION_ON + , inout VaryingsMeshToDS varyings + #else + , inout VaryingsMeshToPS varyings + #endif + #endif + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + VertexDescription vertexDescription = GetVertexDescription(input, timeParameters + #ifdef HAVE_VFX_MODIFICATION + , element + #endif + ); + + // copy graph output to the results + input.positionOS = vertexDescription.Position; + input.normalOS = vertexDescription.Normal; + input.tangentOS.xyz = vertexDescription.Tangent; + + + + return input; + } + + #if defined(_ADD_CUSTOM_VELOCITY) // For shader graph custom velocity + // Return precomputed Velocity in object space + float3 GetCustomVelocity(AttributesMesh input + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + VertexDescription vertexDescription = GetVertexDescription(input, _TimeParameters.xyz + #ifdef HAVE_VFX_MODIFICATION + , element + #endif + ); + return vertexDescription.CustomVelocity; + } + #endif + + FragInputs BuildFragInputs(VaryingsMeshToPS input) + { + FragInputs output; + ZERO_INITIALIZE(FragInputs, output); + + // Init to some default value to make the computer quiet (else it output 'divide by zero' warning even if value is not used). + // TODO: this is a really poor workaround, but the variable is used in a bunch of places + // to compute normals which are then passed on elsewhere to compute other values... + output.tangentToWorld = k_identity3x3; + output.positionSS = input.positionCS; // input.positionCS is SV_Position + + + #ifdef HAVE_VFX_MODIFICATION + // FragInputs from VFX come from two places: Interpolator or CBuffer. + #if VFX_USE_GRAPH_VALUES + uint instanceActiveIndex = asuint(UNITY_ACCESS_INSTANCED_PROP(PerInstance, _InstanceActiveIndex)); + /* WARNING: $splice Could not find named fragment 'VFXLoadGraphValues' */ + #endif + + /* WARNING: $splice Could not find named fragment 'VFXSetFragInputs' */ + + #endif + + // splice point to copy custom interpolator fields from varyings to frag inputs + + + return output; + } + + // existing HDRP code uses the combined function to go directly from packed to frag inputs + FragInputs UnpackVaryingsMeshToFragInputs(PackedVaryingsMeshToPS input) + { + UNITY_SETUP_INSTANCE_ID(input); + #if defined(HAVE_VFX_MODIFICATION) && defined(UNITY_INSTANCING_ENABLED) + unity_InstanceID = input.instanceID; + #endif + VaryingsMeshToPS unpacked = UnpackVaryingsMeshToPS(input); + return BuildFragInputs(unpacked); + } + SurfaceDescriptionInputs FragInputsToSurfaceDescriptionInputs(FragInputs input, float3 viewWS) + { + SurfaceDescriptionInputs output; + ZERO_INITIALIZE(SurfaceDescriptionInputs, output); + + #if defined(SHADER_STAGE_RAY_TRACING) + #else + #endif + output.TangentSpaceNormal = float3(0.0f, 0.0f, 1.0f); + + #if UNITY_UV_STARTS_AT_TOP + #else + #endif + + + + // splice point to copy frag inputs custom interpolator pack into the SDI + + + return output; + } + + // -------------------------------------------------- + // Build Surface Data (Specific Material) + + void ApplyDecalToSurfaceDataNoNormal(DecalSurfaceData decalSurfaceData, inout SurfaceData surfaceData); + + void ApplyDecalAndGetNormal(FragInputs fragInputs, PositionInputs posInput, SurfaceDescription surfaceDescription, + inout SurfaceData surfaceData) + { + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + #ifdef DECAL_NORMAL_BLENDING + // SG nodes don't ouptut surface gradients, so if decals require surf grad blending, we have to convert + // the normal to gradient before applying the decal. We then have to resolve the gradient back to world space + float3 normalTS; + + normalTS = SurfaceGradientFromTangentSpaceNormalAndFromTBN(surfaceDescription.NormalTS, + fragInputs.tangentToWorld[0], fragInputs.tangentToWorld[1]); + + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, fragInputs.tangentToWorld[2], normalTS); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + + GetNormalWS_SG(fragInputs, normalTS, surfaceData.normalWS, doubleSidedConstants); + #else + // normal delivered to master node + GetNormalWS(fragInputs, surfaceDescription.NormalTS, surfaceData.normalWS, doubleSidedConstants); + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + // Both uses and modifies 'surfaceData.normalWS'. + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, surfaceData.normalWS.xyz); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + #endif + } + void BuildSurfaceData(FragInputs fragInputs, inout SurfaceDescription surfaceDescription, float3 V, PositionInputs posInput, out SurfaceData surfaceData, out float3 bentNormalWS) + { + ZERO_INITIALIZE(SurfaceData, surfaceData); + + // specularOcclusion need to be init ahead of decal to quiet the compiler that modify the SurfaceData struct + // however specularOcclusion can come from the graph, so need to be init here so it can be override. + surfaceData.specularOcclusion = 1.0; + + surfaceData.baseColor = surfaceDescription.BaseColor; + surfaceData.perceptualSmoothness = surfaceDescription.Smoothness; + surfaceData.ambientOcclusion = surfaceDescription.Occlusion; + surfaceData.metallic = surfaceDescription.Metallic; + + #if defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE) || defined(_REFRACTION_THIN) + if (_EnableSSRefraction) + { + + surfaceData.transmittanceMask = (1.0 - surfaceDescription.Alpha); + surfaceDescription.Alpha = 1.0; + } + else + { + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + surfaceDescription.Alpha = 1.0; + } + #else + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + #endif + + // These static material feature allow compile time optimization + surfaceData.materialFeatures = MATERIALFEATUREFLAGS_LIT_STANDARD; + #ifdef _MATERIAL_FEATURE_SUBSURFACE_SCATTERING + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING; + #endif + + #ifdef _MATERIAL_FEATURE_TRANSMISSION + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_TRANSMISSION; + #endif + + #ifdef _MATERIAL_FEATURE_ANISOTROPY + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_ANISOTROPY; + + // Initialize the normal to something non-zero to avoid a div-zero warning for anisotropy. + surfaceData.normalWS = float3(0, 1, 0); + #endif + + #ifdef _MATERIAL_FEATURE_IRIDESCENCE + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_IRIDESCENCE; + #endif + + #ifdef _MATERIAL_FEATURE_SPECULAR_COLOR + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR; + #endif + + #ifdef _MATERIAL_FEATURE_CLEAR_COAT + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_CLEAR_COAT; + #endif + + #if defined (_MATERIAL_FEATURE_SPECULAR_COLOR) && defined (_ENERGY_CONSERVING_SPECULAR) + // Require to have setup baseColor + // Reproduce the energy conservation done in legacy Unity. Not ideal but better for compatibility and users can unchek it + surfaceData.baseColor *= (1.0 - Max3(surfaceData.specularColor.r, surfaceData.specularColor.g, surfaceData.specularColor.b)); + #endif + + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + ApplyDecalAndGetNormal(fragInputs, posInput, surfaceDescription, surfaceData); + + surfaceData.geomNormalWS = fragInputs.tangentToWorld[2]; + + surfaceData.tangentWS = normalize(fragInputs.tangentToWorld[0].xyz); // The tangent is not normalize in tangentToWorld for mikkt. TODO: Check if it expected that we normalize with Morten. Tag: SURFACE_GRADIENT + + + bentNormalWS = surfaceData.normalWS; + + surfaceData.tangentWS = Orthonormalize(surfaceData.tangentWS, surfaceData.normalWS); + + #ifdef DEBUG_DISPLAY + if (_DebugMipMapMode != DEBUGMIPMAPMODE_NONE) + { + // TODO: need to update mip info + surfaceData.metallic = 0; + } + + // We need to call ApplyDebugToSurfaceData after filling the surfarcedata and before filling builtinData + // as it can modify attribute use for static lighting + ApplyDebugToSurfaceData(fragInputs.tangentToWorld, surfaceData); + #endif + + // By default we use the ambient occlusion with Tri-ace trick (apply outside) for specular occlusion. + // If user provide bent normal then we process a better term + #if defined(_SPECULAR_OCCLUSION_CUSTOM) + // Just use the value passed through via the slot (not active otherwise) + #elif defined(_SPECULAR_OCCLUSION_FROM_AO_BENT_NORMAL) + // If we have bent normal and ambient occlusion, process a specular occlusion + surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData.normalWS, surfaceData.ambientOcclusion, PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness)); + #elif defined(_AMBIENT_OCCLUSION) && defined(_SPECULAR_OCCLUSION_FROM_AO) + surfaceData.specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(ClampNdotV(dot(surfaceData.normalWS, V)), surfaceData.ambientOcclusion, PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness)); + #endif + + #if defined(_ENABLE_GEOMETRIC_SPECULAR_AA) && !defined(SHADER_STAGE_RAY_TRACING) + surfaceData.perceptualSmoothness = GeometricNormalFiltering(surfaceData.perceptualSmoothness, fragInputs.tangentToWorld[2], surfaceDescription.SpecularAAScreenSpaceVariance, surfaceDescription.SpecularAAThreshold); + #endif + } + + // -------------------------------------------------- + // Get Surface And BuiltinData + + void GetSurfaceAndBuiltinData(FragInputs fragInputs, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData RAY_TRACING_OPTIONAL_PARAMETERS) + { + // 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 + LODDitheringTransition(ComputeFadeMaskSeed(V, posInput.positionSS), unity_LODFade.x); + #endif + #endif + + #ifndef SHADER_UNLIT + #ifdef _DOUBLESIDED_ON + float3 doubleSidedConstants = _DoubleSidedConstants.xyz; + #else + float3 doubleSidedConstants = float3(1.0, 1.0, 1.0); + #endif + + ApplyDoubleSidedFlipOrMirror(fragInputs, doubleSidedConstants); // Apply double sided flip on the vertex normal + #endif // SHADER_UNLIT + + SurfaceDescriptionInputs surfaceDescriptionInputs = FragInputsToSurfaceDescriptionInputs(fragInputs, V); + + #if defined(HAVE_VFX_MODIFICATION) + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + GetElementPixelProperties(fragInputs, properties); + + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs, properties); + #else + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs); + #endif + + // Perform alpha test very early to save performance (a killed pixel will not sample textures) + // TODO: split graph evaluation to grab just alpha dependencies first? tricky.. + #ifdef _ALPHATEST_ON + float alphaCutoff = surfaceDescription.AlphaClipThreshold; + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + // The TransparentDepthPrepass is also used with SSR transparent. + // If an artists enable transaprent SSR but not the TransparentDepthPrepass itself, then we use AlphaClipThreshold + // otherwise if TransparentDepthPrepass is enabled we use AlphaClipThresholdDepthPrepass + #elif SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_POSTPASS + // DepthPostpass always use its own alpha threshold + alphaCutoff = surfaceDescription.AlphaClipThresholdDepthPostpass; + #elif (SHADERPASS == SHADERPASS_SHADOWS) || (SHADERPASS == SHADERPASS_RAYTRACING_VISIBILITY) + // If use shadow threshold isn't enable we don't allow any test + #endif + + GENERIC_ALPHA_TEST(surfaceDescription.Alpha, alphaCutoff); + #endif + + #if !defined(SHADER_STAGE_RAY_TRACING) && _DEPTHOFFSET_ON + ApplyDepthOffsetPositionInput(V, surfaceDescription.DepthOffset, GetViewForwardDir(), GetWorldToHClipMatrix(), posInput); + #endif + + #ifndef SHADER_UNLIT + float3 bentNormalWS; + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData, bentNormalWS); + + #ifdef FRAG_INPUTS_USE_TEXCOORD1 + float4 lightmapTexCoord1 = fragInputs.texCoord1; + #else + float4 lightmapTexCoord1 = float4(0,0,0,0); + #endif + + #ifdef FRAG_INPUTS_USE_TEXCOORD2 + float4 lightmapTexCoord2 = fragInputs.texCoord2; + #else + float4 lightmapTexCoord2 = float4(0,0,0,0); + #endif + + // Builtin Data + // For back lighting we use the oposite vertex normal + InitBuiltinData(posInput, surfaceDescription.Alpha, bentNormalWS, -fragInputs.tangentToWorld[2], lightmapTexCoord1, lightmapTexCoord2, builtinData); + + #else + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData); + + ZERO_BUILTIN_INITIALIZE(builtinData); // No call to InitBuiltinData as we don't have any lighting + builtinData.opacity = surfaceDescription.Alpha; + + #if defined(DEBUG_DISPLAY) + // Light Layers are currently not used for the Unlit shader (because it is not lit) + // But Unlit objects do cast shadows according to their rendering layer mask, which is what we want to + // display in the light layers visualization mode, therefore we need the renderingLayers + builtinData.renderingLayers = GetMeshRenderingLightLayer(); + #endif + + #endif // SHADER_UNLIT + + #ifdef _ALPHATEST_ON + // Used for sharpening by alpha to mask - Alpha to covertage is only used with depth only and forward pass (no shadow pass, no transparent pass) + builtinData.alphaClipTreshold = alphaCutoff; + #endif + + // override sampleBakedGI - not used by Unlit + + builtinData.emissiveColor = surfaceDescription.Emission; + + // Note this will not fully work on transparent surfaces (can check with _SURFACE_TYPE_TRANSPARENT define) + // We will always overwrite vt feeback with the nearest. So behind transparent surfaces vt will not be resolved + // This is a limitation of the current MRT approach. + #ifdef UNITY_VIRTUAL_TEXTURING + #endif + + #if _DEPTHOFFSET_ON + builtinData.depthOffset = surfaceDescription.DepthOffset; + #endif + + // TODO: We should generate distortion / distortionBlur for non distortion pass + #if (SHADERPASS == SHADERPASS_DISTORTION) + builtinData.distortion = surfaceDescription.Distortion; + builtinData.distortionBlur = surfaceDescription.DistortionBlur; + #endif + + #ifndef SHADER_UNLIT + // PostInitBuiltinData call ApplyDebugToBuiltinData + PostInitBuiltinData(V, posInput, surfaceData, builtinData); + #else + ApplyDebugToBuiltinData(builtinData); + #endif + + RAY_TRACING_OPTIONAL_ALPHA_TEST_PASS + } + + // -------------------------------------------------- + // Main + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassDepthOnly.hlsl" + + // -------------------------------------------------- + // Visual Effect Vertex Invocations + + #ifdef HAVE_VFX_MODIFICATION + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/VisualEffectVertex.hlsl" + #endif + + ENDHLSL + } + Pass + { + Name "MotionVectors" + Tags + { + "LightMode" = "MotionVectors" + } + + // Render State + Cull [_CullMode] + ZWrite On + Stencil + { + WriteMask [_StencilWriteMaskMV] + Ref [_StencilRefMV] + CompFront Always + PassFront Replace + CompBack Always + PassBack Replace + } + + // Debug + // + + // -------------------------------------------------- + // Pass + + HLSLPROGRAM + + // Pragmas + #pragma multi_compile _ DOTS_INSTANCING_ON + #pragma instancing_options renderinglayer + #pragma target 4.5 + #pragma vertex Vert + #pragma fragment Frag + #pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch + #pragma multi_compile_instancing + + // Keywords + #pragma multi_compile_fragment _ WRITE_MSAA_DEPTH + #pragma shader_feature _ _SURFACE_TYPE_TRANSPARENT + #pragma shader_feature_local _ _DOUBLESIDED_ON + #pragma shader_feature_local _ _ADD_PRECOMPUTED_VELOCITY + #pragma shader_feature_local _ _TRANSPARENT_WRITES_MOTION_VEC + #pragma shader_feature_local_fragment _ _ENABLE_FOG_ON_TRANSPARENT + #pragma multi_compile _ WRITE_NORMAL_BUFFER + #pragma shader_feature_local_fragment _ _DISABLE_DECALS + #pragma shader_feature_local_raytracing _ _DISABLE_DECALS + #pragma shader_feature_local_fragment _ _DISABLE_SSR + #pragma shader_feature_local_raytracing _ _DISABLE_SSR + #pragma shader_feature_local_fragment _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local_raytracing _ _DISABLE_SSR_TRANSPARENT + #pragma multi_compile _ WRITE_DECAL_BUFFER + #pragma shader_feature_local _ _REFRACTION_PLANE _REFRACTION_SPHERE _REFRACTION_THIN + // GraphKeywords: + + // For custom interpolators to inject a substruct definition before FragInputs definition, + // allowing for FragInputs to capture CI's intended for ShaderGraph's SDI. + struct CustomInterpolators + { + }; + #define USE_CUSTOMINTERP_SUBSTRUCT + + + + // TODO: Merge FragInputsVFX substruct with CustomInterpolators. + #ifdef HAVE_VFX_MODIFICATION + struct FragInputsVFX + { + /* WARNING: $splice Could not find named fragment 'FragInputsVFX' */ + }; + #endif + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl" // Required by Tessellation.hlsl + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Tessellation.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Texture.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl" // Required to be include before we include properties as it define DECLARE_STACK_CB + // Always include Shader Graph version + // Always include last to avoid double macros + #include "Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl" // Need to be here for Gradient struct definition + + // -------------------------------------------------- + // Defines + + // Attribute + #define ATTRIBUTES_NEED_NORMAL + #define ATTRIBUTES_NEED_TANGENT + #define VARYINGS_NEED_POSITION_WS + #define VARYINGS_NEED_TANGENT_TO_WORLD + + #define HAVE_MESH_MODIFICATION + + //Strip down the FragInputs.hlsl (on graphics), so we can only optimize the interpolators we use. + //if by accident something requests contents of FragInputs.hlsl, it will be caught as a compiler error + //Frag inputs stripping is only enabled when FRAG_INPUTS_ENABLE_STRIPPING is set + #if !defined(SHADER_STAGE_RAY_TRACING) && SHADERPASS != SHADERPASS_RAYTRACING_GBUFFER && SHADERPASS != SHADERPASS_FULL_SCREEN_DEBUG + #define FRAG_INPUTS_ENABLE_STRIPPING + #endif + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl" + + + + #define SHADERPASS SHADERPASS_MOTION_VECTORS + + + // Following two define are a workaround introduce in 10.1.x for RaytracingQualityNode + // The ShaderGraph don't support correctly migration of this node as it serialize all the node data + // in the json file making it impossible to uprgrade. Until we get a fix, we do a workaround here + // to still allow us to rename the field and keyword of this node without breaking existing code. + #ifdef RAYTRACING_SHADER_GRAPH_DEFAULT + #define RAYTRACING_SHADER_GRAPH_HIGH + #endif + + #ifdef RAYTRACING_SHADER_GRAPH_RAYTRACED + #define RAYTRACING_SHADER_GRAPH_LOW + #endif + // end + + #ifndef SHADER_UNLIT + // We need isFrontFace when using double sided - it is not required for unlit as in case of unlit double sided only drive the cullmode + // VARYINGS_NEED_CULLFACE can be define by VaryingsMeshToPS.FaceSign input if a IsFrontFace Node is included in the shader graph. + #if defined(_DOUBLESIDED_ON) && !defined(VARYINGS_NEED_CULLFACE) + #define VARYINGS_NEED_CULLFACE + #endif + #endif + + // Specific Material Define + #define _SPECULAR_OCCLUSION_FROM_AO 1 + #define _ENERGY_CONSERVING_SPECULAR 1 + + // If we use subsurface scattering, enable output split lighting (for forward pass) + #if defined(_MATERIAL_FEATURE_SUBSURFACE_SCATTERING) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define OUTPUT_SPLIT_LIGHTING + #endif + + // This shader support recursive rendering for raytracing + #define HAVE_RECURSIVE_RENDERING + + // In Path Tracing, For all single-sided, refractive materials, we want to force a thin refraction model + #if (SHADERPASS == SHADERPASS_PATH_TRACING) && !defined(_DOUBLESIDED_ON) && (defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE)) + #undef _REFRACTION_PLANE + #undef _REFRACTION_SPHERE + #define _REFRACTION_THIN + #endif + // Caution: we can use the define SHADER_UNLIT onlit after the above Material include as it is the Unlit template who define it + + // To handle SSR on transparent correctly with a possibility to enable/disable it per framesettings + // we should have a code like this: + // if !defined(_DISABLE_SSR_TRANSPARENT) + // pragma multi_compile _ WRITE_NORMAL_BUFFER + // endif + // i.e we enable the multicompile only if we can receive SSR or not, and then C# code drive + // it based on if SSR transparent in frame settings and not (and stripper can strip it). + // this is currently not possible with our current preprocessor as _DISABLE_SSR_TRANSPARENT is a keyword not a define + // so instead we used this and chose to pay the extra cost of normal write even if SSR transaprent is disabled. + // Ideally the shader graph generator should handle it but condition below can't be handle correctly for now. + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + #if !defined(_DISABLE_SSR_TRANSPARENT) && !defined(SHADER_UNLIT) + #define WRITE_NORMAL_BUFFER + #endif + #endif + + #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) + // Don't do it with debug display mode as it is possible there is no depth prepass in this case + #if !defined(_SURFACE_TYPE_TRANSPARENT) + #if SHADERPASS == SHADERPASS_FORWARD + #define SHADERPASS_FORWARD_BYPASS_ALPHA_TEST + #elif SHADERPASS == SHADERPASS_GBUFFER + #define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST + #endif + #endif + #endif + + // Define _DEFERRED_CAPABLE_MATERIAL for shader capable to run in deferred pass + #if defined(SHADER_LIT) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define _DEFERRED_CAPABLE_MATERIAL + #endif + + // Translate transparent motion vector define + #if defined(_TRANSPARENT_WRITES_MOTION_VEC) && defined(_SURFACE_TYPE_TRANSPARENT) + #define _WRITE_TRANSPARENT_MOTION_VECTOR + #endif + + // -- Graph Properties + CBUFFER_START(UnityPerMaterial) + float4 _Color; + float4 _EmissionColor; + float _UseShadowThreshold; + float4 _DoubleSidedConstants; + float _BlendMode; + float _EnableBlendModePreserveSpecularLighting; + float _RayTracing; + float _RefractionModel; + CBUFFER_END + + + // Object and Global properties + + // -- Property used by ScenePickingPass + #ifdef SCENEPICKINGPASS + float4 _SelectionID; + #endif + + // -- Properties used by SceneSelectionPass + #ifdef SCENESELECTIONPASS + int _ObjectId; + int _PassValue; + #endif + + // Includes + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugDisplay.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/NormalSurfaceGradient.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/Lit.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/BuiltinUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/MaterialUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Decal/DecalUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitDecalData.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderGraphFunctions.hlsl" + // GraphIncludes: + + // -------------------------------------------------- + // Structs and Packing + + struct AttributesMesh + { + float3 positionOS : POSITION; + float3 normalOS : NORMAL; + float4 tangentOS : TANGENT; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : INSTANCEID_SEMANTIC; + #endif + }; + struct VaryingsMeshToPS + { + SV_POSITION_QUALIFIERS float4 positionCS : SV_POSITION; + float3 positionRWS; + float3 normalWS; + float4 tangentWS; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : CUSTOM_INSTANCE_ID; + #endif + }; + struct VertexDescriptionInputs + { + float3 ObjectSpaceNormal; + float3 ObjectSpaceTangent; + float3 ObjectSpacePosition; + }; + struct SurfaceDescriptionInputs + { + float3 TangentSpaceNormal; + }; + struct PackedVaryingsMeshToPS + { + SV_POSITION_QUALIFIERS float4 positionCS : SV_POSITION; + float4 tangentWS : INTERP0; + float3 positionRWS : INTERP1; + float3 normalWS : INTERP2; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : CUSTOM_INSTANCE_ID; + #endif + }; + + PackedVaryingsMeshToPS PackVaryingsMeshToPS (VaryingsMeshToPS input) + { + PackedVaryingsMeshToPS output; + ZERO_INITIALIZE(PackedVaryingsMeshToPS, output); + output.positionCS = input.positionCS; + output.tangentWS.xyzw = input.tangentWS; + output.positionRWS.xyz = input.positionRWS; + output.normalWS.xyz = input.normalWS; + #if UNITY_ANY_INSTANCING_ENABLED + output.instanceID = input.instanceID; + #endif + return output; + } + + VaryingsMeshToPS UnpackVaryingsMeshToPS (PackedVaryingsMeshToPS input) + { + VaryingsMeshToPS output; + output.positionCS = input.positionCS; + output.tangentWS = input.tangentWS.xyzw; + output.positionRWS = input.positionRWS.xyz; + output.normalWS = input.normalWS.xyz; + #if UNITY_ANY_INSTANCING_ENABLED + output.instanceID = input.instanceID; + #endif + return output; + } + + + // -------------------------------------------------- + // Graph + + + // Graph Functions + // GraphFunctions: + + // Graph Vertex + struct VertexDescription + { + float3 Position; + float3 Normal; + float3 Tangent; + }; + + VertexDescription VertexDescriptionFunction(VertexDescriptionInputs IN) + { + VertexDescription description = (VertexDescription)0; + description.Position = IN.ObjectSpacePosition; + description.Normal = IN.ObjectSpaceNormal; + description.Tangent = IN.ObjectSpaceTangent; + return description; + } + + // Graph Pixel + struct SurfaceDescription + { + float3 BaseColor; + float3 Emission; + float Alpha; + float3 BentNormal; + float Smoothness; + float Occlusion; + float3 NormalTS; + float Metallic; + }; + + SurfaceDescription SurfaceDescriptionFunction(SurfaceDescriptionInputs IN) + { + SurfaceDescription surface = (SurfaceDescription)0; + float4 _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4 = _Color; + float _Split_cace9cff304a4c5d84b5305897d09aa9_R_1_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[0]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_G_2_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[1]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_B_3_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[2]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[3]; + surface.BaseColor = (_Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4.xyz); + surface.Emission = float3(0, 0, 0); + surface.Alpha = _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float; + surface.BentNormal = IN.TangentSpaceNormal; + surface.Smoothness = 0.5; + surface.Occlusion = 1; + surface.NormalTS = IN.TangentSpaceNormal; + surface.Metallic = 0; + return surface; + } + + // -------------------------------------------------- + // Build Graph Inputs + #ifdef HAVE_VFX_MODIFICATION + #define VFX_SRP_ATTRIBUTES AttributesMesh + #define VaryingsMeshType VaryingsMeshToPS + #define VFX_SRP_VARYINGS VaryingsMeshType + #define VFX_SRP_SURFACE_INPUTS FragInputs + #endif + + VertexDescriptionInputs AttributesMeshToVertexDescriptionInputs(AttributesMesh input) + { + VertexDescriptionInputs output; + ZERO_INITIALIZE(VertexDescriptionInputs, output); + + output.ObjectSpaceNormal = input.normalOS; + output.ObjectSpaceTangent = input.tangentOS.xyz; + output.ObjectSpacePosition = input.positionOS; + + return output; + } + + VertexDescription GetVertexDescription(AttributesMesh input, float3 timeParameters + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + // build graph inputs + VertexDescriptionInputs vertexDescriptionInputs = AttributesMeshToVertexDescriptionInputs(input); + // Override time parameters with used one (This is required to correctly handle motion vectors for vertex animation based on time) + + // evaluate vertex graph + #ifdef HAVE_VFX_MODIFICATION + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + // Fetch the vertex graph properties for the particle instance. + GetElementVertexProperties(element, properties); + + VertexDescription vertexDescription = VertexDescriptionFunction(vertexDescriptionInputs, properties); + #else + VertexDescription vertexDescription = VertexDescriptionFunction(vertexDescriptionInputs); + #endif + return vertexDescription; + + } + + AttributesMesh ApplyMeshModification(AttributesMesh input, float3 timeParameters + #ifdef USE_CUSTOMINTERP_SUBSTRUCT + #ifdef TESSELLATION_ON + , inout VaryingsMeshToDS varyings + #else + , inout VaryingsMeshToPS varyings + #endif + #endif + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + VertexDescription vertexDescription = GetVertexDescription(input, timeParameters + #ifdef HAVE_VFX_MODIFICATION + , element + #endif + ); + + // copy graph output to the results + input.positionOS = vertexDescription.Position; + input.normalOS = vertexDescription.Normal; + input.tangentOS.xyz = vertexDescription.Tangent; + + + + return input; + } + + #if defined(_ADD_CUSTOM_VELOCITY) // For shader graph custom velocity + // Return precomputed Velocity in object space + float3 GetCustomVelocity(AttributesMesh input + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + VertexDescription vertexDescription = GetVertexDescription(input, _TimeParameters.xyz + #ifdef HAVE_VFX_MODIFICATION + , element + #endif + ); + return vertexDescription.CustomVelocity; + } + #endif + + FragInputs BuildFragInputs(VaryingsMeshToPS input) + { + FragInputs output; + ZERO_INITIALIZE(FragInputs, output); + + // Init to some default value to make the computer quiet (else it output 'divide by zero' warning even if value is not used). + // TODO: this is a really poor workaround, but the variable is used in a bunch of places + // to compute normals which are then passed on elsewhere to compute other values... + output.tangentToWorld = k_identity3x3; + output.positionSS = input.positionCS; // input.positionCS is SV_Position + + output.positionRWS = input.positionRWS; + output.tangentToWorld = BuildTangentToWorld(input.tangentWS, input.normalWS); + + #ifdef HAVE_VFX_MODIFICATION + // FragInputs from VFX come from two places: Interpolator or CBuffer. + #if VFX_USE_GRAPH_VALUES + uint instanceActiveIndex = asuint(UNITY_ACCESS_INSTANCED_PROP(PerInstance, _InstanceActiveIndex)); + /* WARNING: $splice Could not find named fragment 'VFXLoadGraphValues' */ + #endif + + /* WARNING: $splice Could not find named fragment 'VFXSetFragInputs' */ + + #endif + + // splice point to copy custom interpolator fields from varyings to frag inputs + + + return output; + } + + // existing HDRP code uses the combined function to go directly from packed to frag inputs + FragInputs UnpackVaryingsMeshToFragInputs(PackedVaryingsMeshToPS input) + { + UNITY_SETUP_INSTANCE_ID(input); + #if defined(HAVE_VFX_MODIFICATION) && defined(UNITY_INSTANCING_ENABLED) + unity_InstanceID = input.instanceID; + #endif + VaryingsMeshToPS unpacked = UnpackVaryingsMeshToPS(input); + return BuildFragInputs(unpacked); + } + SurfaceDescriptionInputs FragInputsToSurfaceDescriptionInputs(FragInputs input, float3 viewWS) + { + SurfaceDescriptionInputs output; + ZERO_INITIALIZE(SurfaceDescriptionInputs, output); + + #if defined(SHADER_STAGE_RAY_TRACING) + #else + #endif + output.TangentSpaceNormal = float3(0.0f, 0.0f, 1.0f); + + #if UNITY_UV_STARTS_AT_TOP + #else + #endif + + + + // splice point to copy frag inputs custom interpolator pack into the SDI + + + return output; + } + + // -------------------------------------------------- + // Build Surface Data (Specific Material) + + void ApplyDecalToSurfaceDataNoNormal(DecalSurfaceData decalSurfaceData, inout SurfaceData surfaceData); + + void ApplyDecalAndGetNormal(FragInputs fragInputs, PositionInputs posInput, SurfaceDescription surfaceDescription, + inout SurfaceData surfaceData) + { + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + #ifdef DECAL_NORMAL_BLENDING + // SG nodes don't ouptut surface gradients, so if decals require surf grad blending, we have to convert + // the normal to gradient before applying the decal. We then have to resolve the gradient back to world space + float3 normalTS; + + normalTS = SurfaceGradientFromTangentSpaceNormalAndFromTBN(surfaceDescription.NormalTS, + fragInputs.tangentToWorld[0], fragInputs.tangentToWorld[1]); + + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, fragInputs.tangentToWorld[2], normalTS); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + + GetNormalWS_SG(fragInputs, normalTS, surfaceData.normalWS, doubleSidedConstants); + #else + // normal delivered to master node + GetNormalWS(fragInputs, surfaceDescription.NormalTS, surfaceData.normalWS, doubleSidedConstants); + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + // Both uses and modifies 'surfaceData.normalWS'. + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, surfaceData.normalWS.xyz); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + #endif + } + void BuildSurfaceData(FragInputs fragInputs, inout SurfaceDescription surfaceDescription, float3 V, PositionInputs posInput, out SurfaceData surfaceData, out float3 bentNormalWS) + { + ZERO_INITIALIZE(SurfaceData, surfaceData); + + // specularOcclusion need to be init ahead of decal to quiet the compiler that modify the SurfaceData struct + // however specularOcclusion can come from the graph, so need to be init here so it can be override. + surfaceData.specularOcclusion = 1.0; + + surfaceData.baseColor = surfaceDescription.BaseColor; + surfaceData.perceptualSmoothness = surfaceDescription.Smoothness; + surfaceData.ambientOcclusion = surfaceDescription.Occlusion; + surfaceData.metallic = surfaceDescription.Metallic; + + #if defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE) || defined(_REFRACTION_THIN) + if (_EnableSSRefraction) + { + + surfaceData.transmittanceMask = (1.0 - surfaceDescription.Alpha); + surfaceDescription.Alpha = 1.0; + } + else + { + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + surfaceDescription.Alpha = 1.0; + } + #else + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + #endif + + // These static material feature allow compile time optimization + surfaceData.materialFeatures = MATERIALFEATUREFLAGS_LIT_STANDARD; + #ifdef _MATERIAL_FEATURE_SUBSURFACE_SCATTERING + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING; + #endif + + #ifdef _MATERIAL_FEATURE_TRANSMISSION + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_TRANSMISSION; + #endif + + #ifdef _MATERIAL_FEATURE_ANISOTROPY + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_ANISOTROPY; + + // Initialize the normal to something non-zero to avoid a div-zero warning for anisotropy. + surfaceData.normalWS = float3(0, 1, 0); + #endif + + #ifdef _MATERIAL_FEATURE_IRIDESCENCE + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_IRIDESCENCE; + #endif + + #ifdef _MATERIAL_FEATURE_SPECULAR_COLOR + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR; + #endif + + #ifdef _MATERIAL_FEATURE_CLEAR_COAT + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_CLEAR_COAT; + #endif + + #if defined (_MATERIAL_FEATURE_SPECULAR_COLOR) && defined (_ENERGY_CONSERVING_SPECULAR) + // Require to have setup baseColor + // Reproduce the energy conservation done in legacy Unity. Not ideal but better for compatibility and users can unchek it + surfaceData.baseColor *= (1.0 - Max3(surfaceData.specularColor.r, surfaceData.specularColor.g, surfaceData.specularColor.b)); + #endif + + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + ApplyDecalAndGetNormal(fragInputs, posInput, surfaceDescription, surfaceData); + + surfaceData.geomNormalWS = fragInputs.tangentToWorld[2]; + + surfaceData.tangentWS = normalize(fragInputs.tangentToWorld[0].xyz); // The tangent is not normalize in tangentToWorld for mikkt. TODO: Check if it expected that we normalize with Morten. Tag: SURFACE_GRADIENT + + + bentNormalWS = surfaceData.normalWS; + + surfaceData.tangentWS = Orthonormalize(surfaceData.tangentWS, surfaceData.normalWS); + + #ifdef DEBUG_DISPLAY + if (_DebugMipMapMode != DEBUGMIPMAPMODE_NONE) + { + // TODO: need to update mip info + surfaceData.metallic = 0; + } + + // We need to call ApplyDebugToSurfaceData after filling the surfarcedata and before filling builtinData + // as it can modify attribute use for static lighting + ApplyDebugToSurfaceData(fragInputs.tangentToWorld, surfaceData); + #endif + + // By default we use the ambient occlusion with Tri-ace trick (apply outside) for specular occlusion. + // If user provide bent normal then we process a better term + #if defined(_SPECULAR_OCCLUSION_CUSTOM) + // Just use the value passed through via the slot (not active otherwise) + #elif defined(_SPECULAR_OCCLUSION_FROM_AO_BENT_NORMAL) + // If we have bent normal and ambient occlusion, process a specular occlusion + surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData.normalWS, surfaceData.ambientOcclusion, PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness)); + #elif defined(_AMBIENT_OCCLUSION) && defined(_SPECULAR_OCCLUSION_FROM_AO) + surfaceData.specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(ClampNdotV(dot(surfaceData.normalWS, V)), surfaceData.ambientOcclusion, PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness)); + #endif + + #if defined(_ENABLE_GEOMETRIC_SPECULAR_AA) && !defined(SHADER_STAGE_RAY_TRACING) + surfaceData.perceptualSmoothness = GeometricNormalFiltering(surfaceData.perceptualSmoothness, fragInputs.tangentToWorld[2], surfaceDescription.SpecularAAScreenSpaceVariance, surfaceDescription.SpecularAAThreshold); + #endif + } + + // -------------------------------------------------- + // Get Surface And BuiltinData + + void GetSurfaceAndBuiltinData(FragInputs fragInputs, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData RAY_TRACING_OPTIONAL_PARAMETERS) + { + // 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 + LODDitheringTransition(ComputeFadeMaskSeed(V, posInput.positionSS), unity_LODFade.x); + #endif + #endif + + #ifndef SHADER_UNLIT + #ifdef _DOUBLESIDED_ON + float3 doubleSidedConstants = _DoubleSidedConstants.xyz; + #else + float3 doubleSidedConstants = float3(1.0, 1.0, 1.0); + #endif + + ApplyDoubleSidedFlipOrMirror(fragInputs, doubleSidedConstants); // Apply double sided flip on the vertex normal + #endif // SHADER_UNLIT + + SurfaceDescriptionInputs surfaceDescriptionInputs = FragInputsToSurfaceDescriptionInputs(fragInputs, V); + + #if defined(HAVE_VFX_MODIFICATION) + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + GetElementPixelProperties(fragInputs, properties); + + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs, properties); + #else + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs); + #endif + + // Perform alpha test very early to save performance (a killed pixel will not sample textures) + // TODO: split graph evaluation to grab just alpha dependencies first? tricky.. + #ifdef _ALPHATEST_ON + float alphaCutoff = surfaceDescription.AlphaClipThreshold; + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + // The TransparentDepthPrepass is also used with SSR transparent. + // If an artists enable transaprent SSR but not the TransparentDepthPrepass itself, then we use AlphaClipThreshold + // otherwise if TransparentDepthPrepass is enabled we use AlphaClipThresholdDepthPrepass + #elif SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_POSTPASS + // DepthPostpass always use its own alpha threshold + alphaCutoff = surfaceDescription.AlphaClipThresholdDepthPostpass; + #elif (SHADERPASS == SHADERPASS_SHADOWS) || (SHADERPASS == SHADERPASS_RAYTRACING_VISIBILITY) + // If use shadow threshold isn't enable we don't allow any test + #endif + + GENERIC_ALPHA_TEST(surfaceDescription.Alpha, alphaCutoff); + #endif + + #if !defined(SHADER_STAGE_RAY_TRACING) && _DEPTHOFFSET_ON + ApplyDepthOffsetPositionInput(V, surfaceDescription.DepthOffset, GetViewForwardDir(), GetWorldToHClipMatrix(), posInput); + #endif + + #ifndef SHADER_UNLIT + float3 bentNormalWS; + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData, bentNormalWS); + + #ifdef FRAG_INPUTS_USE_TEXCOORD1 + float4 lightmapTexCoord1 = fragInputs.texCoord1; + #else + float4 lightmapTexCoord1 = float4(0,0,0,0); + #endif + + #ifdef FRAG_INPUTS_USE_TEXCOORD2 + float4 lightmapTexCoord2 = fragInputs.texCoord2; + #else + float4 lightmapTexCoord2 = float4(0,0,0,0); + #endif + + // Builtin Data + // For back lighting we use the oposite vertex normal + InitBuiltinData(posInput, surfaceDescription.Alpha, bentNormalWS, -fragInputs.tangentToWorld[2], lightmapTexCoord1, lightmapTexCoord2, builtinData); + + #else + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData); + + ZERO_BUILTIN_INITIALIZE(builtinData); // No call to InitBuiltinData as we don't have any lighting + builtinData.opacity = surfaceDescription.Alpha; + + #if defined(DEBUG_DISPLAY) + // Light Layers are currently not used for the Unlit shader (because it is not lit) + // But Unlit objects do cast shadows according to their rendering layer mask, which is what we want to + // display in the light layers visualization mode, therefore we need the renderingLayers + builtinData.renderingLayers = GetMeshRenderingLightLayer(); + #endif + + #endif // SHADER_UNLIT + + #ifdef _ALPHATEST_ON + // Used for sharpening by alpha to mask - Alpha to covertage is only used with depth only and forward pass (no shadow pass, no transparent pass) + builtinData.alphaClipTreshold = alphaCutoff; + #endif + + // override sampleBakedGI - not used by Unlit + + builtinData.emissiveColor = surfaceDescription.Emission; + + // Note this will not fully work on transparent surfaces (can check with _SURFACE_TYPE_TRANSPARENT define) + // We will always overwrite vt feeback with the nearest. So behind transparent surfaces vt will not be resolved + // This is a limitation of the current MRT approach. + #ifdef UNITY_VIRTUAL_TEXTURING + #endif + + #if _DEPTHOFFSET_ON + builtinData.depthOffset = surfaceDescription.DepthOffset; + #endif + + // TODO: We should generate distortion / distortionBlur for non distortion pass + #if (SHADERPASS == SHADERPASS_DISTORTION) + builtinData.distortion = surfaceDescription.Distortion; + builtinData.distortionBlur = surfaceDescription.DistortionBlur; + #endif + + #ifndef SHADER_UNLIT + // PostInitBuiltinData call ApplyDebugToBuiltinData + PostInitBuiltinData(V, posInput, surfaceData, builtinData); + #else + ApplyDebugToBuiltinData(builtinData); + #endif + + RAY_TRACING_OPTIONAL_ALPHA_TEST_PASS + } + + // -------------------------------------------------- + // Main + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassMotionVectors.hlsl" + + // -------------------------------------------------- + // Visual Effect Vertex Invocations + + #ifdef HAVE_VFX_MODIFICATION + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/VisualEffectVertex.hlsl" + #endif + + ENDHLSL + } + Pass + { + Name "TransparentDepthPrepass" + Tags + { + "LightMode" = "TransparentDepthPrepass" + } + + // Render State + Cull [_CullMode] + Blend One Zero + ZWrite On + Stencil + { + WriteMask [_StencilWriteMaskDepth] + Ref [_StencilRefDepth] + CompFront Always + PassFront Replace + CompBack Always + PassBack Replace + } + + // Debug + // + + // -------------------------------------------------- + // Pass + + HLSLPROGRAM + + // Pragmas + #pragma multi_compile _ DOTS_INSTANCING_ON + #pragma instancing_options renderinglayer + #pragma target 4.5 + #pragma vertex Vert + #pragma fragment Frag + #pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch + #pragma multi_compile_instancing + + // Keywords + #pragma shader_feature _ _SURFACE_TYPE_TRANSPARENT + #pragma shader_feature_local _ _DOUBLESIDED_ON + #pragma shader_feature_local _ _ADD_PRECOMPUTED_VELOCITY + #pragma shader_feature_local _ _TRANSPARENT_WRITES_MOTION_VEC + #pragma shader_feature_local_fragment _ _ENABLE_FOG_ON_TRANSPARENT + #pragma shader_feature_local_fragment _ _DISABLE_DECALS + #pragma shader_feature_local_raytracing _ _DISABLE_DECALS + #pragma shader_feature_local_fragment _ _DISABLE_SSR + #pragma shader_feature_local_raytracing _ _DISABLE_SSR + #pragma shader_feature_local_fragment _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local_raytracing _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local _ _REFRACTION_PLANE _REFRACTION_SPHERE _REFRACTION_THIN + // GraphKeywords: + + // For custom interpolators to inject a substruct definition before FragInputs definition, + // allowing for FragInputs to capture CI's intended for ShaderGraph's SDI. + struct CustomInterpolators + { + }; + #define USE_CUSTOMINTERP_SUBSTRUCT + + + + // TODO: Merge FragInputsVFX substruct with CustomInterpolators. + #ifdef HAVE_VFX_MODIFICATION + struct FragInputsVFX + { + /* WARNING: $splice Could not find named fragment 'FragInputsVFX' */ + }; + #endif + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl" // Required by Tessellation.hlsl + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Tessellation.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Texture.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl" // Required to be include before we include properties as it define DECLARE_STACK_CB + // Always include Shader Graph version + // Always include last to avoid double macros + #include "Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl" // Need to be here for Gradient struct definition + + // -------------------------------------------------- + // Defines + + // Attribute + #define ATTRIBUTES_NEED_NORMAL + #define ATTRIBUTES_NEED_TANGENT + #define VARYINGS_NEED_TANGENT_TO_WORLD + + #define HAVE_MESH_MODIFICATION + + //Strip down the FragInputs.hlsl (on graphics), so we can only optimize the interpolators we use. + //if by accident something requests contents of FragInputs.hlsl, it will be caught as a compiler error + //Frag inputs stripping is only enabled when FRAG_INPUTS_ENABLE_STRIPPING is set + #if !defined(SHADER_STAGE_RAY_TRACING) && SHADERPASS != SHADERPASS_RAYTRACING_GBUFFER && SHADERPASS != SHADERPASS_FULL_SCREEN_DEBUG + #define FRAG_INPUTS_ENABLE_STRIPPING + #endif + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl" + + + + #define SHADERPASS SHADERPASS_TRANSPARENT_DEPTH_PREPASS + #define RAYTRACING_SHADER_GRAPH_DEFAULT + + + // Following two define are a workaround introduce in 10.1.x for RaytracingQualityNode + // The ShaderGraph don't support correctly migration of this node as it serialize all the node data + // in the json file making it impossible to uprgrade. Until we get a fix, we do a workaround here + // to still allow us to rename the field and keyword of this node without breaking existing code. + #ifdef RAYTRACING_SHADER_GRAPH_DEFAULT + #define RAYTRACING_SHADER_GRAPH_HIGH + #endif + + #ifdef RAYTRACING_SHADER_GRAPH_RAYTRACED + #define RAYTRACING_SHADER_GRAPH_LOW + #endif + // end + + #ifndef SHADER_UNLIT + // We need isFrontFace when using double sided - it is not required for unlit as in case of unlit double sided only drive the cullmode + // VARYINGS_NEED_CULLFACE can be define by VaryingsMeshToPS.FaceSign input if a IsFrontFace Node is included in the shader graph. + #if defined(_DOUBLESIDED_ON) && !defined(VARYINGS_NEED_CULLFACE) + #define VARYINGS_NEED_CULLFACE + #endif + #endif + + // Specific Material Define + #define _SPECULAR_OCCLUSION_FROM_AO 1 + #define _ENERGY_CONSERVING_SPECULAR 1 + + // If we use subsurface scattering, enable output split lighting (for forward pass) + #if defined(_MATERIAL_FEATURE_SUBSURFACE_SCATTERING) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define OUTPUT_SPLIT_LIGHTING + #endif + + // This shader support recursive rendering for raytracing + #define HAVE_RECURSIVE_RENDERING + + // In Path Tracing, For all single-sided, refractive materials, we want to force a thin refraction model + #if (SHADERPASS == SHADERPASS_PATH_TRACING) && !defined(_DOUBLESIDED_ON) && (defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE)) + #undef _REFRACTION_PLANE + #undef _REFRACTION_SPHERE + #define _REFRACTION_THIN + #endif + // Caution: we can use the define SHADER_UNLIT onlit after the above Material include as it is the Unlit template who define it + + // To handle SSR on transparent correctly with a possibility to enable/disable it per framesettings + // we should have a code like this: + // if !defined(_DISABLE_SSR_TRANSPARENT) + // pragma multi_compile _ WRITE_NORMAL_BUFFER + // endif + // i.e we enable the multicompile only if we can receive SSR or not, and then C# code drive + // it based on if SSR transparent in frame settings and not (and stripper can strip it). + // this is currently not possible with our current preprocessor as _DISABLE_SSR_TRANSPARENT is a keyword not a define + // so instead we used this and chose to pay the extra cost of normal write even if SSR transaprent is disabled. + // Ideally the shader graph generator should handle it but condition below can't be handle correctly for now. + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + #if !defined(_DISABLE_SSR_TRANSPARENT) && !defined(SHADER_UNLIT) + #define WRITE_NORMAL_BUFFER + #endif + #endif + + #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) + // Don't do it with debug display mode as it is possible there is no depth prepass in this case + #if !defined(_SURFACE_TYPE_TRANSPARENT) + #if SHADERPASS == SHADERPASS_FORWARD + #define SHADERPASS_FORWARD_BYPASS_ALPHA_TEST + #elif SHADERPASS == SHADERPASS_GBUFFER + #define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST + #endif + #endif + #endif + + // Define _DEFERRED_CAPABLE_MATERIAL for shader capable to run in deferred pass + #if defined(SHADER_LIT) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define _DEFERRED_CAPABLE_MATERIAL + #endif + + // Translate transparent motion vector define + #if defined(_TRANSPARENT_WRITES_MOTION_VEC) && defined(_SURFACE_TYPE_TRANSPARENT) + #define _WRITE_TRANSPARENT_MOTION_VECTOR + #endif + + // -- Graph Properties + CBUFFER_START(UnityPerMaterial) + float4 _Color; + float4 _EmissionColor; + float _UseShadowThreshold; + float4 _DoubleSidedConstants; + float _BlendMode; + float _EnableBlendModePreserveSpecularLighting; + float _RayTracing; + float _RefractionModel; + CBUFFER_END + + + // Object and Global properties + + // -- Property used by ScenePickingPass + #ifdef SCENEPICKINGPASS + float4 _SelectionID; + #endif + + // -- Properties used by SceneSelectionPass + #ifdef SCENESELECTIONPASS + int _ObjectId; + int _PassValue; + #endif + + // Includes + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugDisplay.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/NormalSurfaceGradient.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/Lit.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/BuiltinUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/MaterialUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Decal/DecalUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitDecalData.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderGraphFunctions.hlsl" + // GraphIncludes: + + // -------------------------------------------------- + // Structs and Packing + + struct AttributesMesh + { + float3 positionOS : POSITION; + float3 normalOS : NORMAL; + float4 tangentOS : TANGENT; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : INSTANCEID_SEMANTIC; + #endif + }; + struct VaryingsMeshToPS + { + SV_POSITION_QUALIFIERS float4 positionCS : SV_POSITION; + float3 normalWS; + float4 tangentWS; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : CUSTOM_INSTANCE_ID; + #endif + }; + struct VertexDescriptionInputs + { + float3 ObjectSpaceNormal; + float3 ObjectSpaceTangent; + float3 ObjectSpacePosition; + }; + struct SurfaceDescriptionInputs + { + float3 TangentSpaceNormal; + }; + struct PackedVaryingsMeshToPS + { + SV_POSITION_QUALIFIERS float4 positionCS : SV_POSITION; + float4 tangentWS : INTERP0; + float3 normalWS : INTERP1; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : CUSTOM_INSTANCE_ID; + #endif + }; + + PackedVaryingsMeshToPS PackVaryingsMeshToPS (VaryingsMeshToPS input) + { + PackedVaryingsMeshToPS output; + ZERO_INITIALIZE(PackedVaryingsMeshToPS, output); + output.positionCS = input.positionCS; + output.tangentWS.xyzw = input.tangentWS; + output.normalWS.xyz = input.normalWS; + #if UNITY_ANY_INSTANCING_ENABLED + output.instanceID = input.instanceID; + #endif + return output; + } + + VaryingsMeshToPS UnpackVaryingsMeshToPS (PackedVaryingsMeshToPS input) + { + VaryingsMeshToPS output; + output.positionCS = input.positionCS; + output.tangentWS = input.tangentWS.xyzw; + output.normalWS = input.normalWS.xyz; + #if UNITY_ANY_INSTANCING_ENABLED + output.instanceID = input.instanceID; + #endif + return output; + } + + + // -------------------------------------------------- + // Graph + + + // Graph Functions + // GraphFunctions: + + // Graph Vertex + struct VertexDescription + { + float3 Position; + float3 Normal; + float3 Tangent; + }; + + VertexDescription VertexDescriptionFunction(VertexDescriptionInputs IN) + { + VertexDescription description = (VertexDescription)0; + description.Position = IN.ObjectSpacePosition; + description.Normal = IN.ObjectSpaceNormal; + description.Tangent = IN.ObjectSpaceTangent; + return description; + } + + // Graph Pixel + struct SurfaceDescription + { + float Alpha; + float3 NormalTS; + float Smoothness; + }; + + SurfaceDescription SurfaceDescriptionFunction(SurfaceDescriptionInputs IN) + { + SurfaceDescription surface = (SurfaceDescription)0; + float4 _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4 = _Color; + float _Split_cace9cff304a4c5d84b5305897d09aa9_R_1_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[0]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_G_2_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[1]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_B_3_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[2]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[3]; + surface.Alpha = _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float; + surface.NormalTS = IN.TangentSpaceNormal; + surface.Smoothness = 0.5; + return surface; + } + + // -------------------------------------------------- + // Build Graph Inputs + #ifdef HAVE_VFX_MODIFICATION + #define VFX_SRP_ATTRIBUTES AttributesMesh + #define VaryingsMeshType VaryingsMeshToPS + #define VFX_SRP_VARYINGS VaryingsMeshType + #define VFX_SRP_SURFACE_INPUTS FragInputs + #endif + + VertexDescriptionInputs AttributesMeshToVertexDescriptionInputs(AttributesMesh input) + { + VertexDescriptionInputs output; + ZERO_INITIALIZE(VertexDescriptionInputs, output); + + output.ObjectSpaceNormal = input.normalOS; + output.ObjectSpaceTangent = input.tangentOS.xyz; + output.ObjectSpacePosition = input.positionOS; + + return output; + } + + VertexDescription GetVertexDescription(AttributesMesh input, float3 timeParameters + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + // build graph inputs + VertexDescriptionInputs vertexDescriptionInputs = AttributesMeshToVertexDescriptionInputs(input); + // Override time parameters with used one (This is required to correctly handle motion vectors for vertex animation based on time) + + // evaluate vertex graph + #ifdef HAVE_VFX_MODIFICATION + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + // Fetch the vertex graph properties for the particle instance. + GetElementVertexProperties(element, properties); + + VertexDescription vertexDescription = VertexDescriptionFunction(vertexDescriptionInputs, properties); + #else + VertexDescription vertexDescription = VertexDescriptionFunction(vertexDescriptionInputs); + #endif + return vertexDescription; + + } + + AttributesMesh ApplyMeshModification(AttributesMesh input, float3 timeParameters + #ifdef USE_CUSTOMINTERP_SUBSTRUCT + #ifdef TESSELLATION_ON + , inout VaryingsMeshToDS varyings + #else + , inout VaryingsMeshToPS varyings + #endif + #endif + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + VertexDescription vertexDescription = GetVertexDescription(input, timeParameters + #ifdef HAVE_VFX_MODIFICATION + , element + #endif + ); + + // copy graph output to the results + input.positionOS = vertexDescription.Position; + input.normalOS = vertexDescription.Normal; + input.tangentOS.xyz = vertexDescription.Tangent; + + + + return input; + } + + #if defined(_ADD_CUSTOM_VELOCITY) // For shader graph custom velocity + // Return precomputed Velocity in object space + float3 GetCustomVelocity(AttributesMesh input + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + VertexDescription vertexDescription = GetVertexDescription(input, _TimeParameters.xyz + #ifdef HAVE_VFX_MODIFICATION + , element + #endif + ); + return vertexDescription.CustomVelocity; + } + #endif + + FragInputs BuildFragInputs(VaryingsMeshToPS input) + { + FragInputs output; + ZERO_INITIALIZE(FragInputs, output); + + // Init to some default value to make the computer quiet (else it output 'divide by zero' warning even if value is not used). + // TODO: this is a really poor workaround, but the variable is used in a bunch of places + // to compute normals which are then passed on elsewhere to compute other values... + output.tangentToWorld = k_identity3x3; + output.positionSS = input.positionCS; // input.positionCS is SV_Position + + output.tangentToWorld = BuildTangentToWorld(input.tangentWS, input.normalWS); + + #ifdef HAVE_VFX_MODIFICATION + // FragInputs from VFX come from two places: Interpolator or CBuffer. + #if VFX_USE_GRAPH_VALUES + uint instanceActiveIndex = asuint(UNITY_ACCESS_INSTANCED_PROP(PerInstance, _InstanceActiveIndex)); + /* WARNING: $splice Could not find named fragment 'VFXLoadGraphValues' */ + #endif + + /* WARNING: $splice Could not find named fragment 'VFXSetFragInputs' */ + + #endif + + // splice point to copy custom interpolator fields from varyings to frag inputs + + + return output; + } + + // existing HDRP code uses the combined function to go directly from packed to frag inputs + FragInputs UnpackVaryingsMeshToFragInputs(PackedVaryingsMeshToPS input) + { + UNITY_SETUP_INSTANCE_ID(input); + #if defined(HAVE_VFX_MODIFICATION) && defined(UNITY_INSTANCING_ENABLED) + unity_InstanceID = input.instanceID; + #endif + VaryingsMeshToPS unpacked = UnpackVaryingsMeshToPS(input); + return BuildFragInputs(unpacked); + } + SurfaceDescriptionInputs FragInputsToSurfaceDescriptionInputs(FragInputs input, float3 viewWS) + { + SurfaceDescriptionInputs output; + ZERO_INITIALIZE(SurfaceDescriptionInputs, output); + + #if defined(SHADER_STAGE_RAY_TRACING) + #else + #endif + output.TangentSpaceNormal = float3(0.0f, 0.0f, 1.0f); + + #if UNITY_UV_STARTS_AT_TOP + #else + #endif + + + + // splice point to copy frag inputs custom interpolator pack into the SDI + + + return output; + } + + // -------------------------------------------------- + // Build Surface Data (Specific Material) + + void ApplyDecalToSurfaceDataNoNormal(DecalSurfaceData decalSurfaceData, inout SurfaceData surfaceData); + + void ApplyDecalAndGetNormal(FragInputs fragInputs, PositionInputs posInput, SurfaceDescription surfaceDescription, + inout SurfaceData surfaceData) + { + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + #ifdef DECAL_NORMAL_BLENDING + // SG nodes don't ouptut surface gradients, so if decals require surf grad blending, we have to convert + // the normal to gradient before applying the decal. We then have to resolve the gradient back to world space + float3 normalTS; + + normalTS = SurfaceGradientFromTangentSpaceNormalAndFromTBN(surfaceDescription.NormalTS, + fragInputs.tangentToWorld[0], fragInputs.tangentToWorld[1]); + + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, fragInputs.tangentToWorld[2], normalTS); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + + GetNormalWS_SG(fragInputs, normalTS, surfaceData.normalWS, doubleSidedConstants); + #else + // normal delivered to master node + GetNormalWS(fragInputs, surfaceDescription.NormalTS, surfaceData.normalWS, doubleSidedConstants); + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + // Both uses and modifies 'surfaceData.normalWS'. + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, surfaceData.normalWS.xyz); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + #endif + } + void BuildSurfaceData(FragInputs fragInputs, inout SurfaceDescription surfaceDescription, float3 V, PositionInputs posInput, out SurfaceData surfaceData, out float3 bentNormalWS) + { + ZERO_INITIALIZE(SurfaceData, surfaceData); + + // specularOcclusion need to be init ahead of decal to quiet the compiler that modify the SurfaceData struct + // however specularOcclusion can come from the graph, so need to be init here so it can be override. + surfaceData.specularOcclusion = 1.0; + + surfaceData.perceptualSmoothness = surfaceDescription.Smoothness; + + #if defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE) || defined(_REFRACTION_THIN) + if (_EnableSSRefraction) + { + + surfaceData.transmittanceMask = (1.0 - surfaceDescription.Alpha); + surfaceDescription.Alpha = 1.0; + } + else + { + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + surfaceDescription.Alpha = 1.0; + } + #else + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + #endif + + // These static material feature allow compile time optimization + surfaceData.materialFeatures = MATERIALFEATUREFLAGS_LIT_STANDARD; + #ifdef _MATERIAL_FEATURE_SUBSURFACE_SCATTERING + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING; + #endif + + #ifdef _MATERIAL_FEATURE_TRANSMISSION + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_TRANSMISSION; + #endif + + #ifdef _MATERIAL_FEATURE_ANISOTROPY + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_ANISOTROPY; + + // Initialize the normal to something non-zero to avoid a div-zero warning for anisotropy. + surfaceData.normalWS = float3(0, 1, 0); + #endif + + #ifdef _MATERIAL_FEATURE_IRIDESCENCE + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_IRIDESCENCE; + #endif + + #ifdef _MATERIAL_FEATURE_SPECULAR_COLOR + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR; + #endif + + #ifdef _MATERIAL_FEATURE_CLEAR_COAT + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_CLEAR_COAT; + #endif + + #if defined (_MATERIAL_FEATURE_SPECULAR_COLOR) && defined (_ENERGY_CONSERVING_SPECULAR) + // Require to have setup baseColor + // Reproduce the energy conservation done in legacy Unity. Not ideal but better for compatibility and users can unchek it + surfaceData.baseColor *= (1.0 - Max3(surfaceData.specularColor.r, surfaceData.specularColor.g, surfaceData.specularColor.b)); + #endif + + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + ApplyDecalAndGetNormal(fragInputs, posInput, surfaceDescription, surfaceData); + + surfaceData.geomNormalWS = fragInputs.tangentToWorld[2]; + + surfaceData.tangentWS = normalize(fragInputs.tangentToWorld[0].xyz); // The tangent is not normalize in tangentToWorld for mikkt. TODO: Check if it expected that we normalize with Morten. Tag: SURFACE_GRADIENT + + + bentNormalWS = surfaceData.normalWS; + + surfaceData.tangentWS = Orthonormalize(surfaceData.tangentWS, surfaceData.normalWS); + + #ifdef DEBUG_DISPLAY + if (_DebugMipMapMode != DEBUGMIPMAPMODE_NONE) + { + // TODO: need to update mip info + surfaceData.metallic = 0; + } + + // We need to call ApplyDebugToSurfaceData after filling the surfarcedata and before filling builtinData + // as it can modify attribute use for static lighting + ApplyDebugToSurfaceData(fragInputs.tangentToWorld, surfaceData); + #endif + + // By default we use the ambient occlusion with Tri-ace trick (apply outside) for specular occlusion. + // If user provide bent normal then we process a better term + #if defined(_SPECULAR_OCCLUSION_CUSTOM) + // Just use the value passed through via the slot (not active otherwise) + #elif defined(_SPECULAR_OCCLUSION_FROM_AO_BENT_NORMAL) + // If we have bent normal and ambient occlusion, process a specular occlusion + surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData.normalWS, surfaceData.ambientOcclusion, PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness)); + #elif defined(_AMBIENT_OCCLUSION) && defined(_SPECULAR_OCCLUSION_FROM_AO) + surfaceData.specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(ClampNdotV(dot(surfaceData.normalWS, V)), surfaceData.ambientOcclusion, PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness)); + #endif + + #if defined(_ENABLE_GEOMETRIC_SPECULAR_AA) && !defined(SHADER_STAGE_RAY_TRACING) + surfaceData.perceptualSmoothness = GeometricNormalFiltering(surfaceData.perceptualSmoothness, fragInputs.tangentToWorld[2], surfaceDescription.SpecularAAScreenSpaceVariance, surfaceDescription.SpecularAAThreshold); + #endif + } + + // -------------------------------------------------- + // Get Surface And BuiltinData + + void GetSurfaceAndBuiltinData(FragInputs fragInputs, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData RAY_TRACING_OPTIONAL_PARAMETERS) + { + // 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 + LODDitheringTransition(ComputeFadeMaskSeed(V, posInput.positionSS), unity_LODFade.x); + #endif + #endif + + #ifndef SHADER_UNLIT + #ifdef _DOUBLESIDED_ON + float3 doubleSidedConstants = _DoubleSidedConstants.xyz; + #else + float3 doubleSidedConstants = float3(1.0, 1.0, 1.0); + #endif + + ApplyDoubleSidedFlipOrMirror(fragInputs, doubleSidedConstants); // Apply double sided flip on the vertex normal + #endif // SHADER_UNLIT + + SurfaceDescriptionInputs surfaceDescriptionInputs = FragInputsToSurfaceDescriptionInputs(fragInputs, V); + + #if defined(HAVE_VFX_MODIFICATION) + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + GetElementPixelProperties(fragInputs, properties); + + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs, properties); + #else + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs); + #endif + + // Perform alpha test very early to save performance (a killed pixel will not sample textures) + // TODO: split graph evaluation to grab just alpha dependencies first? tricky.. + #ifdef _ALPHATEST_ON + float alphaCutoff = surfaceDescription.AlphaClipThreshold; + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + // The TransparentDepthPrepass is also used with SSR transparent. + // If an artists enable transaprent SSR but not the TransparentDepthPrepass itself, then we use AlphaClipThreshold + // otherwise if TransparentDepthPrepass is enabled we use AlphaClipThresholdDepthPrepass + #elif SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_POSTPASS + // DepthPostpass always use its own alpha threshold + alphaCutoff = surfaceDescription.AlphaClipThresholdDepthPostpass; + #elif (SHADERPASS == SHADERPASS_SHADOWS) || (SHADERPASS == SHADERPASS_RAYTRACING_VISIBILITY) + // If use shadow threshold isn't enable we don't allow any test + #endif + + GENERIC_ALPHA_TEST(surfaceDescription.Alpha, alphaCutoff); + #endif + + #if !defined(SHADER_STAGE_RAY_TRACING) && _DEPTHOFFSET_ON + ApplyDepthOffsetPositionInput(V, surfaceDescription.DepthOffset, GetViewForwardDir(), GetWorldToHClipMatrix(), posInput); + #endif + + #ifndef SHADER_UNLIT + float3 bentNormalWS; + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData, bentNormalWS); + + #ifdef FRAG_INPUTS_USE_TEXCOORD1 + float4 lightmapTexCoord1 = fragInputs.texCoord1; + #else + float4 lightmapTexCoord1 = float4(0,0,0,0); + #endif + + #ifdef FRAG_INPUTS_USE_TEXCOORD2 + float4 lightmapTexCoord2 = fragInputs.texCoord2; + #else + float4 lightmapTexCoord2 = float4(0,0,0,0); + #endif + + // Builtin Data + // For back lighting we use the oposite vertex normal + InitBuiltinData(posInput, surfaceDescription.Alpha, bentNormalWS, -fragInputs.tangentToWorld[2], lightmapTexCoord1, lightmapTexCoord2, builtinData); + + #else + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData); + + ZERO_BUILTIN_INITIALIZE(builtinData); // No call to InitBuiltinData as we don't have any lighting + builtinData.opacity = surfaceDescription.Alpha; + + #if defined(DEBUG_DISPLAY) + // Light Layers are currently not used for the Unlit shader (because it is not lit) + // But Unlit objects do cast shadows according to their rendering layer mask, which is what we want to + // display in the light layers visualization mode, therefore we need the renderingLayers + builtinData.renderingLayers = GetMeshRenderingLightLayer(); + #endif + + #endif // SHADER_UNLIT + + #ifdef _ALPHATEST_ON + // Used for sharpening by alpha to mask - Alpha to covertage is only used with depth only and forward pass (no shadow pass, no transparent pass) + builtinData.alphaClipTreshold = alphaCutoff; + #endif + + // override sampleBakedGI - not used by Unlit + + + // Note this will not fully work on transparent surfaces (can check with _SURFACE_TYPE_TRANSPARENT define) + // We will always overwrite vt feeback with the nearest. So behind transparent surfaces vt will not be resolved + // This is a limitation of the current MRT approach. + #ifdef UNITY_VIRTUAL_TEXTURING + #endif + + #if _DEPTHOFFSET_ON + builtinData.depthOffset = surfaceDescription.DepthOffset; + #endif + + // TODO: We should generate distortion / distortionBlur for non distortion pass + #if (SHADERPASS == SHADERPASS_DISTORTION) + builtinData.distortion = surfaceDescription.Distortion; + builtinData.distortionBlur = surfaceDescription.DistortionBlur; + #endif + + #ifndef SHADER_UNLIT + // PostInitBuiltinData call ApplyDebugToBuiltinData + PostInitBuiltinData(V, posInput, surfaceData, builtinData); + #else + ApplyDebugToBuiltinData(builtinData); + #endif + + RAY_TRACING_OPTIONAL_ALPHA_TEST_PASS + } + + // -------------------------------------------------- + // Main + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassDepthOnly.hlsl" + + // -------------------------------------------------- + // Visual Effect Vertex Invocations + + #ifdef HAVE_VFX_MODIFICATION + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/VisualEffectVertex.hlsl" + #endif + + ENDHLSL + } + Pass + { + Name "FullScreenDebug" + Tags + { + "LightMode" = "FullScreenDebug" + } + + // Render State + Cull [_CullMode] + ZTest LEqual + ZWrite Off + + // Debug + // + + // -------------------------------------------------- + // Pass + + HLSLPROGRAM + + // Pragmas + #pragma multi_compile _ DOTS_INSTANCING_ON + #pragma instancing_options renderinglayer + #pragma target 4.5 + #pragma vertex Vert + #pragma fragment Frag + #pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch + #pragma multi_compile_instancing + + // Keywords + #pragma shader_feature _ _SURFACE_TYPE_TRANSPARENT + #pragma shader_feature_local _ _DOUBLESIDED_ON + #pragma shader_feature_local _ _ADD_PRECOMPUTED_VELOCITY + #pragma shader_feature_local _ _TRANSPARENT_WRITES_MOTION_VEC + #pragma shader_feature_local_fragment _ _ENABLE_FOG_ON_TRANSPARENT + #pragma shader_feature_local_fragment _ _DISABLE_DECALS + #pragma shader_feature_local_raytracing _ _DISABLE_DECALS + #pragma shader_feature_local_fragment _ _DISABLE_SSR + #pragma shader_feature_local_raytracing _ _DISABLE_SSR + #pragma shader_feature_local_fragment _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local_raytracing _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local _ _REFRACTION_PLANE _REFRACTION_SPHERE _REFRACTION_THIN + // GraphKeywords: + + // For custom interpolators to inject a substruct definition before FragInputs definition, + // allowing for FragInputs to capture CI's intended for ShaderGraph's SDI. + struct CustomInterpolators + { + }; + #define USE_CUSTOMINTERP_SUBSTRUCT + + + + // TODO: Merge FragInputsVFX substruct with CustomInterpolators. + #ifdef HAVE_VFX_MODIFICATION + struct FragInputsVFX + { + /* WARNING: $splice Could not find named fragment 'FragInputsVFX' */ + }; + #endif + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl" // Required by Tessellation.hlsl + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Tessellation.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Texture.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl" // Required to be include before we include properties as it define DECLARE_STACK_CB + // Always include Shader Graph version + // Always include last to avoid double macros + #include "Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl" // Need to be here for Gradient struct definition + + // -------------------------------------------------- + // Defines + + // Attribute + #define ATTRIBUTES_NEED_NORMAL + #define ATTRIBUTES_NEED_TANGENT + + #define HAVE_MESH_MODIFICATION + + //Strip down the FragInputs.hlsl (on graphics), so we can only optimize the interpolators we use. + //if by accident something requests contents of FragInputs.hlsl, it will be caught as a compiler error + //Frag inputs stripping is only enabled when FRAG_INPUTS_ENABLE_STRIPPING is set + #if !defined(SHADER_STAGE_RAY_TRACING) && SHADERPASS != SHADERPASS_RAYTRACING_GBUFFER && SHADERPASS != SHADERPASS_FULL_SCREEN_DEBUG + #define FRAG_INPUTS_ENABLE_STRIPPING + #endif + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl" + + + + #define SHADERPASS SHADERPASS_FULL_SCREEN_DEBUG + #define RAYTRACING_SHADER_GRAPH_DEFAULT + + + // Following two define are a workaround introduce in 10.1.x for RaytracingQualityNode + // The ShaderGraph don't support correctly migration of this node as it serialize all the node data + // in the json file making it impossible to uprgrade. Until we get a fix, we do a workaround here + // to still allow us to rename the field and keyword of this node without breaking existing code. + #ifdef RAYTRACING_SHADER_GRAPH_DEFAULT + #define RAYTRACING_SHADER_GRAPH_HIGH + #endif + + #ifdef RAYTRACING_SHADER_GRAPH_RAYTRACED + #define RAYTRACING_SHADER_GRAPH_LOW + #endif + // end + + #ifndef SHADER_UNLIT + // We need isFrontFace when using double sided - it is not required for unlit as in case of unlit double sided only drive the cullmode + // VARYINGS_NEED_CULLFACE can be define by VaryingsMeshToPS.FaceSign input if a IsFrontFace Node is included in the shader graph. + #if defined(_DOUBLESIDED_ON) && !defined(VARYINGS_NEED_CULLFACE) + #define VARYINGS_NEED_CULLFACE + #endif + #endif + + // Specific Material Define + #define _SPECULAR_OCCLUSION_FROM_AO 1 + #define _ENERGY_CONSERVING_SPECULAR 1 + + // If we use subsurface scattering, enable output split lighting (for forward pass) + #if defined(_MATERIAL_FEATURE_SUBSURFACE_SCATTERING) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define OUTPUT_SPLIT_LIGHTING + #endif + + // This shader support recursive rendering for raytracing + #define HAVE_RECURSIVE_RENDERING + + // In Path Tracing, For all single-sided, refractive materials, we want to force a thin refraction model + #if (SHADERPASS == SHADERPASS_PATH_TRACING) && !defined(_DOUBLESIDED_ON) && (defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE)) + #undef _REFRACTION_PLANE + #undef _REFRACTION_SPHERE + #define _REFRACTION_THIN + #endif + // Caution: we can use the define SHADER_UNLIT onlit after the above Material include as it is the Unlit template who define it + + // To handle SSR on transparent correctly with a possibility to enable/disable it per framesettings + // we should have a code like this: + // if !defined(_DISABLE_SSR_TRANSPARENT) + // pragma multi_compile _ WRITE_NORMAL_BUFFER + // endif + // i.e we enable the multicompile only if we can receive SSR or not, and then C# code drive + // it based on if SSR transparent in frame settings and not (and stripper can strip it). + // this is currently not possible with our current preprocessor as _DISABLE_SSR_TRANSPARENT is a keyword not a define + // so instead we used this and chose to pay the extra cost of normal write even if SSR transaprent is disabled. + // Ideally the shader graph generator should handle it but condition below can't be handle correctly for now. + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + #if !defined(_DISABLE_SSR_TRANSPARENT) && !defined(SHADER_UNLIT) + #define WRITE_NORMAL_BUFFER + #endif + #endif + + #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) + // Don't do it with debug display mode as it is possible there is no depth prepass in this case + #if !defined(_SURFACE_TYPE_TRANSPARENT) + #if SHADERPASS == SHADERPASS_FORWARD + #define SHADERPASS_FORWARD_BYPASS_ALPHA_TEST + #elif SHADERPASS == SHADERPASS_GBUFFER + #define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST + #endif + #endif + #endif + + // Define _DEFERRED_CAPABLE_MATERIAL for shader capable to run in deferred pass + #if defined(SHADER_LIT) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define _DEFERRED_CAPABLE_MATERIAL + #endif + + // Translate transparent motion vector define + #if defined(_TRANSPARENT_WRITES_MOTION_VEC) && defined(_SURFACE_TYPE_TRANSPARENT) + #define _WRITE_TRANSPARENT_MOTION_VECTOR + #endif + + // -- Graph Properties + CBUFFER_START(UnityPerMaterial) + float4 _Color; + float4 _EmissionColor; + float _UseShadowThreshold; + float4 _DoubleSidedConstants; + float _BlendMode; + float _EnableBlendModePreserveSpecularLighting; + float _RayTracing; + float _RefractionModel; + CBUFFER_END + + + // Object and Global properties + + // -- Property used by ScenePickingPass + #ifdef SCENEPICKINGPASS + float4 _SelectionID; + #endif + + // -- Properties used by SceneSelectionPass + #ifdef SCENESELECTIONPASS + int _ObjectId; + int _PassValue; + #endif + + // Includes + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugDisplay.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/NormalSurfaceGradient.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/Lit.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/BuiltinUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/MaterialUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderGraphFunctions.hlsl" + // GraphIncludes: + + // -------------------------------------------------- + // Structs and Packing + + struct AttributesMesh + { + float3 positionOS : POSITION; + float3 normalOS : NORMAL; + float4 tangentOS : TANGENT; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : INSTANCEID_SEMANTIC; + #endif + }; + struct VaryingsMeshToPS + { + SV_POSITION_QUALIFIERS float4 positionCS : SV_POSITION; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : CUSTOM_INSTANCE_ID; + #endif + }; + struct VertexDescriptionInputs + { + float3 ObjectSpaceNormal; + float3 ObjectSpaceTangent; + float3 ObjectSpacePosition; + }; + struct SurfaceDescriptionInputs + { + float3 TangentSpaceNormal; + }; + struct PackedVaryingsMeshToPS + { + SV_POSITION_QUALIFIERS float4 positionCS : SV_POSITION; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : CUSTOM_INSTANCE_ID; + #endif + }; + + PackedVaryingsMeshToPS PackVaryingsMeshToPS (VaryingsMeshToPS input) + { + PackedVaryingsMeshToPS output; + ZERO_INITIALIZE(PackedVaryingsMeshToPS, output); + output.positionCS = input.positionCS; + #if UNITY_ANY_INSTANCING_ENABLED + output.instanceID = input.instanceID; + #endif + return output; + } + + VaryingsMeshToPS UnpackVaryingsMeshToPS (PackedVaryingsMeshToPS input) + { + VaryingsMeshToPS output; + output.positionCS = input.positionCS; + #if UNITY_ANY_INSTANCING_ENABLED + output.instanceID = input.instanceID; + #endif + return output; + } + + + // -------------------------------------------------- + // Graph + + + // Graph Functions + // GraphFunctions: + + // Graph Vertex + struct VertexDescription + { + float3 Position; + float3 Normal; + float3 Tangent; + }; + + VertexDescription VertexDescriptionFunction(VertexDescriptionInputs IN) + { + VertexDescription description = (VertexDescription)0; + description.Position = IN.ObjectSpacePosition; + description.Normal = IN.ObjectSpaceNormal; + description.Tangent = IN.ObjectSpaceTangent; + return description; + } + + // Graph Pixel + struct SurfaceDescription + { + float3 BaseColor; + float3 Emission; + float Alpha; + float3 BentNormal; + float Smoothness; + float Occlusion; + float3 NormalTS; + float Metallic; + }; + + SurfaceDescription SurfaceDescriptionFunction(SurfaceDescriptionInputs IN) + { + SurfaceDescription surface = (SurfaceDescription)0; + float4 _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4 = _Color; + float _Split_cace9cff304a4c5d84b5305897d09aa9_R_1_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[0]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_G_2_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[1]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_B_3_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[2]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[3]; + surface.BaseColor = (_Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4.xyz); + surface.Emission = float3(0, 0, 0); + surface.Alpha = _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float; + surface.BentNormal = IN.TangentSpaceNormal; + surface.Smoothness = 0.5; + surface.Occlusion = 1; + surface.NormalTS = IN.TangentSpaceNormal; + surface.Metallic = 0; + return surface; + } + + // -------------------------------------------------- + // Build Graph Inputs + #ifdef HAVE_VFX_MODIFICATION + #define VFX_SRP_ATTRIBUTES AttributesMesh + #define VaryingsMeshType VaryingsMeshToPS + #define VFX_SRP_VARYINGS VaryingsMeshType + #define VFX_SRP_SURFACE_INPUTS FragInputs + #endif + + VertexDescriptionInputs AttributesMeshToVertexDescriptionInputs(AttributesMesh input) + { + VertexDescriptionInputs output; + ZERO_INITIALIZE(VertexDescriptionInputs, output); + + output.ObjectSpaceNormal = input.normalOS; + output.ObjectSpaceTangent = input.tangentOS.xyz; + output.ObjectSpacePosition = input.positionOS; + + return output; + } + + VertexDescription GetVertexDescription(AttributesMesh input, float3 timeParameters + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + // build graph inputs + VertexDescriptionInputs vertexDescriptionInputs = AttributesMeshToVertexDescriptionInputs(input); + // Override time parameters with used one (This is required to correctly handle motion vectors for vertex animation based on time) + + // evaluate vertex graph + #ifdef HAVE_VFX_MODIFICATION + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + // Fetch the vertex graph properties for the particle instance. + GetElementVertexProperties(element, properties); + + VertexDescription vertexDescription = VertexDescriptionFunction(vertexDescriptionInputs, properties); + #else + VertexDescription vertexDescription = VertexDescriptionFunction(vertexDescriptionInputs); + #endif + return vertexDescription; + + } + + AttributesMesh ApplyMeshModification(AttributesMesh input, float3 timeParameters + #ifdef USE_CUSTOMINTERP_SUBSTRUCT + #ifdef TESSELLATION_ON + , inout VaryingsMeshToDS varyings + #else + , inout VaryingsMeshToPS varyings + #endif + #endif + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + VertexDescription vertexDescription = GetVertexDescription(input, timeParameters + #ifdef HAVE_VFX_MODIFICATION + , element + #endif + ); + + // copy graph output to the results + input.positionOS = vertexDescription.Position; + input.normalOS = vertexDescription.Normal; + input.tangentOS.xyz = vertexDescription.Tangent; + + + + return input; + } + + #if defined(_ADD_CUSTOM_VELOCITY) // For shader graph custom velocity + // Return precomputed Velocity in object space + float3 GetCustomVelocity(AttributesMesh input + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + VertexDescription vertexDescription = GetVertexDescription(input, _TimeParameters.xyz + #ifdef HAVE_VFX_MODIFICATION + , element + #endif + ); + return vertexDescription.CustomVelocity; + } + #endif + + FragInputs BuildFragInputs(VaryingsMeshToPS input) + { + FragInputs output; + ZERO_INITIALIZE(FragInputs, output); + + // Init to some default value to make the computer quiet (else it output 'divide by zero' warning even if value is not used). + // TODO: this is a really poor workaround, but the variable is used in a bunch of places + // to compute normals which are then passed on elsewhere to compute other values... + output.tangentToWorld = k_identity3x3; + output.positionSS = input.positionCS; // input.positionCS is SV_Position + + + #ifdef HAVE_VFX_MODIFICATION + // FragInputs from VFX come from two places: Interpolator or CBuffer. + #if VFX_USE_GRAPH_VALUES + uint instanceActiveIndex = asuint(UNITY_ACCESS_INSTANCED_PROP(PerInstance, _InstanceActiveIndex)); + /* WARNING: $splice Could not find named fragment 'VFXLoadGraphValues' */ + #endif + + /* WARNING: $splice Could not find named fragment 'VFXSetFragInputs' */ + + #endif + + // splice point to copy custom interpolator fields from varyings to frag inputs + + + return output; + } + + // existing HDRP code uses the combined function to go directly from packed to frag inputs + FragInputs UnpackVaryingsMeshToFragInputs(PackedVaryingsMeshToPS input) + { + UNITY_SETUP_INSTANCE_ID(input); + #if defined(HAVE_VFX_MODIFICATION) && defined(UNITY_INSTANCING_ENABLED) + unity_InstanceID = input.instanceID; + #endif + VaryingsMeshToPS unpacked = UnpackVaryingsMeshToPS(input); + return BuildFragInputs(unpacked); + } + SurfaceDescriptionInputs FragInputsToSurfaceDescriptionInputs(FragInputs input, float3 viewWS) + { + SurfaceDescriptionInputs output; + ZERO_INITIALIZE(SurfaceDescriptionInputs, output); + + #if defined(SHADER_STAGE_RAY_TRACING) + #else + #endif + output.TangentSpaceNormal = float3(0.0f, 0.0f, 1.0f); + + #if UNITY_UV_STARTS_AT_TOP + #else + #endif + + + + // splice point to copy frag inputs custom interpolator pack into the SDI + + + return output; + } + + // -------------------------------------------------- + // Build Surface Data (Specific Material) + + void ApplyDecalToSurfaceDataNoNormal(DecalSurfaceData decalSurfaceData, inout SurfaceData surfaceData); + + void ApplyDecalAndGetNormal(FragInputs fragInputs, PositionInputs posInput, SurfaceDescription surfaceDescription, + inout SurfaceData surfaceData) + { + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + #ifdef DECAL_NORMAL_BLENDING + // SG nodes don't ouptut surface gradients, so if decals require surf grad blending, we have to convert + // the normal to gradient before applying the decal. We then have to resolve the gradient back to world space + float3 normalTS; + + normalTS = SurfaceGradientFromTangentSpaceNormalAndFromTBN(surfaceDescription.NormalTS, + fragInputs.tangentToWorld[0], fragInputs.tangentToWorld[1]); + + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, fragInputs.tangentToWorld[2], normalTS); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + + GetNormalWS_SG(fragInputs, normalTS, surfaceData.normalWS, doubleSidedConstants); + #else + // normal delivered to master node + GetNormalWS(fragInputs, surfaceDescription.NormalTS, surfaceData.normalWS, doubleSidedConstants); + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + // Both uses and modifies 'surfaceData.normalWS'. + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, surfaceData.normalWS.xyz); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + #endif + } + void BuildSurfaceData(FragInputs fragInputs, inout SurfaceDescription surfaceDescription, float3 V, PositionInputs posInput, out SurfaceData surfaceData, out float3 bentNormalWS) + { + ZERO_INITIALIZE(SurfaceData, surfaceData); + + // specularOcclusion need to be init ahead of decal to quiet the compiler that modify the SurfaceData struct + // however specularOcclusion can come from the graph, so need to be init here so it can be override. + surfaceData.specularOcclusion = 1.0; + + surfaceData.baseColor = surfaceDescription.BaseColor; + surfaceData.perceptualSmoothness = surfaceDescription.Smoothness; + surfaceData.ambientOcclusion = surfaceDescription.Occlusion; + surfaceData.metallic = surfaceDescription.Metallic; + + #if defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE) || defined(_REFRACTION_THIN) + if (_EnableSSRefraction) + { + + surfaceData.transmittanceMask = (1.0 - surfaceDescription.Alpha); + surfaceDescription.Alpha = 1.0; + } + else + { + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + surfaceDescription.Alpha = 1.0; + } + #else + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + #endif + + // These static material feature allow compile time optimization + surfaceData.materialFeatures = MATERIALFEATUREFLAGS_LIT_STANDARD; + #ifdef _MATERIAL_FEATURE_SUBSURFACE_SCATTERING + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING; + #endif + + #ifdef _MATERIAL_FEATURE_TRANSMISSION + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_TRANSMISSION; + #endif + + #ifdef _MATERIAL_FEATURE_ANISOTROPY + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_ANISOTROPY; + + // Initialize the normal to something non-zero to avoid a div-zero warning for anisotropy. + surfaceData.normalWS = float3(0, 1, 0); + #endif + + #ifdef _MATERIAL_FEATURE_IRIDESCENCE + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_IRIDESCENCE; + #endif + + #ifdef _MATERIAL_FEATURE_SPECULAR_COLOR + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR; + #endif + + #ifdef _MATERIAL_FEATURE_CLEAR_COAT + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_CLEAR_COAT; + #endif + + #if defined (_MATERIAL_FEATURE_SPECULAR_COLOR) && defined (_ENERGY_CONSERVING_SPECULAR) + // Require to have setup baseColor + // Reproduce the energy conservation done in legacy Unity. Not ideal but better for compatibility and users can unchek it + surfaceData.baseColor *= (1.0 - Max3(surfaceData.specularColor.r, surfaceData.specularColor.g, surfaceData.specularColor.b)); + #endif + + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + ApplyDecalAndGetNormal(fragInputs, posInput, surfaceDescription, surfaceData); + + surfaceData.geomNormalWS = fragInputs.tangentToWorld[2]; + + surfaceData.tangentWS = normalize(fragInputs.tangentToWorld[0].xyz); // The tangent is not normalize in tangentToWorld for mikkt. TODO: Check if it expected that we normalize with Morten. Tag: SURFACE_GRADIENT + + + bentNormalWS = surfaceData.normalWS; + + surfaceData.tangentWS = Orthonormalize(surfaceData.tangentWS, surfaceData.normalWS); + + #ifdef DEBUG_DISPLAY + if (_DebugMipMapMode != DEBUGMIPMAPMODE_NONE) + { + // TODO: need to update mip info + surfaceData.metallic = 0; + } + + // We need to call ApplyDebugToSurfaceData after filling the surfarcedata and before filling builtinData + // as it can modify attribute use for static lighting + ApplyDebugToSurfaceData(fragInputs.tangentToWorld, surfaceData); + #endif + + // By default we use the ambient occlusion with Tri-ace trick (apply outside) for specular occlusion. + // If user provide bent normal then we process a better term + #if defined(_SPECULAR_OCCLUSION_CUSTOM) + // Just use the value passed through via the slot (not active otherwise) + #elif defined(_SPECULAR_OCCLUSION_FROM_AO_BENT_NORMAL) + // If we have bent normal and ambient occlusion, process a specular occlusion + surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData.normalWS, surfaceData.ambientOcclusion, PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness)); + #elif defined(_AMBIENT_OCCLUSION) && defined(_SPECULAR_OCCLUSION_FROM_AO) + surfaceData.specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(ClampNdotV(dot(surfaceData.normalWS, V)), surfaceData.ambientOcclusion, PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness)); + #endif + + #if defined(_ENABLE_GEOMETRIC_SPECULAR_AA) && !defined(SHADER_STAGE_RAY_TRACING) + surfaceData.perceptualSmoothness = GeometricNormalFiltering(surfaceData.perceptualSmoothness, fragInputs.tangentToWorld[2], surfaceDescription.SpecularAAScreenSpaceVariance, surfaceDescription.SpecularAAThreshold); + #endif + } + + // -------------------------------------------------- + // Get Surface And BuiltinData + + void GetSurfaceAndBuiltinData(FragInputs fragInputs, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData RAY_TRACING_OPTIONAL_PARAMETERS) + { + // 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 + LODDitheringTransition(ComputeFadeMaskSeed(V, posInput.positionSS), unity_LODFade.x); + #endif + #endif + + #ifndef SHADER_UNLIT + #ifdef _DOUBLESIDED_ON + float3 doubleSidedConstants = _DoubleSidedConstants.xyz; + #else + float3 doubleSidedConstants = float3(1.0, 1.0, 1.0); + #endif + + ApplyDoubleSidedFlipOrMirror(fragInputs, doubleSidedConstants); // Apply double sided flip on the vertex normal + #endif // SHADER_UNLIT + + SurfaceDescriptionInputs surfaceDescriptionInputs = FragInputsToSurfaceDescriptionInputs(fragInputs, V); + + #if defined(HAVE_VFX_MODIFICATION) + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + GetElementPixelProperties(fragInputs, properties); + + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs, properties); + #else + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs); + #endif + + // Perform alpha test very early to save performance (a killed pixel will not sample textures) + // TODO: split graph evaluation to grab just alpha dependencies first? tricky.. + #ifdef _ALPHATEST_ON + float alphaCutoff = surfaceDescription.AlphaClipThreshold; + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + // The TransparentDepthPrepass is also used with SSR transparent. + // If an artists enable transaprent SSR but not the TransparentDepthPrepass itself, then we use AlphaClipThreshold + // otherwise if TransparentDepthPrepass is enabled we use AlphaClipThresholdDepthPrepass + #elif SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_POSTPASS + // DepthPostpass always use its own alpha threshold + alphaCutoff = surfaceDescription.AlphaClipThresholdDepthPostpass; + #elif (SHADERPASS == SHADERPASS_SHADOWS) || (SHADERPASS == SHADERPASS_RAYTRACING_VISIBILITY) + // If use shadow threshold isn't enable we don't allow any test + #endif + + GENERIC_ALPHA_TEST(surfaceDescription.Alpha, alphaCutoff); + #endif + + #if !defined(SHADER_STAGE_RAY_TRACING) && _DEPTHOFFSET_ON + ApplyDepthOffsetPositionInput(V, surfaceDescription.DepthOffset, GetViewForwardDir(), GetWorldToHClipMatrix(), posInput); + #endif + + #ifndef SHADER_UNLIT + float3 bentNormalWS; + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData, bentNormalWS); + + #ifdef FRAG_INPUTS_USE_TEXCOORD1 + float4 lightmapTexCoord1 = fragInputs.texCoord1; + #else + float4 lightmapTexCoord1 = float4(0,0,0,0); + #endif + + #ifdef FRAG_INPUTS_USE_TEXCOORD2 + float4 lightmapTexCoord2 = fragInputs.texCoord2; + #else + float4 lightmapTexCoord2 = float4(0,0,0,0); + #endif + + // Builtin Data + // For back lighting we use the oposite vertex normal + InitBuiltinData(posInput, surfaceDescription.Alpha, bentNormalWS, -fragInputs.tangentToWorld[2], lightmapTexCoord1, lightmapTexCoord2, builtinData); + + #else + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData); + + ZERO_BUILTIN_INITIALIZE(builtinData); // No call to InitBuiltinData as we don't have any lighting + builtinData.opacity = surfaceDescription.Alpha; + + #if defined(DEBUG_DISPLAY) + // Light Layers are currently not used for the Unlit shader (because it is not lit) + // But Unlit objects do cast shadows according to their rendering layer mask, which is what we want to + // display in the light layers visualization mode, therefore we need the renderingLayers + builtinData.renderingLayers = GetMeshRenderingLightLayer(); + #endif + + #endif // SHADER_UNLIT + + #ifdef _ALPHATEST_ON + // Used for sharpening by alpha to mask - Alpha to covertage is only used with depth only and forward pass (no shadow pass, no transparent pass) + builtinData.alphaClipTreshold = alphaCutoff; + #endif + + // override sampleBakedGI - not used by Unlit + + builtinData.emissiveColor = surfaceDescription.Emission; + + // Note this will not fully work on transparent surfaces (can check with _SURFACE_TYPE_TRANSPARENT define) + // We will always overwrite vt feeback with the nearest. So behind transparent surfaces vt will not be resolved + // This is a limitation of the current MRT approach. + #ifdef UNITY_VIRTUAL_TEXTURING + #endif + + #if _DEPTHOFFSET_ON + builtinData.depthOffset = surfaceDescription.DepthOffset; + #endif + + // TODO: We should generate distortion / distortionBlur for non distortion pass + #if (SHADERPASS == SHADERPASS_DISTORTION) + builtinData.distortion = surfaceDescription.Distortion; + builtinData.distortionBlur = surfaceDescription.DistortionBlur; + #endif + + #ifndef SHADER_UNLIT + // PostInitBuiltinData call ApplyDebugToBuiltinData + PostInitBuiltinData(V, posInput, surfaceData, builtinData); + #else + ApplyDebugToBuiltinData(builtinData); + #endif + + RAY_TRACING_OPTIONAL_ALPHA_TEST_PASS + } + + // -------------------------------------------------- + // Main + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassFullScreenDebug.hlsl" + + // -------------------------------------------------- + // Visual Effect Vertex Invocations + + #ifdef HAVE_VFX_MODIFICATION + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/VisualEffectVertex.hlsl" + #endif + + ENDHLSL + } + Pass + { + Name "DepthOnly" + Tags + { + "LightMode" = "DepthOnly" + } + + // Render State + Cull [_CullMode] + ZWrite On + Stencil + { + WriteMask [_StencilWriteMaskDepth] + Ref [_StencilRefDepth] + CompFront Always + PassFront Replace + CompBack Always + PassBack Replace + } + + // Debug + // + + // -------------------------------------------------- + // Pass + + HLSLPROGRAM + + // Pragmas + #pragma multi_compile _ DOTS_INSTANCING_ON + #pragma instancing_options renderinglayer + #pragma target 4.5 + #pragma vertex Vert + #pragma fragment Frag + #pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch + #pragma multi_compile_instancing + + // Keywords + #pragma multi_compile _ WRITE_NORMAL_BUFFER + #pragma multi_compile_fragment _ WRITE_MSAA_DEPTH + #pragma shader_feature _ _SURFACE_TYPE_TRANSPARENT + #pragma shader_feature_local _ _DOUBLESIDED_ON + #pragma shader_feature_local _ _ADD_PRECOMPUTED_VELOCITY + #pragma shader_feature_local _ _TRANSPARENT_WRITES_MOTION_VEC + #pragma shader_feature_local_fragment _ _ENABLE_FOG_ON_TRANSPARENT + #pragma shader_feature_local_fragment _ _DISABLE_DECALS + #pragma shader_feature_local_raytracing _ _DISABLE_DECALS + #pragma shader_feature_local_fragment _ _DISABLE_SSR + #pragma shader_feature_local_raytracing _ _DISABLE_SSR + #pragma shader_feature_local_fragment _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local_raytracing _ _DISABLE_SSR_TRANSPARENT + #pragma multi_compile _ WRITE_DECAL_BUFFER + #pragma shader_feature_local _ _REFRACTION_PLANE _REFRACTION_SPHERE _REFRACTION_THIN + // GraphKeywords: + + // For custom interpolators to inject a substruct definition before FragInputs definition, + // allowing for FragInputs to capture CI's intended for ShaderGraph's SDI. + struct CustomInterpolators + { + }; + #define USE_CUSTOMINTERP_SUBSTRUCT + + + + // TODO: Merge FragInputsVFX substruct with CustomInterpolators. + #ifdef HAVE_VFX_MODIFICATION + struct FragInputsVFX + { + /* WARNING: $splice Could not find named fragment 'FragInputsVFX' */ + }; + #endif + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl" // Required by Tessellation.hlsl + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Tessellation.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Texture.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl" // Required to be include before we include properties as it define DECLARE_STACK_CB + // Always include Shader Graph version + // Always include last to avoid double macros + #include "Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl" // Need to be here for Gradient struct definition + + // -------------------------------------------------- + // Defines + + // Attribute + #define ATTRIBUTES_NEED_NORMAL + #define ATTRIBUTES_NEED_TANGENT + #define VARYINGS_NEED_TANGENT_TO_WORLD + + #define HAVE_MESH_MODIFICATION + + //Strip down the FragInputs.hlsl (on graphics), so we can only optimize the interpolators we use. + //if by accident something requests contents of FragInputs.hlsl, it will be caught as a compiler error + //Frag inputs stripping is only enabled when FRAG_INPUTS_ENABLE_STRIPPING is set + #if !defined(SHADER_STAGE_RAY_TRACING) && SHADERPASS != SHADERPASS_RAYTRACING_GBUFFER && SHADERPASS != SHADERPASS_FULL_SCREEN_DEBUG + #define FRAG_INPUTS_ENABLE_STRIPPING + #endif + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl" + + + + #define SHADERPASS SHADERPASS_DEPTH_ONLY + #define RAYTRACING_SHADER_GRAPH_DEFAULT + + + // Following two define are a workaround introduce in 10.1.x for RaytracingQualityNode + // The ShaderGraph don't support correctly migration of this node as it serialize all the node data + // in the json file making it impossible to uprgrade. Until we get a fix, we do a workaround here + // to still allow us to rename the field and keyword of this node without breaking existing code. + #ifdef RAYTRACING_SHADER_GRAPH_DEFAULT + #define RAYTRACING_SHADER_GRAPH_HIGH + #endif + + #ifdef RAYTRACING_SHADER_GRAPH_RAYTRACED + #define RAYTRACING_SHADER_GRAPH_LOW + #endif + // end + + #ifndef SHADER_UNLIT + // We need isFrontFace when using double sided - it is not required for unlit as in case of unlit double sided only drive the cullmode + // VARYINGS_NEED_CULLFACE can be define by VaryingsMeshToPS.FaceSign input if a IsFrontFace Node is included in the shader graph. + #if defined(_DOUBLESIDED_ON) && !defined(VARYINGS_NEED_CULLFACE) + #define VARYINGS_NEED_CULLFACE + #endif + #endif + + // Specific Material Define + #define _SPECULAR_OCCLUSION_FROM_AO 1 + #define _ENERGY_CONSERVING_SPECULAR 1 + + // If we use subsurface scattering, enable output split lighting (for forward pass) + #if defined(_MATERIAL_FEATURE_SUBSURFACE_SCATTERING) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define OUTPUT_SPLIT_LIGHTING + #endif + + // This shader support recursive rendering for raytracing + #define HAVE_RECURSIVE_RENDERING + + // In Path Tracing, For all single-sided, refractive materials, we want to force a thin refraction model + #if (SHADERPASS == SHADERPASS_PATH_TRACING) && !defined(_DOUBLESIDED_ON) && (defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE)) + #undef _REFRACTION_PLANE + #undef _REFRACTION_SPHERE + #define _REFRACTION_THIN + #endif + // Caution: we can use the define SHADER_UNLIT onlit after the above Material include as it is the Unlit template who define it + + // To handle SSR on transparent correctly with a possibility to enable/disable it per framesettings + // we should have a code like this: + // if !defined(_DISABLE_SSR_TRANSPARENT) + // pragma multi_compile _ WRITE_NORMAL_BUFFER + // endif + // i.e we enable the multicompile only if we can receive SSR or not, and then C# code drive + // it based on if SSR transparent in frame settings and not (and stripper can strip it). + // this is currently not possible with our current preprocessor as _DISABLE_SSR_TRANSPARENT is a keyword not a define + // so instead we used this and chose to pay the extra cost of normal write even if SSR transaprent is disabled. + // Ideally the shader graph generator should handle it but condition below can't be handle correctly for now. + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + #if !defined(_DISABLE_SSR_TRANSPARENT) && !defined(SHADER_UNLIT) + #define WRITE_NORMAL_BUFFER + #endif + #endif + + #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) + // Don't do it with debug display mode as it is possible there is no depth prepass in this case + #if !defined(_SURFACE_TYPE_TRANSPARENT) + #if SHADERPASS == SHADERPASS_FORWARD + #define SHADERPASS_FORWARD_BYPASS_ALPHA_TEST + #elif SHADERPASS == SHADERPASS_GBUFFER + #define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST + #endif + #endif + #endif + + // Define _DEFERRED_CAPABLE_MATERIAL for shader capable to run in deferred pass + #if defined(SHADER_LIT) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define _DEFERRED_CAPABLE_MATERIAL + #endif + + // Translate transparent motion vector define + #if defined(_TRANSPARENT_WRITES_MOTION_VEC) && defined(_SURFACE_TYPE_TRANSPARENT) + #define _WRITE_TRANSPARENT_MOTION_VECTOR + #endif + + // -- Graph Properties + CBUFFER_START(UnityPerMaterial) + float4 _Color; + float4 _EmissionColor; + float _UseShadowThreshold; + float4 _DoubleSidedConstants; + float _BlendMode; + float _EnableBlendModePreserveSpecularLighting; + float _RayTracing; + float _RefractionModel; + CBUFFER_END + + + // Object and Global properties + + // -- Property used by ScenePickingPass + #ifdef SCENEPICKINGPASS + float4 _SelectionID; + #endif + + // -- Properties used by SceneSelectionPass + #ifdef SCENESELECTIONPASS + int _ObjectId; + int _PassValue; + #endif + + // Includes + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugDisplay.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/NormalSurfaceGradient.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/Lit.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/BuiltinUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/MaterialUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Decal/DecalUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitDecalData.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderGraphFunctions.hlsl" + // GraphIncludes: + + // -------------------------------------------------- + // Structs and Packing + + struct AttributesMesh + { + float3 positionOS : POSITION; + float3 normalOS : NORMAL; + float4 tangentOS : TANGENT; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : INSTANCEID_SEMANTIC; + #endif + }; + struct VaryingsMeshToPS + { + SV_POSITION_QUALIFIERS float4 positionCS : SV_POSITION; + float3 normalWS; + float4 tangentWS; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : CUSTOM_INSTANCE_ID; + #endif + }; + struct VertexDescriptionInputs + { + float3 ObjectSpaceNormal; + float3 ObjectSpaceTangent; + float3 ObjectSpacePosition; + }; + struct SurfaceDescriptionInputs + { + float3 TangentSpaceNormal; + }; + struct PackedVaryingsMeshToPS + { + SV_POSITION_QUALIFIERS float4 positionCS : SV_POSITION; + float4 tangentWS : INTERP0; + float3 normalWS : INTERP1; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : CUSTOM_INSTANCE_ID; + #endif + }; + + PackedVaryingsMeshToPS PackVaryingsMeshToPS (VaryingsMeshToPS input) + { + PackedVaryingsMeshToPS output; + ZERO_INITIALIZE(PackedVaryingsMeshToPS, output); + output.positionCS = input.positionCS; + output.tangentWS.xyzw = input.tangentWS; + output.normalWS.xyz = input.normalWS; + #if UNITY_ANY_INSTANCING_ENABLED + output.instanceID = input.instanceID; + #endif + return output; + } + + VaryingsMeshToPS UnpackVaryingsMeshToPS (PackedVaryingsMeshToPS input) + { + VaryingsMeshToPS output; + output.positionCS = input.positionCS; + output.tangentWS = input.tangentWS.xyzw; + output.normalWS = input.normalWS.xyz; + #if UNITY_ANY_INSTANCING_ENABLED + output.instanceID = input.instanceID; + #endif + return output; + } + + + // -------------------------------------------------- + // Graph + + + // Graph Functions + // GraphFunctions: + + // Graph Vertex + struct VertexDescription + { + float3 Position; + float3 Normal; + float3 Tangent; + }; + + VertexDescription VertexDescriptionFunction(VertexDescriptionInputs IN) + { + VertexDescription description = (VertexDescription)0; + description.Position = IN.ObjectSpacePosition; + description.Normal = IN.ObjectSpaceNormal; + description.Tangent = IN.ObjectSpaceTangent; + return description; + } + + // Graph Pixel + struct SurfaceDescription + { + float3 BaseColor; + float3 Emission; + float Alpha; + float3 BentNormal; + float Smoothness; + float Occlusion; + float3 NormalTS; + float Metallic; + }; + + SurfaceDescription SurfaceDescriptionFunction(SurfaceDescriptionInputs IN) + { + SurfaceDescription surface = (SurfaceDescription)0; + float4 _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4 = _Color; + float _Split_cace9cff304a4c5d84b5305897d09aa9_R_1_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[0]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_G_2_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[1]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_B_3_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[2]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[3]; + surface.BaseColor = (_Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4.xyz); + surface.Emission = float3(0, 0, 0); + surface.Alpha = _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float; + surface.BentNormal = IN.TangentSpaceNormal; + surface.Smoothness = 0.5; + surface.Occlusion = 1; + surface.NormalTS = IN.TangentSpaceNormal; + surface.Metallic = 0; + return surface; + } + + // -------------------------------------------------- + // Build Graph Inputs + #ifdef HAVE_VFX_MODIFICATION + #define VFX_SRP_ATTRIBUTES AttributesMesh + #define VaryingsMeshType VaryingsMeshToPS + #define VFX_SRP_VARYINGS VaryingsMeshType + #define VFX_SRP_SURFACE_INPUTS FragInputs + #endif + + VertexDescriptionInputs AttributesMeshToVertexDescriptionInputs(AttributesMesh input) + { + VertexDescriptionInputs output; + ZERO_INITIALIZE(VertexDescriptionInputs, output); + + output.ObjectSpaceNormal = input.normalOS; + output.ObjectSpaceTangent = input.tangentOS.xyz; + output.ObjectSpacePosition = input.positionOS; + + return output; + } + + VertexDescription GetVertexDescription(AttributesMesh input, float3 timeParameters + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + // build graph inputs + VertexDescriptionInputs vertexDescriptionInputs = AttributesMeshToVertexDescriptionInputs(input); + // Override time parameters with used one (This is required to correctly handle motion vectors for vertex animation based on time) + + // evaluate vertex graph + #ifdef HAVE_VFX_MODIFICATION + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + // Fetch the vertex graph properties for the particle instance. + GetElementVertexProperties(element, properties); + + VertexDescription vertexDescription = VertexDescriptionFunction(vertexDescriptionInputs, properties); + #else + VertexDescription vertexDescription = VertexDescriptionFunction(vertexDescriptionInputs); + #endif + return vertexDescription; + + } + + AttributesMesh ApplyMeshModification(AttributesMesh input, float3 timeParameters + #ifdef USE_CUSTOMINTERP_SUBSTRUCT + #ifdef TESSELLATION_ON + , inout VaryingsMeshToDS varyings + #else + , inout VaryingsMeshToPS varyings + #endif + #endif + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + VertexDescription vertexDescription = GetVertexDescription(input, timeParameters + #ifdef HAVE_VFX_MODIFICATION + , element + #endif + ); + + // copy graph output to the results + input.positionOS = vertexDescription.Position; + input.normalOS = vertexDescription.Normal; + input.tangentOS.xyz = vertexDescription.Tangent; + + + + return input; + } + + #if defined(_ADD_CUSTOM_VELOCITY) // For shader graph custom velocity + // Return precomputed Velocity in object space + float3 GetCustomVelocity(AttributesMesh input + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + VertexDescription vertexDescription = GetVertexDescription(input, _TimeParameters.xyz + #ifdef HAVE_VFX_MODIFICATION + , element + #endif + ); + return vertexDescription.CustomVelocity; + } + #endif + + FragInputs BuildFragInputs(VaryingsMeshToPS input) + { + FragInputs output; + ZERO_INITIALIZE(FragInputs, output); + + // Init to some default value to make the computer quiet (else it output 'divide by zero' warning even if value is not used). + // TODO: this is a really poor workaround, but the variable is used in a bunch of places + // to compute normals which are then passed on elsewhere to compute other values... + output.tangentToWorld = k_identity3x3; + output.positionSS = input.positionCS; // input.positionCS is SV_Position + + output.tangentToWorld = BuildTangentToWorld(input.tangentWS, input.normalWS); + + #ifdef HAVE_VFX_MODIFICATION + // FragInputs from VFX come from two places: Interpolator or CBuffer. + #if VFX_USE_GRAPH_VALUES + uint instanceActiveIndex = asuint(UNITY_ACCESS_INSTANCED_PROP(PerInstance, _InstanceActiveIndex)); + /* WARNING: $splice Could not find named fragment 'VFXLoadGraphValues' */ + #endif + + /* WARNING: $splice Could not find named fragment 'VFXSetFragInputs' */ + + #endif + + // splice point to copy custom interpolator fields from varyings to frag inputs + + + return output; + } + + // existing HDRP code uses the combined function to go directly from packed to frag inputs + FragInputs UnpackVaryingsMeshToFragInputs(PackedVaryingsMeshToPS input) + { + UNITY_SETUP_INSTANCE_ID(input); + #if defined(HAVE_VFX_MODIFICATION) && defined(UNITY_INSTANCING_ENABLED) + unity_InstanceID = input.instanceID; + #endif + VaryingsMeshToPS unpacked = UnpackVaryingsMeshToPS(input); + return BuildFragInputs(unpacked); + } + SurfaceDescriptionInputs FragInputsToSurfaceDescriptionInputs(FragInputs input, float3 viewWS) + { + SurfaceDescriptionInputs output; + ZERO_INITIALIZE(SurfaceDescriptionInputs, output); + + #if defined(SHADER_STAGE_RAY_TRACING) + #else + #endif + output.TangentSpaceNormal = float3(0.0f, 0.0f, 1.0f); + + #if UNITY_UV_STARTS_AT_TOP + #else + #endif + + + + // splice point to copy frag inputs custom interpolator pack into the SDI + + + return output; + } + + // -------------------------------------------------- + // Build Surface Data (Specific Material) + + void ApplyDecalToSurfaceDataNoNormal(DecalSurfaceData decalSurfaceData, inout SurfaceData surfaceData); + + void ApplyDecalAndGetNormal(FragInputs fragInputs, PositionInputs posInput, SurfaceDescription surfaceDescription, + inout SurfaceData surfaceData) + { + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + #ifdef DECAL_NORMAL_BLENDING + // SG nodes don't ouptut surface gradients, so if decals require surf grad blending, we have to convert + // the normal to gradient before applying the decal. We then have to resolve the gradient back to world space + float3 normalTS; + + normalTS = SurfaceGradientFromTangentSpaceNormalAndFromTBN(surfaceDescription.NormalTS, + fragInputs.tangentToWorld[0], fragInputs.tangentToWorld[1]); + + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, fragInputs.tangentToWorld[2], normalTS); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + + GetNormalWS_SG(fragInputs, normalTS, surfaceData.normalWS, doubleSidedConstants); + #else + // normal delivered to master node + GetNormalWS(fragInputs, surfaceDescription.NormalTS, surfaceData.normalWS, doubleSidedConstants); + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + // Both uses and modifies 'surfaceData.normalWS'. + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, surfaceData.normalWS.xyz); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + #endif + } + void BuildSurfaceData(FragInputs fragInputs, inout SurfaceDescription surfaceDescription, float3 V, PositionInputs posInput, out SurfaceData surfaceData, out float3 bentNormalWS) + { + ZERO_INITIALIZE(SurfaceData, surfaceData); + + // specularOcclusion need to be init ahead of decal to quiet the compiler that modify the SurfaceData struct + // however specularOcclusion can come from the graph, so need to be init here so it can be override. + surfaceData.specularOcclusion = 1.0; + + surfaceData.baseColor = surfaceDescription.BaseColor; + surfaceData.perceptualSmoothness = surfaceDescription.Smoothness; + surfaceData.ambientOcclusion = surfaceDescription.Occlusion; + surfaceData.metallic = surfaceDescription.Metallic; + + #if defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE) || defined(_REFRACTION_THIN) + if (_EnableSSRefraction) + { + + surfaceData.transmittanceMask = (1.0 - surfaceDescription.Alpha); + surfaceDescription.Alpha = 1.0; + } + else + { + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + surfaceDescription.Alpha = 1.0; + } + #else + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + #endif + + // These static material feature allow compile time optimization + surfaceData.materialFeatures = MATERIALFEATUREFLAGS_LIT_STANDARD; + #ifdef _MATERIAL_FEATURE_SUBSURFACE_SCATTERING + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING; + #endif + + #ifdef _MATERIAL_FEATURE_TRANSMISSION + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_TRANSMISSION; + #endif + + #ifdef _MATERIAL_FEATURE_ANISOTROPY + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_ANISOTROPY; + + // Initialize the normal to something non-zero to avoid a div-zero warning for anisotropy. + surfaceData.normalWS = float3(0, 1, 0); + #endif + + #ifdef _MATERIAL_FEATURE_IRIDESCENCE + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_IRIDESCENCE; + #endif + + #ifdef _MATERIAL_FEATURE_SPECULAR_COLOR + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR; + #endif + + #ifdef _MATERIAL_FEATURE_CLEAR_COAT + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_CLEAR_COAT; + #endif + + #if defined (_MATERIAL_FEATURE_SPECULAR_COLOR) && defined (_ENERGY_CONSERVING_SPECULAR) + // Require to have setup baseColor + // Reproduce the energy conservation done in legacy Unity. Not ideal but better for compatibility and users can unchek it + surfaceData.baseColor *= (1.0 - Max3(surfaceData.specularColor.r, surfaceData.specularColor.g, surfaceData.specularColor.b)); + #endif + + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + ApplyDecalAndGetNormal(fragInputs, posInput, surfaceDescription, surfaceData); + + surfaceData.geomNormalWS = fragInputs.tangentToWorld[2]; + + surfaceData.tangentWS = normalize(fragInputs.tangentToWorld[0].xyz); // The tangent is not normalize in tangentToWorld for mikkt. TODO: Check if it expected that we normalize with Morten. Tag: SURFACE_GRADIENT + + + bentNormalWS = surfaceData.normalWS; + + surfaceData.tangentWS = Orthonormalize(surfaceData.tangentWS, surfaceData.normalWS); + + #ifdef DEBUG_DISPLAY + if (_DebugMipMapMode != DEBUGMIPMAPMODE_NONE) + { + // TODO: need to update mip info + surfaceData.metallic = 0; + } + + // We need to call ApplyDebugToSurfaceData after filling the surfarcedata and before filling builtinData + // as it can modify attribute use for static lighting + ApplyDebugToSurfaceData(fragInputs.tangentToWorld, surfaceData); + #endif + + // By default we use the ambient occlusion with Tri-ace trick (apply outside) for specular occlusion. + // If user provide bent normal then we process a better term + #if defined(_SPECULAR_OCCLUSION_CUSTOM) + // Just use the value passed through via the slot (not active otherwise) + #elif defined(_SPECULAR_OCCLUSION_FROM_AO_BENT_NORMAL) + // If we have bent normal and ambient occlusion, process a specular occlusion + surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData.normalWS, surfaceData.ambientOcclusion, PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness)); + #elif defined(_AMBIENT_OCCLUSION) && defined(_SPECULAR_OCCLUSION_FROM_AO) + surfaceData.specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(ClampNdotV(dot(surfaceData.normalWS, V)), surfaceData.ambientOcclusion, PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness)); + #endif + + #if defined(_ENABLE_GEOMETRIC_SPECULAR_AA) && !defined(SHADER_STAGE_RAY_TRACING) + surfaceData.perceptualSmoothness = GeometricNormalFiltering(surfaceData.perceptualSmoothness, fragInputs.tangentToWorld[2], surfaceDescription.SpecularAAScreenSpaceVariance, surfaceDescription.SpecularAAThreshold); + #endif + } + + // -------------------------------------------------- + // Get Surface And BuiltinData + + void GetSurfaceAndBuiltinData(FragInputs fragInputs, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData RAY_TRACING_OPTIONAL_PARAMETERS) + { + // 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 + LODDitheringTransition(ComputeFadeMaskSeed(V, posInput.positionSS), unity_LODFade.x); + #endif + #endif + + #ifndef SHADER_UNLIT + #ifdef _DOUBLESIDED_ON + float3 doubleSidedConstants = _DoubleSidedConstants.xyz; + #else + float3 doubleSidedConstants = float3(1.0, 1.0, 1.0); + #endif + + ApplyDoubleSidedFlipOrMirror(fragInputs, doubleSidedConstants); // Apply double sided flip on the vertex normal + #endif // SHADER_UNLIT + + SurfaceDescriptionInputs surfaceDescriptionInputs = FragInputsToSurfaceDescriptionInputs(fragInputs, V); + + #if defined(HAVE_VFX_MODIFICATION) + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + GetElementPixelProperties(fragInputs, properties); + + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs, properties); + #else + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs); + #endif + + // Perform alpha test very early to save performance (a killed pixel will not sample textures) + // TODO: split graph evaluation to grab just alpha dependencies first? tricky.. + #ifdef _ALPHATEST_ON + float alphaCutoff = surfaceDescription.AlphaClipThreshold; + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + // The TransparentDepthPrepass is also used with SSR transparent. + // If an artists enable transaprent SSR but not the TransparentDepthPrepass itself, then we use AlphaClipThreshold + // otherwise if TransparentDepthPrepass is enabled we use AlphaClipThresholdDepthPrepass + #elif SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_POSTPASS + // DepthPostpass always use its own alpha threshold + alphaCutoff = surfaceDescription.AlphaClipThresholdDepthPostpass; + #elif (SHADERPASS == SHADERPASS_SHADOWS) || (SHADERPASS == SHADERPASS_RAYTRACING_VISIBILITY) + // If use shadow threshold isn't enable we don't allow any test + #endif + + GENERIC_ALPHA_TEST(surfaceDescription.Alpha, alphaCutoff); + #endif + + #if !defined(SHADER_STAGE_RAY_TRACING) && _DEPTHOFFSET_ON + ApplyDepthOffsetPositionInput(V, surfaceDescription.DepthOffset, GetViewForwardDir(), GetWorldToHClipMatrix(), posInput); + #endif + + #ifndef SHADER_UNLIT + float3 bentNormalWS; + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData, bentNormalWS); + + #ifdef FRAG_INPUTS_USE_TEXCOORD1 + float4 lightmapTexCoord1 = fragInputs.texCoord1; + #else + float4 lightmapTexCoord1 = float4(0,0,0,0); + #endif + + #ifdef FRAG_INPUTS_USE_TEXCOORD2 + float4 lightmapTexCoord2 = fragInputs.texCoord2; + #else + float4 lightmapTexCoord2 = float4(0,0,0,0); + #endif + + // Builtin Data + // For back lighting we use the oposite vertex normal + InitBuiltinData(posInput, surfaceDescription.Alpha, bentNormalWS, -fragInputs.tangentToWorld[2], lightmapTexCoord1, lightmapTexCoord2, builtinData); + + #else + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData); + + ZERO_BUILTIN_INITIALIZE(builtinData); // No call to InitBuiltinData as we don't have any lighting + builtinData.opacity = surfaceDescription.Alpha; + + #if defined(DEBUG_DISPLAY) + // Light Layers are currently not used for the Unlit shader (because it is not lit) + // But Unlit objects do cast shadows according to their rendering layer mask, which is what we want to + // display in the light layers visualization mode, therefore we need the renderingLayers + builtinData.renderingLayers = GetMeshRenderingLightLayer(); + #endif + + #endif // SHADER_UNLIT + + #ifdef _ALPHATEST_ON + // Used for sharpening by alpha to mask - Alpha to covertage is only used with depth only and forward pass (no shadow pass, no transparent pass) + builtinData.alphaClipTreshold = alphaCutoff; + #endif + + // override sampleBakedGI - not used by Unlit + + builtinData.emissiveColor = surfaceDescription.Emission; + + // Note this will not fully work on transparent surfaces (can check with _SURFACE_TYPE_TRANSPARENT define) + // We will always overwrite vt feeback with the nearest. So behind transparent surfaces vt will not be resolved + // This is a limitation of the current MRT approach. + #ifdef UNITY_VIRTUAL_TEXTURING + #endif + + #if _DEPTHOFFSET_ON + builtinData.depthOffset = surfaceDescription.DepthOffset; + #endif + + // TODO: We should generate distortion / distortionBlur for non distortion pass + #if (SHADERPASS == SHADERPASS_DISTORTION) + builtinData.distortion = surfaceDescription.Distortion; + builtinData.distortionBlur = surfaceDescription.DistortionBlur; + #endif + + #ifndef SHADER_UNLIT + // PostInitBuiltinData call ApplyDebugToBuiltinData + PostInitBuiltinData(V, posInput, surfaceData, builtinData); + #else + ApplyDebugToBuiltinData(builtinData); + #endif + + RAY_TRACING_OPTIONAL_ALPHA_TEST_PASS + } + + // -------------------------------------------------- + // Main + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassDepthOnly.hlsl" + + // -------------------------------------------------- + // Visual Effect Vertex Invocations + + #ifdef HAVE_VFX_MODIFICATION + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/VisualEffectVertex.hlsl" + #endif + + ENDHLSL + } + Pass + { + Name "GBuffer" + Tags + { + "LightMode" = "GBuffer" + } + + // Render State + Cull [_CullMode] + ZTest [_ZTestGBuffer] + ColorMask [_LightLayersMaskBuffer4] 4 + ColorMask [_LightLayersMaskBuffer5] 5 + Stencil + { + WriteMask [_StencilWriteMaskGBuffer] + Ref [_StencilRefGBuffer] + CompFront Always + PassFront Replace + CompBack Always + PassBack Replace + } + + // Debug + // + + // -------------------------------------------------- + // Pass + + HLSLPROGRAM + + // Pragmas + #pragma multi_compile _ DOTS_INSTANCING_ON + #pragma instancing_options renderinglayer + #pragma target 4.5 + #pragma vertex Vert + #pragma fragment Frag + #pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch + #pragma multi_compile_instancing + + // Keywords + #pragma multi_compile_fragment _ LIGHT_LAYERS + #pragma multi_compile_raytracing _ LIGHT_LAYERS + #pragma shader_feature _ _SURFACE_TYPE_TRANSPARENT + #pragma shader_feature_local _ _DOUBLESIDED_ON + #pragma shader_feature_local _ _ADD_PRECOMPUTED_VELOCITY + #pragma shader_feature_local _ _TRANSPARENT_WRITES_MOTION_VEC + #pragma shader_feature_local_fragment _ _ENABLE_FOG_ON_TRANSPARENT + #pragma multi_compile _ DEBUG_DISPLAY + #pragma shader_feature_local_fragment _ _DISABLE_DECALS + #pragma shader_feature_local_raytracing _ _DISABLE_DECALS + #pragma shader_feature_local_fragment _ _DISABLE_SSR + #pragma shader_feature_local_raytracing _ _DISABLE_SSR + #pragma shader_feature_local_fragment _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local_raytracing _ _DISABLE_SSR_TRANSPARENT + #pragma multi_compile _ LIGHTMAP_ON + #pragma multi_compile _ DIRLIGHTMAP_COMBINED + #pragma multi_compile_fragment PROBE_VOLUMES_OFF PROBE_VOLUMES_L1 PROBE_VOLUMES_L2 + #pragma multi_compile_raytracing PROBE_VOLUMES_OFF PROBE_VOLUMES_L1 PROBE_VOLUMES_L2 + #pragma multi_compile _ DYNAMICLIGHTMAP_ON + #pragma multi_compile_fragment _ SHADOWS_SHADOWMASK + #pragma multi_compile_raytracing _ SHADOWS_SHADOWMASK + #pragma multi_compile_fragment DECALS_OFF DECALS_3RT DECALS_4RT + #pragma multi_compile_fragment _ DECAL_SURFACE_GRADIENT + #pragma shader_feature_local _ _REFRACTION_PLANE _REFRACTION_SPHERE _REFRACTION_THIN + // GraphKeywords: + + // For custom interpolators to inject a substruct definition before FragInputs definition, + // allowing for FragInputs to capture CI's intended for ShaderGraph's SDI. + struct CustomInterpolators + { + }; + #define USE_CUSTOMINTERP_SUBSTRUCT + + + + // TODO: Merge FragInputsVFX substruct with CustomInterpolators. + #ifdef HAVE_VFX_MODIFICATION + struct FragInputsVFX + { + /* WARNING: $splice Could not find named fragment 'FragInputsVFX' */ + }; + #endif + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl" // Required by Tessellation.hlsl + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Tessellation.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Texture.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl" // Required to be include before we include properties as it define DECLARE_STACK_CB + // Always include Shader Graph version + // Always include last to avoid double macros + #include "Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl" // Need to be here for Gradient struct definition + + // -------------------------------------------------- + // Defines + + // Attribute + #define ATTRIBUTES_NEED_NORMAL + #define ATTRIBUTES_NEED_TANGENT + #define ATTRIBUTES_NEED_TEXCOORD1 + #define ATTRIBUTES_NEED_TEXCOORD2 + #define VARYINGS_NEED_POSITION_WS + #define VARYINGS_NEED_TANGENT_TO_WORLD + #define VARYINGS_NEED_TEXCOORD1 + #define VARYINGS_NEED_TEXCOORD2 + + #define HAVE_MESH_MODIFICATION + + //Strip down the FragInputs.hlsl (on graphics), so we can only optimize the interpolators we use. + //if by accident something requests contents of FragInputs.hlsl, it will be caught as a compiler error + //Frag inputs stripping is only enabled when FRAG_INPUTS_ENABLE_STRIPPING is set + #if !defined(SHADER_STAGE_RAY_TRACING) && SHADERPASS != SHADERPASS_RAYTRACING_GBUFFER && SHADERPASS != SHADERPASS_FULL_SCREEN_DEBUG + #define FRAG_INPUTS_ENABLE_STRIPPING + #endif + #define FRAG_INPUTS_USE_TEXCOORD1 + #define FRAG_INPUTS_USE_TEXCOORD2 + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl" + + + + #define SHADERPASS SHADERPASS_GBUFFER + #define RAYTRACING_SHADER_GRAPH_DEFAULT + + + // Following two define are a workaround introduce in 10.1.x for RaytracingQualityNode + // The ShaderGraph don't support correctly migration of this node as it serialize all the node data + // in the json file making it impossible to uprgrade. Until we get a fix, we do a workaround here + // to still allow us to rename the field and keyword of this node without breaking existing code. + #ifdef RAYTRACING_SHADER_GRAPH_DEFAULT + #define RAYTRACING_SHADER_GRAPH_HIGH + #endif + + #ifdef RAYTRACING_SHADER_GRAPH_RAYTRACED + #define RAYTRACING_SHADER_GRAPH_LOW + #endif + // end + + #ifndef SHADER_UNLIT + // We need isFrontFace when using double sided - it is not required for unlit as in case of unlit double sided only drive the cullmode + // VARYINGS_NEED_CULLFACE can be define by VaryingsMeshToPS.FaceSign input if a IsFrontFace Node is included in the shader graph. + #if defined(_DOUBLESIDED_ON) && !defined(VARYINGS_NEED_CULLFACE) + #define VARYINGS_NEED_CULLFACE + #endif + #endif + + // Specific Material Define + #define _SPECULAR_OCCLUSION_FROM_AO 1 + #define _ENERGY_CONSERVING_SPECULAR 1 + + // If we use subsurface scattering, enable output split lighting (for forward pass) + #if defined(_MATERIAL_FEATURE_SUBSURFACE_SCATTERING) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define OUTPUT_SPLIT_LIGHTING + #endif + + // This shader support recursive rendering for raytracing + #define HAVE_RECURSIVE_RENDERING + + // In Path Tracing, For all single-sided, refractive materials, we want to force a thin refraction model + #if (SHADERPASS == SHADERPASS_PATH_TRACING) && !defined(_DOUBLESIDED_ON) && (defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE)) + #undef _REFRACTION_PLANE + #undef _REFRACTION_SPHERE + #define _REFRACTION_THIN + #endif + // Caution: we can use the define SHADER_UNLIT onlit after the above Material include as it is the Unlit template who define it + + // To handle SSR on transparent correctly with a possibility to enable/disable it per framesettings + // we should have a code like this: + // if !defined(_DISABLE_SSR_TRANSPARENT) + // pragma multi_compile _ WRITE_NORMAL_BUFFER + // endif + // i.e we enable the multicompile only if we can receive SSR or not, and then C# code drive + // it based on if SSR transparent in frame settings and not (and stripper can strip it). + // this is currently not possible with our current preprocessor as _DISABLE_SSR_TRANSPARENT is a keyword not a define + // so instead we used this and chose to pay the extra cost of normal write even if SSR transaprent is disabled. + // Ideally the shader graph generator should handle it but condition below can't be handle correctly for now. + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + #if !defined(_DISABLE_SSR_TRANSPARENT) && !defined(SHADER_UNLIT) + #define WRITE_NORMAL_BUFFER + #endif + #endif + + #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) + // Don't do it with debug display mode as it is possible there is no depth prepass in this case + #if !defined(_SURFACE_TYPE_TRANSPARENT) + #if SHADERPASS == SHADERPASS_FORWARD + #define SHADERPASS_FORWARD_BYPASS_ALPHA_TEST + #elif SHADERPASS == SHADERPASS_GBUFFER + #define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST + #endif + #endif + #endif + + // Define _DEFERRED_CAPABLE_MATERIAL for shader capable to run in deferred pass + #if defined(SHADER_LIT) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define _DEFERRED_CAPABLE_MATERIAL + #endif + + // Translate transparent motion vector define + #if defined(_TRANSPARENT_WRITES_MOTION_VEC) && defined(_SURFACE_TYPE_TRANSPARENT) + #define _WRITE_TRANSPARENT_MOTION_VECTOR + #endif + + // -- Graph Properties + CBUFFER_START(UnityPerMaterial) + float4 _Color; + float4 _EmissionColor; + float _UseShadowThreshold; + float4 _DoubleSidedConstants; + float _BlendMode; + float _EnableBlendModePreserveSpecularLighting; + float _RayTracing; + float _RefractionModel; + CBUFFER_END + + + // Object and Global properties + + // -- Property used by ScenePickingPass + #ifdef SCENEPICKINGPASS + float4 _SelectionID; + #endif + + // -- Properties used by SceneSelectionPass + #ifdef SCENESELECTIONPASS + int _ObjectId; + int _PassValue; + #endif + + // Includes + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugDisplay.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/NormalSurfaceGradient.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/Lit.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/BuiltinUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/MaterialUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Decal/DecalUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitDecalData.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderGraphFunctions.hlsl" + // GraphIncludes: + + // -------------------------------------------------- + // Structs and Packing + + struct AttributesMesh + { + float3 positionOS : POSITION; + float3 normalOS : NORMAL; + float4 tangentOS : TANGENT; + float4 uv1 : TEXCOORD1; + float4 uv2 : TEXCOORD2; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : INSTANCEID_SEMANTIC; + #endif + }; + struct VaryingsMeshToPS + { + SV_POSITION_QUALIFIERS float4 positionCS : SV_POSITION; + float3 positionRWS; + float3 normalWS; + float4 tangentWS; + float4 texCoord1; + float4 texCoord2; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : CUSTOM_INSTANCE_ID; + #endif + }; + struct VertexDescriptionInputs + { + float3 ObjectSpaceNormal; + float3 ObjectSpaceTangent; + float3 ObjectSpacePosition; + }; + struct SurfaceDescriptionInputs + { + float3 TangentSpaceNormal; + }; + struct PackedVaryingsMeshToPS + { + SV_POSITION_QUALIFIERS float4 positionCS : SV_POSITION; + float4 tangentWS : INTERP0; + float4 texCoord1 : INTERP1; + float4 texCoord2 : INTERP2; + float3 positionRWS : INTERP3; + float3 normalWS : INTERP4; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : CUSTOM_INSTANCE_ID; + #endif + }; + + PackedVaryingsMeshToPS PackVaryingsMeshToPS (VaryingsMeshToPS input) + { + PackedVaryingsMeshToPS output; + ZERO_INITIALIZE(PackedVaryingsMeshToPS, output); + output.positionCS = input.positionCS; + output.tangentWS.xyzw = input.tangentWS; + output.texCoord1.xyzw = input.texCoord1; + output.texCoord2.xyzw = input.texCoord2; + output.positionRWS.xyz = input.positionRWS; + output.normalWS.xyz = input.normalWS; + #if UNITY_ANY_INSTANCING_ENABLED + output.instanceID = input.instanceID; + #endif + return output; + } + + VaryingsMeshToPS UnpackVaryingsMeshToPS (PackedVaryingsMeshToPS input) + { + VaryingsMeshToPS output; + output.positionCS = input.positionCS; + output.tangentWS = input.tangentWS.xyzw; + output.texCoord1 = input.texCoord1.xyzw; + output.texCoord2 = input.texCoord2.xyzw; + output.positionRWS = input.positionRWS.xyz; + output.normalWS = input.normalWS.xyz; + #if UNITY_ANY_INSTANCING_ENABLED + output.instanceID = input.instanceID; + #endif + return output; + } + + + // -------------------------------------------------- + // Graph + + + // Graph Functions + // GraphFunctions: + + // Graph Vertex + struct VertexDescription + { + float3 Position; + float3 Normal; + float3 Tangent; + }; + + VertexDescription VertexDescriptionFunction(VertexDescriptionInputs IN) + { + VertexDescription description = (VertexDescription)0; + description.Position = IN.ObjectSpacePosition; + description.Normal = IN.ObjectSpaceNormal; + description.Tangent = IN.ObjectSpaceTangent; + return description; + } + + // Graph Pixel + struct SurfaceDescription + { + float3 BaseColor; + float3 Emission; + float Alpha; + float3 BentNormal; + float Smoothness; + float Occlusion; + float3 NormalTS; + float Metallic; + float4 VTPackedFeedback; + }; + + SurfaceDescription SurfaceDescriptionFunction(SurfaceDescriptionInputs IN) + { + SurfaceDescription surface = (SurfaceDescription)0; + float4 _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4 = _Color; + float _Split_cace9cff304a4c5d84b5305897d09aa9_R_1_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[0]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_G_2_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[1]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_B_3_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[2]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[3]; + surface.BaseColor = (_Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4.xyz); + surface.Emission = float3(0, 0, 0); + surface.Alpha = _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float; + surface.BentNormal = IN.TangentSpaceNormal; + surface.Smoothness = 0.5; + surface.Occlusion = 1; + surface.NormalTS = IN.TangentSpaceNormal; + surface.Metallic = 0; + { + surface.VTPackedFeedback = float4(1.0f,1.0f,1.0f,1.0f); + } + return surface; + } + + // -------------------------------------------------- + // Build Graph Inputs + #ifdef HAVE_VFX_MODIFICATION + #define VFX_SRP_ATTRIBUTES AttributesMesh + #define VaryingsMeshType VaryingsMeshToPS + #define VFX_SRP_VARYINGS VaryingsMeshType + #define VFX_SRP_SURFACE_INPUTS FragInputs + #endif + + VertexDescriptionInputs AttributesMeshToVertexDescriptionInputs(AttributesMesh input) + { + VertexDescriptionInputs output; + ZERO_INITIALIZE(VertexDescriptionInputs, output); + + output.ObjectSpaceNormal = input.normalOS; + output.ObjectSpaceTangent = input.tangentOS.xyz; + output.ObjectSpacePosition = input.positionOS; + + return output; + } + + VertexDescription GetVertexDescription(AttributesMesh input, float3 timeParameters + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + // build graph inputs + VertexDescriptionInputs vertexDescriptionInputs = AttributesMeshToVertexDescriptionInputs(input); + // Override time parameters with used one (This is required to correctly handle motion vectors for vertex animation based on time) + + // evaluate vertex graph + #ifdef HAVE_VFX_MODIFICATION + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + // Fetch the vertex graph properties for the particle instance. + GetElementVertexProperties(element, properties); + + VertexDescription vertexDescription = VertexDescriptionFunction(vertexDescriptionInputs, properties); + #else + VertexDescription vertexDescription = VertexDescriptionFunction(vertexDescriptionInputs); + #endif + return vertexDescription; + + } + + AttributesMesh ApplyMeshModification(AttributesMesh input, float3 timeParameters + #ifdef USE_CUSTOMINTERP_SUBSTRUCT + #ifdef TESSELLATION_ON + , inout VaryingsMeshToDS varyings + #else + , inout VaryingsMeshToPS varyings + #endif + #endif + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + VertexDescription vertexDescription = GetVertexDescription(input, timeParameters + #ifdef HAVE_VFX_MODIFICATION + , element + #endif + ); + + // copy graph output to the results + input.positionOS = vertexDescription.Position; + input.normalOS = vertexDescription.Normal; + input.tangentOS.xyz = vertexDescription.Tangent; + + + + return input; + } + + #if defined(_ADD_CUSTOM_VELOCITY) // For shader graph custom velocity + // Return precomputed Velocity in object space + float3 GetCustomVelocity(AttributesMesh input + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + VertexDescription vertexDescription = GetVertexDescription(input, _TimeParameters.xyz + #ifdef HAVE_VFX_MODIFICATION + , element + #endif + ); + return vertexDescription.CustomVelocity; + } + #endif + + FragInputs BuildFragInputs(VaryingsMeshToPS input) + { + FragInputs output; + ZERO_INITIALIZE(FragInputs, output); + + // Init to some default value to make the computer quiet (else it output 'divide by zero' warning even if value is not used). + // TODO: this is a really poor workaround, but the variable is used in a bunch of places + // to compute normals which are then passed on elsewhere to compute other values... + output.tangentToWorld = k_identity3x3; + output.positionSS = input.positionCS; // input.positionCS is SV_Position + + output.positionRWS = input.positionRWS; + output.tangentToWorld = BuildTangentToWorld(input.tangentWS, input.normalWS); + output.texCoord1 = input.texCoord1; + output.texCoord2 = input.texCoord2; + + #ifdef HAVE_VFX_MODIFICATION + // FragInputs from VFX come from two places: Interpolator or CBuffer. + #if VFX_USE_GRAPH_VALUES + uint instanceActiveIndex = asuint(UNITY_ACCESS_INSTANCED_PROP(PerInstance, _InstanceActiveIndex)); + /* WARNING: $splice Could not find named fragment 'VFXLoadGraphValues' */ + #endif + + /* WARNING: $splice Could not find named fragment 'VFXSetFragInputs' */ + + #endif + + // splice point to copy custom interpolator fields from varyings to frag inputs + + + return output; + } + + // existing HDRP code uses the combined function to go directly from packed to frag inputs + FragInputs UnpackVaryingsMeshToFragInputs(PackedVaryingsMeshToPS input) + { + UNITY_SETUP_INSTANCE_ID(input); + #if defined(HAVE_VFX_MODIFICATION) && defined(UNITY_INSTANCING_ENABLED) + unity_InstanceID = input.instanceID; + #endif + VaryingsMeshToPS unpacked = UnpackVaryingsMeshToPS(input); + return BuildFragInputs(unpacked); + } + SurfaceDescriptionInputs FragInputsToSurfaceDescriptionInputs(FragInputs input, float3 viewWS) + { + SurfaceDescriptionInputs output; + ZERO_INITIALIZE(SurfaceDescriptionInputs, output); + + #if defined(SHADER_STAGE_RAY_TRACING) + #else + #endif + output.TangentSpaceNormal = float3(0.0f, 0.0f, 1.0f); + + #if UNITY_UV_STARTS_AT_TOP + #else + #endif + + + + // splice point to copy frag inputs custom interpolator pack into the SDI + + + return output; + } + + // -------------------------------------------------- + // Build Surface Data (Specific Material) + + void ApplyDecalToSurfaceDataNoNormal(DecalSurfaceData decalSurfaceData, inout SurfaceData surfaceData); + + void ApplyDecalAndGetNormal(FragInputs fragInputs, PositionInputs posInput, SurfaceDescription surfaceDescription, + inout SurfaceData surfaceData) + { + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + #ifdef DECAL_NORMAL_BLENDING + // SG nodes don't ouptut surface gradients, so if decals require surf grad blending, we have to convert + // the normal to gradient before applying the decal. We then have to resolve the gradient back to world space + float3 normalTS; + + normalTS = SurfaceGradientFromTangentSpaceNormalAndFromTBN(surfaceDescription.NormalTS, + fragInputs.tangentToWorld[0], fragInputs.tangentToWorld[1]); + + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, fragInputs.tangentToWorld[2], normalTS); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + + GetNormalWS_SG(fragInputs, normalTS, surfaceData.normalWS, doubleSidedConstants); + #else + // normal delivered to master node + GetNormalWS(fragInputs, surfaceDescription.NormalTS, surfaceData.normalWS, doubleSidedConstants); + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + // Both uses and modifies 'surfaceData.normalWS'. + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, surfaceData.normalWS.xyz); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + #endif + } + void BuildSurfaceData(FragInputs fragInputs, inout SurfaceDescription surfaceDescription, float3 V, PositionInputs posInput, out SurfaceData surfaceData, out float3 bentNormalWS) + { + ZERO_INITIALIZE(SurfaceData, surfaceData); + + // specularOcclusion need to be init ahead of decal to quiet the compiler that modify the SurfaceData struct + // however specularOcclusion can come from the graph, so need to be init here so it can be override. + surfaceData.specularOcclusion = 1.0; + + surfaceData.baseColor = surfaceDescription.BaseColor; + surfaceData.perceptualSmoothness = surfaceDescription.Smoothness; + surfaceData.ambientOcclusion = surfaceDescription.Occlusion; + surfaceData.metallic = surfaceDescription.Metallic; + + #if defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE) || defined(_REFRACTION_THIN) + if (_EnableSSRefraction) + { + + surfaceData.transmittanceMask = (1.0 - surfaceDescription.Alpha); + surfaceDescription.Alpha = 1.0; + } + else + { + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + surfaceDescription.Alpha = 1.0; + } + #else + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + #endif + + // These static material feature allow compile time optimization + surfaceData.materialFeatures = MATERIALFEATUREFLAGS_LIT_STANDARD; + #ifdef _MATERIAL_FEATURE_SUBSURFACE_SCATTERING + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING; + #endif + + #ifdef _MATERIAL_FEATURE_TRANSMISSION + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_TRANSMISSION; + #endif + + #ifdef _MATERIAL_FEATURE_ANISOTROPY + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_ANISOTROPY; + + // Initialize the normal to something non-zero to avoid a div-zero warning for anisotropy. + surfaceData.normalWS = float3(0, 1, 0); + #endif + + #ifdef _MATERIAL_FEATURE_IRIDESCENCE + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_IRIDESCENCE; + #endif + + #ifdef _MATERIAL_FEATURE_SPECULAR_COLOR + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR; + #endif + + #ifdef _MATERIAL_FEATURE_CLEAR_COAT + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_CLEAR_COAT; + #endif + + #if defined (_MATERIAL_FEATURE_SPECULAR_COLOR) && defined (_ENERGY_CONSERVING_SPECULAR) + // Require to have setup baseColor + // Reproduce the energy conservation done in legacy Unity. Not ideal but better for compatibility and users can unchek it + surfaceData.baseColor *= (1.0 - Max3(surfaceData.specularColor.r, surfaceData.specularColor.g, surfaceData.specularColor.b)); + #endif + + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + ApplyDecalAndGetNormal(fragInputs, posInput, surfaceDescription, surfaceData); + + surfaceData.geomNormalWS = fragInputs.tangentToWorld[2]; + + surfaceData.tangentWS = normalize(fragInputs.tangentToWorld[0].xyz); // The tangent is not normalize in tangentToWorld for mikkt. TODO: Check if it expected that we normalize with Morten. Tag: SURFACE_GRADIENT + + + bentNormalWS = surfaceData.normalWS; + + surfaceData.tangentWS = Orthonormalize(surfaceData.tangentWS, surfaceData.normalWS); + + #ifdef DEBUG_DISPLAY + if (_DebugMipMapMode != DEBUGMIPMAPMODE_NONE) + { + // TODO: need to update mip info + surfaceData.metallic = 0; + } + + // We need to call ApplyDebugToSurfaceData after filling the surfarcedata and before filling builtinData + // as it can modify attribute use for static lighting + ApplyDebugToSurfaceData(fragInputs.tangentToWorld, surfaceData); + #endif + + // By default we use the ambient occlusion with Tri-ace trick (apply outside) for specular occlusion. + // If user provide bent normal then we process a better term + #if defined(_SPECULAR_OCCLUSION_CUSTOM) + // Just use the value passed through via the slot (not active otherwise) + #elif defined(_SPECULAR_OCCLUSION_FROM_AO_BENT_NORMAL) + // If we have bent normal and ambient occlusion, process a specular occlusion + surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData.normalWS, surfaceData.ambientOcclusion, PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness)); + #elif defined(_AMBIENT_OCCLUSION) && defined(_SPECULAR_OCCLUSION_FROM_AO) + surfaceData.specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(ClampNdotV(dot(surfaceData.normalWS, V)), surfaceData.ambientOcclusion, PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness)); + #endif + + #if defined(_ENABLE_GEOMETRIC_SPECULAR_AA) && !defined(SHADER_STAGE_RAY_TRACING) + surfaceData.perceptualSmoothness = GeometricNormalFiltering(surfaceData.perceptualSmoothness, fragInputs.tangentToWorld[2], surfaceDescription.SpecularAAScreenSpaceVariance, surfaceDescription.SpecularAAThreshold); + #endif + } + + // -------------------------------------------------- + // Get Surface And BuiltinData + + void GetSurfaceAndBuiltinData(FragInputs fragInputs, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData RAY_TRACING_OPTIONAL_PARAMETERS) + { + // 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 + LODDitheringTransition(ComputeFadeMaskSeed(V, posInput.positionSS), unity_LODFade.x); + #endif + #endif + + #ifndef SHADER_UNLIT + #ifdef _DOUBLESIDED_ON + float3 doubleSidedConstants = _DoubleSidedConstants.xyz; + #else + float3 doubleSidedConstants = float3(1.0, 1.0, 1.0); + #endif + + ApplyDoubleSidedFlipOrMirror(fragInputs, doubleSidedConstants); // Apply double sided flip on the vertex normal + #endif // SHADER_UNLIT + + SurfaceDescriptionInputs surfaceDescriptionInputs = FragInputsToSurfaceDescriptionInputs(fragInputs, V); + + #if defined(HAVE_VFX_MODIFICATION) + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + GetElementPixelProperties(fragInputs, properties); + + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs, properties); + #else + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs); + #endif + + // Perform alpha test very early to save performance (a killed pixel will not sample textures) + // TODO: split graph evaluation to grab just alpha dependencies first? tricky.. + #ifdef _ALPHATEST_ON + float alphaCutoff = surfaceDescription.AlphaClipThreshold; + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + // The TransparentDepthPrepass is also used with SSR transparent. + // If an artists enable transaprent SSR but not the TransparentDepthPrepass itself, then we use AlphaClipThreshold + // otherwise if TransparentDepthPrepass is enabled we use AlphaClipThresholdDepthPrepass + #elif SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_POSTPASS + // DepthPostpass always use its own alpha threshold + alphaCutoff = surfaceDescription.AlphaClipThresholdDepthPostpass; + #elif (SHADERPASS == SHADERPASS_SHADOWS) || (SHADERPASS == SHADERPASS_RAYTRACING_VISIBILITY) + // If use shadow threshold isn't enable we don't allow any test + #endif + + GENERIC_ALPHA_TEST(surfaceDescription.Alpha, alphaCutoff); + #endif + + #if !defined(SHADER_STAGE_RAY_TRACING) && _DEPTHOFFSET_ON + ApplyDepthOffsetPositionInput(V, surfaceDescription.DepthOffset, GetViewForwardDir(), GetWorldToHClipMatrix(), posInput); + #endif + + #ifndef SHADER_UNLIT + float3 bentNormalWS; + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData, bentNormalWS); + + #ifdef FRAG_INPUTS_USE_TEXCOORD1 + float4 lightmapTexCoord1 = fragInputs.texCoord1; + #else + float4 lightmapTexCoord1 = float4(0,0,0,0); + #endif + + #ifdef FRAG_INPUTS_USE_TEXCOORD2 + float4 lightmapTexCoord2 = fragInputs.texCoord2; + #else + float4 lightmapTexCoord2 = float4(0,0,0,0); + #endif + + // Builtin Data + // For back lighting we use the oposite vertex normal + InitBuiltinData(posInput, surfaceDescription.Alpha, bentNormalWS, -fragInputs.tangentToWorld[2], lightmapTexCoord1, lightmapTexCoord2, builtinData); + + #else + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData); + + ZERO_BUILTIN_INITIALIZE(builtinData); // No call to InitBuiltinData as we don't have any lighting + builtinData.opacity = surfaceDescription.Alpha; + + #if defined(DEBUG_DISPLAY) + // Light Layers are currently not used for the Unlit shader (because it is not lit) + // But Unlit objects do cast shadows according to their rendering layer mask, which is what we want to + // display in the light layers visualization mode, therefore we need the renderingLayers + builtinData.renderingLayers = GetMeshRenderingLightLayer(); + #endif + + #endif // SHADER_UNLIT + + #ifdef _ALPHATEST_ON + // Used for sharpening by alpha to mask - Alpha to covertage is only used with depth only and forward pass (no shadow pass, no transparent pass) + builtinData.alphaClipTreshold = alphaCutoff; + #endif + + // override sampleBakedGI - not used by Unlit + + builtinData.emissiveColor = surfaceDescription.Emission; + + // Note this will not fully work on transparent surfaces (can check with _SURFACE_TYPE_TRANSPARENT define) + // We will always overwrite vt feeback with the nearest. So behind transparent surfaces vt will not be resolved + // This is a limitation of the current MRT approach. + #ifdef UNITY_VIRTUAL_TEXTURING + builtinData.vtPackedFeedback = surfaceDescription.VTPackedFeedback; + #endif + + #if _DEPTHOFFSET_ON + builtinData.depthOffset = surfaceDescription.DepthOffset; + #endif + + // TODO: We should generate distortion / distortionBlur for non distortion pass + #if (SHADERPASS == SHADERPASS_DISTORTION) + builtinData.distortion = surfaceDescription.Distortion; + builtinData.distortionBlur = surfaceDescription.DistortionBlur; + #endif + + #ifndef SHADER_UNLIT + // PostInitBuiltinData call ApplyDebugToBuiltinData + PostInitBuiltinData(V, posInput, surfaceData, builtinData); + #else + ApplyDebugToBuiltinData(builtinData); + #endif + + RAY_TRACING_OPTIONAL_ALPHA_TEST_PASS + } + + // -------------------------------------------------- + // Main + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassGBuffer.hlsl" + + // -------------------------------------------------- + // Visual Effect Vertex Invocations + + #ifdef HAVE_VFX_MODIFICATION + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/VisualEffectVertex.hlsl" + #endif + + ENDHLSL + } + Pass + { + Name "Forward" + Tags + { + "LightMode" = "Forward" + } + + // Render State + Cull [_CullModeForward] + Blend [_SrcBlend] [_DstBlend], [_AlphaSrcBlend] [_AlphaDstBlend] + Blend 1 SrcAlpha OneMinusSrcAlpha + ZTest [_ZTestDepthEqualForOpaque] + ZWrite [_ZWrite] + ColorMask 0 + Stencil + { + WriteMask [_StencilWriteMask] + Ref [_StencilRef] + CompFront Always + PassFront Replace + CompBack Always + PassBack Replace + } + + // Debug + // + + // -------------------------------------------------- + // Pass + + HLSLPROGRAM + + // Pragmas + #pragma multi_compile _ DOTS_INSTANCING_ON + #pragma instancing_options renderinglayer + #pragma target 4.5 + #pragma vertex Vert + #pragma fragment Frag + #pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch + #pragma multi_compile_instancing + + // Keywords + #pragma shader_feature _ _SURFACE_TYPE_TRANSPARENT + #pragma shader_feature_local _ _DOUBLESIDED_ON + #pragma shader_feature_local _ _ADD_PRECOMPUTED_VELOCITY + #pragma shader_feature_local _ _TRANSPARENT_WRITES_MOTION_VEC + #pragma shader_feature_local_fragment _ _ENABLE_FOG_ON_TRANSPARENT + #pragma multi_compile _ DEBUG_DISPLAY + #pragma shader_feature_local_fragment _ _DISABLE_DECALS + #pragma shader_feature_local_raytracing _ _DISABLE_DECALS + #pragma shader_feature_local_fragment _ _DISABLE_SSR + #pragma shader_feature_local_raytracing _ _DISABLE_SSR + #pragma shader_feature_local_fragment _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local_raytracing _ _DISABLE_SSR_TRANSPARENT + #pragma multi_compile _ LIGHTMAP_ON + #pragma multi_compile _ DIRLIGHTMAP_COMBINED + #pragma multi_compile_fragment PROBE_VOLUMES_OFF PROBE_VOLUMES_L1 PROBE_VOLUMES_L2 + #pragma multi_compile_raytracing PROBE_VOLUMES_OFF PROBE_VOLUMES_L1 PROBE_VOLUMES_L2 + #pragma multi_compile _ DYNAMICLIGHTMAP_ON + #pragma multi_compile_fragment _ SHADOWS_SHADOWMASK + #pragma multi_compile_raytracing _ SHADOWS_SHADOWMASK + #pragma multi_compile_fragment DECALS_OFF DECALS_3RT DECALS_4RT + #pragma multi_compile_fragment _ DECAL_SURFACE_GRADIENT + #pragma multi_compile_fragment SHADOW_LOW SHADOW_MEDIUM SHADOW_HIGH + #pragma multi_compile_fragment AREA_SHADOW_MEDIUM AREA_SHADOW_HIGH + #pragma multi_compile_fragment SCREEN_SPACE_SHADOWS_OFF SCREEN_SPACE_SHADOWS_ON + #pragma multi_compile_fragment USE_FPTL_LIGHTLIST USE_CLUSTERED_LIGHTLIST + #pragma shader_feature_local _ _REFRACTION_PLANE _REFRACTION_SPHERE _REFRACTION_THIN + // GraphKeywords: + + // For custom interpolators to inject a substruct definition before FragInputs definition, + // allowing for FragInputs to capture CI's intended for ShaderGraph's SDI. + struct CustomInterpolators + { + }; + #define USE_CUSTOMINTERP_SUBSTRUCT + + + + // TODO: Merge FragInputsVFX substruct with CustomInterpolators. + #ifdef HAVE_VFX_MODIFICATION + struct FragInputsVFX + { + /* WARNING: $splice Could not find named fragment 'FragInputsVFX' */ + }; + #endif + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl" // Required by Tessellation.hlsl + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Tessellation.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Texture.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl" // Required to be include before we include properties as it define DECLARE_STACK_CB + // Always include Shader Graph version + // Always include last to avoid double macros + #include "Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl" // Need to be here for Gradient struct definition + + // -------------------------------------------------- + // Defines + + // Attribute + #define ATTRIBUTES_NEED_NORMAL + #define ATTRIBUTES_NEED_TANGENT + #define ATTRIBUTES_NEED_TEXCOORD1 + #define ATTRIBUTES_NEED_TEXCOORD2 + #define VARYINGS_NEED_POSITION_WS + #define VARYINGS_NEED_TANGENT_TO_WORLD + #define VARYINGS_NEED_TEXCOORD1 + #define VARYINGS_NEED_TEXCOORD2 + + #define HAVE_MESH_MODIFICATION + + //Strip down the FragInputs.hlsl (on graphics), so we can only optimize the interpolators we use. + //if by accident something requests contents of FragInputs.hlsl, it will be caught as a compiler error + //Frag inputs stripping is only enabled when FRAG_INPUTS_ENABLE_STRIPPING is set + #if !defined(SHADER_STAGE_RAY_TRACING) && SHADERPASS != SHADERPASS_RAYTRACING_GBUFFER && SHADERPASS != SHADERPASS_FULL_SCREEN_DEBUG + #define FRAG_INPUTS_ENABLE_STRIPPING + #endif + #define FRAG_INPUTS_USE_TEXCOORD1 + #define FRAG_INPUTS_USE_TEXCOORD2 + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl" + + + + #define SHADERPASS SHADERPASS_FORWARD + #define SUPPORT_BLENDMODE_PRESERVE_SPECULAR_LIGHTING 1 + #define HAS_LIGHTLOOP 1 + #define RAYTRACING_SHADER_GRAPH_DEFAULT + #define SHADER_LIT 1 + + + // Following two define are a workaround introduce in 10.1.x for RaytracingQualityNode + // The ShaderGraph don't support correctly migration of this node as it serialize all the node data + // in the json file making it impossible to uprgrade. Until we get a fix, we do a workaround here + // to still allow us to rename the field and keyword of this node without breaking existing code. + #ifdef RAYTRACING_SHADER_GRAPH_DEFAULT + #define RAYTRACING_SHADER_GRAPH_HIGH + #endif + + #ifdef RAYTRACING_SHADER_GRAPH_RAYTRACED + #define RAYTRACING_SHADER_GRAPH_LOW + #endif + // end + + #ifndef SHADER_UNLIT + // We need isFrontFace when using double sided - it is not required for unlit as in case of unlit double sided only drive the cullmode + // VARYINGS_NEED_CULLFACE can be define by VaryingsMeshToPS.FaceSign input if a IsFrontFace Node is included in the shader graph. + #if defined(_DOUBLESIDED_ON) && !defined(VARYINGS_NEED_CULLFACE) + #define VARYINGS_NEED_CULLFACE + #endif + #endif + + // Specific Material Define + #define _SPECULAR_OCCLUSION_FROM_AO 1 + #define _ENERGY_CONSERVING_SPECULAR 1 + + // If we use subsurface scattering, enable output split lighting (for forward pass) + #if defined(_MATERIAL_FEATURE_SUBSURFACE_SCATTERING) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define OUTPUT_SPLIT_LIGHTING + #endif + + // This shader support recursive rendering for raytracing + #define HAVE_RECURSIVE_RENDERING + + // In Path Tracing, For all single-sided, refractive materials, we want to force a thin refraction model + #if (SHADERPASS == SHADERPASS_PATH_TRACING) && !defined(_DOUBLESIDED_ON) && (defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE)) + #undef _REFRACTION_PLANE + #undef _REFRACTION_SPHERE + #define _REFRACTION_THIN + #endif + // Caution: we can use the define SHADER_UNLIT onlit after the above Material include as it is the Unlit template who define it + + // To handle SSR on transparent correctly with a possibility to enable/disable it per framesettings + // we should have a code like this: + // if !defined(_DISABLE_SSR_TRANSPARENT) + // pragma multi_compile _ WRITE_NORMAL_BUFFER + // endif + // i.e we enable the multicompile only if we can receive SSR or not, and then C# code drive + // it based on if SSR transparent in frame settings and not (and stripper can strip it). + // this is currently not possible with our current preprocessor as _DISABLE_SSR_TRANSPARENT is a keyword not a define + // so instead we used this and chose to pay the extra cost of normal write even if SSR transaprent is disabled. + // Ideally the shader graph generator should handle it but condition below can't be handle correctly for now. + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + #if !defined(_DISABLE_SSR_TRANSPARENT) && !defined(SHADER_UNLIT) + #define WRITE_NORMAL_BUFFER + #endif + #endif + + #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) + // Don't do it with debug display mode as it is possible there is no depth prepass in this case + #if !defined(_SURFACE_TYPE_TRANSPARENT) + #if SHADERPASS == SHADERPASS_FORWARD + #define SHADERPASS_FORWARD_BYPASS_ALPHA_TEST + #elif SHADERPASS == SHADERPASS_GBUFFER + #define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST + #endif + #endif + #endif + + // Define _DEFERRED_CAPABLE_MATERIAL for shader capable to run in deferred pass + #if defined(SHADER_LIT) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define _DEFERRED_CAPABLE_MATERIAL + #endif + + // Translate transparent motion vector define + #if defined(_TRANSPARENT_WRITES_MOTION_VEC) && defined(_SURFACE_TYPE_TRANSPARENT) + #define _WRITE_TRANSPARENT_MOTION_VECTOR + #endif + + // -- Graph Properties + CBUFFER_START(UnityPerMaterial) + float4 _Color; + float4 _EmissionColor; + float _UseShadowThreshold; + float4 _DoubleSidedConstants; + float _BlendMode; + float _EnableBlendModePreserveSpecularLighting; + float _RayTracing; + float _RefractionModel; + CBUFFER_END + + + // Object and Global properties + + // -- Property used by ScenePickingPass + #ifdef SCENEPICKINGPASS + float4 _SelectionID; + #endif + + // -- Properties used by SceneSelectionPass + #ifdef SCENESELECTIONPASS + int _ObjectId; + int _PassValue; + #endif + + // Includes + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugDisplay.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/NormalSurfaceGradient.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/Lighting.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoopDef.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/Lit.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoop.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/BuiltinUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/MaterialUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Decal/DecalUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitDecalData.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderGraphFunctions.hlsl" + // GraphIncludes: + + // -------------------------------------------------- + // Structs and Packing + + struct AttributesMesh + { + float3 positionOS : POSITION; + float3 normalOS : NORMAL; + float4 tangentOS : TANGENT; + float4 uv1 : TEXCOORD1; + float4 uv2 : TEXCOORD2; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : INSTANCEID_SEMANTIC; + #endif + }; + struct VaryingsMeshToPS + { + SV_POSITION_QUALIFIERS float4 positionCS : SV_POSITION; + float3 positionRWS; + float3 normalWS; + float4 tangentWS; + float4 texCoord1; + float4 texCoord2; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : CUSTOM_INSTANCE_ID; + #endif + }; + struct VertexDescriptionInputs + { + float3 ObjectSpaceNormal; + float3 ObjectSpaceTangent; + float3 ObjectSpacePosition; + }; + struct SurfaceDescriptionInputs + { + float3 TangentSpaceNormal; + }; + struct PackedVaryingsMeshToPS + { + SV_POSITION_QUALIFIERS float4 positionCS : SV_POSITION; + float4 tangentWS : INTERP0; + float4 texCoord1 : INTERP1; + float4 texCoord2 : INTERP2; + float3 positionRWS : INTERP3; + float3 normalWS : INTERP4; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : CUSTOM_INSTANCE_ID; + #endif + }; + + PackedVaryingsMeshToPS PackVaryingsMeshToPS (VaryingsMeshToPS input) + { + PackedVaryingsMeshToPS output; + ZERO_INITIALIZE(PackedVaryingsMeshToPS, output); + output.positionCS = input.positionCS; + output.tangentWS.xyzw = input.tangentWS; + output.texCoord1.xyzw = input.texCoord1; + output.texCoord2.xyzw = input.texCoord2; + output.positionRWS.xyz = input.positionRWS; + output.normalWS.xyz = input.normalWS; + #if UNITY_ANY_INSTANCING_ENABLED + output.instanceID = input.instanceID; + #endif + return output; + } + + VaryingsMeshToPS UnpackVaryingsMeshToPS (PackedVaryingsMeshToPS input) + { + VaryingsMeshToPS output; + output.positionCS = input.positionCS; + output.tangentWS = input.tangentWS.xyzw; + output.texCoord1 = input.texCoord1.xyzw; + output.texCoord2 = input.texCoord2.xyzw; + output.positionRWS = input.positionRWS.xyz; + output.normalWS = input.normalWS.xyz; + #if UNITY_ANY_INSTANCING_ENABLED + output.instanceID = input.instanceID; + #endif + return output; + } + + + // -------------------------------------------------- + // Graph + + + // Graph Functions + // GraphFunctions: + + // Graph Vertex + struct VertexDescription + { + float3 Position; + float3 Normal; + float3 Tangent; + }; + + VertexDescription VertexDescriptionFunction(VertexDescriptionInputs IN) + { + VertexDescription description = (VertexDescription)0; + description.Position = IN.ObjectSpacePosition; + description.Normal = IN.ObjectSpaceNormal; + description.Tangent = IN.ObjectSpaceTangent; + return description; + } + + // Graph Pixel + struct SurfaceDescription + { + float3 BaseColor; + float3 Emission; + float Alpha; + float3 BentNormal; + float Smoothness; + float Occlusion; + float3 NormalTS; + float Metallic; + float4 VTPackedFeedback; + }; + + SurfaceDescription SurfaceDescriptionFunction(SurfaceDescriptionInputs IN) + { + SurfaceDescription surface = (SurfaceDescription)0; + float4 _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4 = _Color; + float _Split_cace9cff304a4c5d84b5305897d09aa9_R_1_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[0]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_G_2_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[1]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_B_3_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[2]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[3]; + surface.BaseColor = (_Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4.xyz); + surface.Emission = float3(0, 0, 0); + surface.Alpha = _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float; + surface.BentNormal = IN.TangentSpaceNormal; + surface.Smoothness = 0.5; + surface.Occlusion = 1; + surface.NormalTS = IN.TangentSpaceNormal; + surface.Metallic = 0; + { + surface.VTPackedFeedback = float4(1.0f,1.0f,1.0f,1.0f); + } + return surface; + } + + // -------------------------------------------------- + // Build Graph Inputs + #ifdef HAVE_VFX_MODIFICATION + #define VFX_SRP_ATTRIBUTES AttributesMesh + #define VaryingsMeshType VaryingsMeshToPS + #define VFX_SRP_VARYINGS VaryingsMeshType + #define VFX_SRP_SURFACE_INPUTS FragInputs + #endif + + VertexDescriptionInputs AttributesMeshToVertexDescriptionInputs(AttributesMesh input) + { + VertexDescriptionInputs output; + ZERO_INITIALIZE(VertexDescriptionInputs, output); + + output.ObjectSpaceNormal = input.normalOS; + output.ObjectSpaceTangent = input.tangentOS.xyz; + output.ObjectSpacePosition = input.positionOS; + + return output; + } + + VertexDescription GetVertexDescription(AttributesMesh input, float3 timeParameters + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + // build graph inputs + VertexDescriptionInputs vertexDescriptionInputs = AttributesMeshToVertexDescriptionInputs(input); + // Override time parameters with used one (This is required to correctly handle motion vectors for vertex animation based on time) + + // evaluate vertex graph + #ifdef HAVE_VFX_MODIFICATION + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + // Fetch the vertex graph properties for the particle instance. + GetElementVertexProperties(element, properties); + + VertexDescription vertexDescription = VertexDescriptionFunction(vertexDescriptionInputs, properties); + #else + VertexDescription vertexDescription = VertexDescriptionFunction(vertexDescriptionInputs); + #endif + return vertexDescription; + + } + + AttributesMesh ApplyMeshModification(AttributesMesh input, float3 timeParameters + #ifdef USE_CUSTOMINTERP_SUBSTRUCT + #ifdef TESSELLATION_ON + , inout VaryingsMeshToDS varyings + #else + , inout VaryingsMeshToPS varyings + #endif + #endif + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + VertexDescription vertexDescription = GetVertexDescription(input, timeParameters + #ifdef HAVE_VFX_MODIFICATION + , element + #endif + ); + + // copy graph output to the results + input.positionOS = vertexDescription.Position; + input.normalOS = vertexDescription.Normal; + input.tangentOS.xyz = vertexDescription.Tangent; + + + + return input; + } + + #if defined(_ADD_CUSTOM_VELOCITY) // For shader graph custom velocity + // Return precomputed Velocity in object space + float3 GetCustomVelocity(AttributesMesh input + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + VertexDescription vertexDescription = GetVertexDescription(input, _TimeParameters.xyz + #ifdef HAVE_VFX_MODIFICATION + , element + #endif + ); + return vertexDescription.CustomVelocity; + } + #endif + + FragInputs BuildFragInputs(VaryingsMeshToPS input) + { + FragInputs output; + ZERO_INITIALIZE(FragInputs, output); + + // Init to some default value to make the computer quiet (else it output 'divide by zero' warning even if value is not used). + // TODO: this is a really poor workaround, but the variable is used in a bunch of places + // to compute normals which are then passed on elsewhere to compute other values... + output.tangentToWorld = k_identity3x3; + output.positionSS = input.positionCS; // input.positionCS is SV_Position + + output.positionRWS = input.positionRWS; + output.tangentToWorld = BuildTangentToWorld(input.tangentWS, input.normalWS); + output.texCoord1 = input.texCoord1; + output.texCoord2 = input.texCoord2; + + #ifdef HAVE_VFX_MODIFICATION + // FragInputs from VFX come from two places: Interpolator or CBuffer. + #if VFX_USE_GRAPH_VALUES + uint instanceActiveIndex = asuint(UNITY_ACCESS_INSTANCED_PROP(PerInstance, _InstanceActiveIndex)); + /* WARNING: $splice Could not find named fragment 'VFXLoadGraphValues' */ + #endif + + /* WARNING: $splice Could not find named fragment 'VFXSetFragInputs' */ + + #endif + + // splice point to copy custom interpolator fields from varyings to frag inputs + + + return output; + } + + // existing HDRP code uses the combined function to go directly from packed to frag inputs + FragInputs UnpackVaryingsMeshToFragInputs(PackedVaryingsMeshToPS input) + { + UNITY_SETUP_INSTANCE_ID(input); + #if defined(HAVE_VFX_MODIFICATION) && defined(UNITY_INSTANCING_ENABLED) + unity_InstanceID = input.instanceID; + #endif + VaryingsMeshToPS unpacked = UnpackVaryingsMeshToPS(input); + return BuildFragInputs(unpacked); + } + SurfaceDescriptionInputs FragInputsToSurfaceDescriptionInputs(FragInputs input, float3 viewWS) + { + SurfaceDescriptionInputs output; + ZERO_INITIALIZE(SurfaceDescriptionInputs, output); + + #if defined(SHADER_STAGE_RAY_TRACING) + #else + #endif + output.TangentSpaceNormal = float3(0.0f, 0.0f, 1.0f); + + #if UNITY_UV_STARTS_AT_TOP + #else + #endif + + + + // splice point to copy frag inputs custom interpolator pack into the SDI + + + return output; + } + + // -------------------------------------------------- + // Build Surface Data (Specific Material) + + void ApplyDecalToSurfaceDataNoNormal(DecalSurfaceData decalSurfaceData, inout SurfaceData surfaceData); + + void ApplyDecalAndGetNormal(FragInputs fragInputs, PositionInputs posInput, SurfaceDescription surfaceDescription, + inout SurfaceData surfaceData) + { + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + #ifdef DECAL_NORMAL_BLENDING + // SG nodes don't ouptut surface gradients, so if decals require surf grad blending, we have to convert + // the normal to gradient before applying the decal. We then have to resolve the gradient back to world space + float3 normalTS; + + normalTS = SurfaceGradientFromTangentSpaceNormalAndFromTBN(surfaceDescription.NormalTS, + fragInputs.tangentToWorld[0], fragInputs.tangentToWorld[1]); + + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, fragInputs.tangentToWorld[2], normalTS); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + + GetNormalWS_SG(fragInputs, normalTS, surfaceData.normalWS, doubleSidedConstants); + #else + // normal delivered to master node + GetNormalWS(fragInputs, surfaceDescription.NormalTS, surfaceData.normalWS, doubleSidedConstants); + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + // Both uses and modifies 'surfaceData.normalWS'. + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, surfaceData.normalWS.xyz); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + #endif + } + void BuildSurfaceData(FragInputs fragInputs, inout SurfaceDescription surfaceDescription, float3 V, PositionInputs posInput, out SurfaceData surfaceData, out float3 bentNormalWS) + { + ZERO_INITIALIZE(SurfaceData, surfaceData); + + // specularOcclusion need to be init ahead of decal to quiet the compiler that modify the SurfaceData struct + // however specularOcclusion can come from the graph, so need to be init here so it can be override. + surfaceData.specularOcclusion = 1.0; + + surfaceData.baseColor = surfaceDescription.BaseColor; + surfaceData.perceptualSmoothness = surfaceDescription.Smoothness; + surfaceData.ambientOcclusion = surfaceDescription.Occlusion; + surfaceData.metallic = surfaceDescription.Metallic; + + #if defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE) || defined(_REFRACTION_THIN) + if (_EnableSSRefraction) + { + + surfaceData.transmittanceMask = (1.0 - surfaceDescription.Alpha); + surfaceDescription.Alpha = 1.0; + } + else + { + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + surfaceDescription.Alpha = 1.0; + } + #else + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + #endif + + // These static material feature allow compile time optimization + surfaceData.materialFeatures = MATERIALFEATUREFLAGS_LIT_STANDARD; + #ifdef _MATERIAL_FEATURE_SUBSURFACE_SCATTERING + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING; + #endif + + #ifdef _MATERIAL_FEATURE_TRANSMISSION + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_TRANSMISSION; + #endif + + #ifdef _MATERIAL_FEATURE_ANISOTROPY + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_ANISOTROPY; + + // Initialize the normal to something non-zero to avoid a div-zero warning for anisotropy. + surfaceData.normalWS = float3(0, 1, 0); + #endif + + #ifdef _MATERIAL_FEATURE_IRIDESCENCE + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_IRIDESCENCE; + #endif + + #ifdef _MATERIAL_FEATURE_SPECULAR_COLOR + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR; + #endif + + #ifdef _MATERIAL_FEATURE_CLEAR_COAT + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_CLEAR_COAT; + #endif + + #if defined (_MATERIAL_FEATURE_SPECULAR_COLOR) && defined (_ENERGY_CONSERVING_SPECULAR) + // Require to have setup baseColor + // Reproduce the energy conservation done in legacy Unity. Not ideal but better for compatibility and users can unchek it + surfaceData.baseColor *= (1.0 - Max3(surfaceData.specularColor.r, surfaceData.specularColor.g, surfaceData.specularColor.b)); + #endif + + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + ApplyDecalAndGetNormal(fragInputs, posInput, surfaceDescription, surfaceData); + + surfaceData.geomNormalWS = fragInputs.tangentToWorld[2]; + + surfaceData.tangentWS = normalize(fragInputs.tangentToWorld[0].xyz); // The tangent is not normalize in tangentToWorld for mikkt. TODO: Check if it expected that we normalize with Morten. Tag: SURFACE_GRADIENT + + + bentNormalWS = surfaceData.normalWS; + + surfaceData.tangentWS = Orthonormalize(surfaceData.tangentWS, surfaceData.normalWS); + + #ifdef DEBUG_DISPLAY + if (_DebugMipMapMode != DEBUGMIPMAPMODE_NONE) + { + // TODO: need to update mip info + surfaceData.metallic = 0; + } + + // We need to call ApplyDebugToSurfaceData after filling the surfarcedata and before filling builtinData + // as it can modify attribute use for static lighting + ApplyDebugToSurfaceData(fragInputs.tangentToWorld, surfaceData); + #endif + + // By default we use the ambient occlusion with Tri-ace trick (apply outside) for specular occlusion. + // If user provide bent normal then we process a better term + #if defined(_SPECULAR_OCCLUSION_CUSTOM) + // Just use the value passed through via the slot (not active otherwise) + #elif defined(_SPECULAR_OCCLUSION_FROM_AO_BENT_NORMAL) + // If we have bent normal and ambient occlusion, process a specular occlusion + surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData.normalWS, surfaceData.ambientOcclusion, PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness)); + #elif defined(_AMBIENT_OCCLUSION) && defined(_SPECULAR_OCCLUSION_FROM_AO) + surfaceData.specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(ClampNdotV(dot(surfaceData.normalWS, V)), surfaceData.ambientOcclusion, PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness)); + #endif + + #if defined(_ENABLE_GEOMETRIC_SPECULAR_AA) && !defined(SHADER_STAGE_RAY_TRACING) + surfaceData.perceptualSmoothness = GeometricNormalFiltering(surfaceData.perceptualSmoothness, fragInputs.tangentToWorld[2], surfaceDescription.SpecularAAScreenSpaceVariance, surfaceDescription.SpecularAAThreshold); + #endif + } + + // -------------------------------------------------- + // Get Surface And BuiltinData + + void GetSurfaceAndBuiltinData(FragInputs fragInputs, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData RAY_TRACING_OPTIONAL_PARAMETERS) + { + // 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 + LODDitheringTransition(ComputeFadeMaskSeed(V, posInput.positionSS), unity_LODFade.x); + #endif + #endif + + #ifndef SHADER_UNLIT + #ifdef _DOUBLESIDED_ON + float3 doubleSidedConstants = _DoubleSidedConstants.xyz; + #else + float3 doubleSidedConstants = float3(1.0, 1.0, 1.0); + #endif + + ApplyDoubleSidedFlipOrMirror(fragInputs, doubleSidedConstants); // Apply double sided flip on the vertex normal + #endif // SHADER_UNLIT + + SurfaceDescriptionInputs surfaceDescriptionInputs = FragInputsToSurfaceDescriptionInputs(fragInputs, V); + + #if defined(HAVE_VFX_MODIFICATION) + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + GetElementPixelProperties(fragInputs, properties); + + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs, properties); + #else + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs); + #endif + + // Perform alpha test very early to save performance (a killed pixel will not sample textures) + // TODO: split graph evaluation to grab just alpha dependencies first? tricky.. + #ifdef _ALPHATEST_ON + float alphaCutoff = surfaceDescription.AlphaClipThreshold; + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + // The TransparentDepthPrepass is also used with SSR transparent. + // If an artists enable transaprent SSR but not the TransparentDepthPrepass itself, then we use AlphaClipThreshold + // otherwise if TransparentDepthPrepass is enabled we use AlphaClipThresholdDepthPrepass + #elif SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_POSTPASS + // DepthPostpass always use its own alpha threshold + alphaCutoff = surfaceDescription.AlphaClipThresholdDepthPostpass; + #elif (SHADERPASS == SHADERPASS_SHADOWS) || (SHADERPASS == SHADERPASS_RAYTRACING_VISIBILITY) + // If use shadow threshold isn't enable we don't allow any test + #endif + + GENERIC_ALPHA_TEST(surfaceDescription.Alpha, alphaCutoff); + #endif + + #if !defined(SHADER_STAGE_RAY_TRACING) && _DEPTHOFFSET_ON + ApplyDepthOffsetPositionInput(V, surfaceDescription.DepthOffset, GetViewForwardDir(), GetWorldToHClipMatrix(), posInput); + #endif + + #ifndef SHADER_UNLIT + float3 bentNormalWS; + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData, bentNormalWS); + + #ifdef FRAG_INPUTS_USE_TEXCOORD1 + float4 lightmapTexCoord1 = fragInputs.texCoord1; + #else + float4 lightmapTexCoord1 = float4(0,0,0,0); + #endif + + #ifdef FRAG_INPUTS_USE_TEXCOORD2 + float4 lightmapTexCoord2 = fragInputs.texCoord2; + #else + float4 lightmapTexCoord2 = float4(0,0,0,0); + #endif + + // Builtin Data + // For back lighting we use the oposite vertex normal + InitBuiltinData(posInput, surfaceDescription.Alpha, bentNormalWS, -fragInputs.tangentToWorld[2], lightmapTexCoord1, lightmapTexCoord2, builtinData); + + #else + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData); + + ZERO_BUILTIN_INITIALIZE(builtinData); // No call to InitBuiltinData as we don't have any lighting + builtinData.opacity = surfaceDescription.Alpha; + + #if defined(DEBUG_DISPLAY) + // Light Layers are currently not used for the Unlit shader (because it is not lit) + // But Unlit objects do cast shadows according to their rendering layer mask, which is what we want to + // display in the light layers visualization mode, therefore we need the renderingLayers + builtinData.renderingLayers = GetMeshRenderingLightLayer(); + #endif + + #endif // SHADER_UNLIT + + #ifdef _ALPHATEST_ON + // Used for sharpening by alpha to mask - Alpha to covertage is only used with depth only and forward pass (no shadow pass, no transparent pass) + builtinData.alphaClipTreshold = alphaCutoff; + #endif + + // override sampleBakedGI - not used by Unlit + + builtinData.emissiveColor = surfaceDescription.Emission; + + // Note this will not fully work on transparent surfaces (can check with _SURFACE_TYPE_TRANSPARENT define) + // We will always overwrite vt feeback with the nearest. So behind transparent surfaces vt will not be resolved + // This is a limitation of the current MRT approach. + #ifdef UNITY_VIRTUAL_TEXTURING + builtinData.vtPackedFeedback = surfaceDescription.VTPackedFeedback; + #endif + + #if _DEPTHOFFSET_ON + builtinData.depthOffset = surfaceDescription.DepthOffset; + #endif + + // TODO: We should generate distortion / distortionBlur for non distortion pass + #if (SHADERPASS == SHADERPASS_DISTORTION) + builtinData.distortion = surfaceDescription.Distortion; + builtinData.distortionBlur = surfaceDescription.DistortionBlur; + #endif + + #ifndef SHADER_UNLIT + // PostInitBuiltinData call ApplyDebugToBuiltinData + PostInitBuiltinData(V, posInput, surfaceData, builtinData); + #else + ApplyDebugToBuiltinData(builtinData); + #endif + + RAY_TRACING_OPTIONAL_ALPHA_TEST_PASS + } + + // -------------------------------------------------- + // Main + + #include "Packages/org.happy-turtle.order-independent-transparency/HDRP/Shaders/OitShaderPassForwardHDRP.hlsl" + + // -------------------------------------------------- + // Visual Effect Vertex Invocations + + #ifdef HAVE_VFX_MODIFICATION + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/VisualEffectVertex.hlsl" + #endif + + ENDHLSL + } + Pass + { + Name "RayTracingPrepass" + Tags + { + "LightMode" = "RayTracingPrepass" + } + + // Render State + Cull [_CullMode] + Blend One Zero + ZWrite On + + // Debug + // + + // -------------------------------------------------- + // Pass + + HLSLPROGRAM + + // Pragmas + #pragma target 4.5 + #pragma vertex Vert + #pragma fragment Frag + #pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch + #pragma multi_compile_instancing + + // Keywords + #pragma shader_feature _ _SURFACE_TYPE_TRANSPARENT + #pragma shader_feature_local _ _DOUBLESIDED_ON + #pragma shader_feature_local _ _ADD_PRECOMPUTED_VELOCITY + #pragma shader_feature_local _ _TRANSPARENT_WRITES_MOTION_VEC + #pragma shader_feature_local_fragment _ _ENABLE_FOG_ON_TRANSPARENT + #pragma shader_feature_local_fragment _ _DISABLE_DECALS + #pragma shader_feature_local_raytracing _ _DISABLE_DECALS + #pragma shader_feature_local_fragment _ _DISABLE_SSR + #pragma shader_feature_local_raytracing _ _DISABLE_SSR + #pragma shader_feature_local_fragment _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local_raytracing _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local _ _REFRACTION_PLANE _REFRACTION_SPHERE _REFRACTION_THIN + // GraphKeywords: + + // For custom interpolators to inject a substruct definition before FragInputs definition, + // allowing for FragInputs to capture CI's intended for ShaderGraph's SDI. + struct CustomInterpolators + { + }; + #define USE_CUSTOMINTERP_SUBSTRUCT + + + + // TODO: Merge FragInputsVFX substruct with CustomInterpolators. + #ifdef HAVE_VFX_MODIFICATION + struct FragInputsVFX + { + /* WARNING: $splice Could not find named fragment 'FragInputsVFX' */ + }; + #endif + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl" // Required by Tessellation.hlsl + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Tessellation.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Texture.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl" // Required to be include before we include properties as it define DECLARE_STACK_CB + // Always include Shader Graph version + // Always include last to avoid double macros + #include "Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl" // Need to be here for Gradient struct definition + + // -------------------------------------------------- + // Defines + + // Attribute + #define ATTRIBUTES_NEED_NORMAL + #define ATTRIBUTES_NEED_TANGENT + + #define HAVE_MESH_MODIFICATION + + //Strip down the FragInputs.hlsl (on graphics), so we can only optimize the interpolators we use. + //if by accident something requests contents of FragInputs.hlsl, it will be caught as a compiler error + //Frag inputs stripping is only enabled when FRAG_INPUTS_ENABLE_STRIPPING is set + #if !defined(SHADER_STAGE_RAY_TRACING) && SHADERPASS != SHADERPASS_RAYTRACING_GBUFFER && SHADERPASS != SHADERPASS_FULL_SCREEN_DEBUG + #define FRAG_INPUTS_ENABLE_STRIPPING + #endif + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl" + + + + #define SHADERPASS SHADERPASS_CONSTANT + #define RAYTRACING_SHADER_GRAPH_DEFAULT + + + // Following two define are a workaround introduce in 10.1.x for RaytracingQualityNode + // The ShaderGraph don't support correctly migration of this node as it serialize all the node data + // in the json file making it impossible to uprgrade. Until we get a fix, we do a workaround here + // to still allow us to rename the field and keyword of this node without breaking existing code. + #ifdef RAYTRACING_SHADER_GRAPH_DEFAULT + #define RAYTRACING_SHADER_GRAPH_HIGH + #endif + + #ifdef RAYTRACING_SHADER_GRAPH_RAYTRACED + #define RAYTRACING_SHADER_GRAPH_LOW + #endif + // end + + #ifndef SHADER_UNLIT + // We need isFrontFace when using double sided - it is not required for unlit as in case of unlit double sided only drive the cullmode + // VARYINGS_NEED_CULLFACE can be define by VaryingsMeshToPS.FaceSign input if a IsFrontFace Node is included in the shader graph. + #if defined(_DOUBLESIDED_ON) && !defined(VARYINGS_NEED_CULLFACE) + #define VARYINGS_NEED_CULLFACE + #endif + #endif + + // Specific Material Define + #define _SPECULAR_OCCLUSION_FROM_AO 1 + #define _ENERGY_CONSERVING_SPECULAR 1 + + // If we use subsurface scattering, enable output split lighting (for forward pass) + #if defined(_MATERIAL_FEATURE_SUBSURFACE_SCATTERING) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define OUTPUT_SPLIT_LIGHTING + #endif + + // This shader support recursive rendering for raytracing + #define HAVE_RECURSIVE_RENDERING + + // In Path Tracing, For all single-sided, refractive materials, we want to force a thin refraction model + #if (SHADERPASS == SHADERPASS_PATH_TRACING) && !defined(_DOUBLESIDED_ON) && (defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE)) + #undef _REFRACTION_PLANE + #undef _REFRACTION_SPHERE + #define _REFRACTION_THIN + #endif + // Caution: we can use the define SHADER_UNLIT onlit after the above Material include as it is the Unlit template who define it + + // To handle SSR on transparent correctly with a possibility to enable/disable it per framesettings + // we should have a code like this: + // if !defined(_DISABLE_SSR_TRANSPARENT) + // pragma multi_compile _ WRITE_NORMAL_BUFFER + // endif + // i.e we enable the multicompile only if we can receive SSR or not, and then C# code drive + // it based on if SSR transparent in frame settings and not (and stripper can strip it). + // this is currently not possible with our current preprocessor as _DISABLE_SSR_TRANSPARENT is a keyword not a define + // so instead we used this and chose to pay the extra cost of normal write even if SSR transaprent is disabled. + // Ideally the shader graph generator should handle it but condition below can't be handle correctly for now. + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + #if !defined(_DISABLE_SSR_TRANSPARENT) && !defined(SHADER_UNLIT) + #define WRITE_NORMAL_BUFFER + #endif + #endif + + #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) + // Don't do it with debug display mode as it is possible there is no depth prepass in this case + #if !defined(_SURFACE_TYPE_TRANSPARENT) + #if SHADERPASS == SHADERPASS_FORWARD + #define SHADERPASS_FORWARD_BYPASS_ALPHA_TEST + #elif SHADERPASS == SHADERPASS_GBUFFER + #define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST + #endif + #endif + #endif + + // Define _DEFERRED_CAPABLE_MATERIAL for shader capable to run in deferred pass + #if defined(SHADER_LIT) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define _DEFERRED_CAPABLE_MATERIAL + #endif + + // Translate transparent motion vector define + #if defined(_TRANSPARENT_WRITES_MOTION_VEC) && defined(_SURFACE_TYPE_TRANSPARENT) + #define _WRITE_TRANSPARENT_MOTION_VECTOR + #endif + + // -- Graph Properties + CBUFFER_START(UnityPerMaterial) + float4 _Color; + float4 _EmissionColor; + float _UseShadowThreshold; + float4 _DoubleSidedConstants; + float _BlendMode; + float _EnableBlendModePreserveSpecularLighting; + float _RayTracing; + float _RefractionModel; + CBUFFER_END + + + // Object and Global properties + + // -- Property used by ScenePickingPass + #ifdef SCENEPICKINGPASS + float4 _SelectionID; + #endif + + // -- Properties used by SceneSelectionPass + #ifdef SCENESELECTIONPASS + int _ObjectId; + int _PassValue; + #endif + + // Includes + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugDisplay.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/NormalSurfaceGradient.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/Lit.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/BuiltinUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/MaterialUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Decal/DecalUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitDecalData.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderGraphFunctions.hlsl" + // GraphIncludes: + + // -------------------------------------------------- + // Structs and Packing + + struct AttributesMesh + { + float3 positionOS : POSITION; + float3 normalOS : NORMAL; + float4 tangentOS : TANGENT; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : INSTANCEID_SEMANTIC; + #endif + }; + struct VaryingsMeshToPS + { + SV_POSITION_QUALIFIERS float4 positionCS : SV_POSITION; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : CUSTOM_INSTANCE_ID; + #endif + }; + struct VertexDescriptionInputs + { + float3 ObjectSpaceNormal; + float3 ObjectSpaceTangent; + float3 ObjectSpacePosition; + }; + struct SurfaceDescriptionInputs + { + float3 TangentSpaceNormal; + }; + struct PackedVaryingsMeshToPS + { + SV_POSITION_QUALIFIERS float4 positionCS : SV_POSITION; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : CUSTOM_INSTANCE_ID; + #endif + }; + + PackedVaryingsMeshToPS PackVaryingsMeshToPS (VaryingsMeshToPS input) + { + PackedVaryingsMeshToPS output; + ZERO_INITIALIZE(PackedVaryingsMeshToPS, output); + output.positionCS = input.positionCS; + #if UNITY_ANY_INSTANCING_ENABLED + output.instanceID = input.instanceID; + #endif + return output; + } + + VaryingsMeshToPS UnpackVaryingsMeshToPS (PackedVaryingsMeshToPS input) + { + VaryingsMeshToPS output; + output.positionCS = input.positionCS; + #if UNITY_ANY_INSTANCING_ENABLED + output.instanceID = input.instanceID; + #endif + return output; + } + + + // -------------------------------------------------- + // Graph + + + // Graph Functions + // GraphFunctions: + + // Graph Vertex + struct VertexDescription + { + float3 Position; + float3 Normal; + float3 Tangent; + }; + + VertexDescription VertexDescriptionFunction(VertexDescriptionInputs IN) + { + VertexDescription description = (VertexDescription)0; + description.Position = IN.ObjectSpacePosition; + description.Normal = IN.ObjectSpaceNormal; + description.Tangent = IN.ObjectSpaceTangent; + return description; + } + + // Graph Pixel + struct SurfaceDescription + { + float3 BaseColor; + float3 Emission; + float Alpha; + float3 BentNormal; + float Smoothness; + float Occlusion; + float3 NormalTS; + float Metallic; + }; + + SurfaceDescription SurfaceDescriptionFunction(SurfaceDescriptionInputs IN) + { + SurfaceDescription surface = (SurfaceDescription)0; + float4 _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4 = _Color; + float _Split_cace9cff304a4c5d84b5305897d09aa9_R_1_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[0]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_G_2_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[1]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_B_3_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[2]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[3]; + surface.BaseColor = (_Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4.xyz); + surface.Emission = float3(0, 0, 0); + surface.Alpha = _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float; + surface.BentNormal = IN.TangentSpaceNormal; + surface.Smoothness = 0.5; + surface.Occlusion = 1; + surface.NormalTS = IN.TangentSpaceNormal; + surface.Metallic = 0; + return surface; + } + + // -------------------------------------------------- + // Build Graph Inputs + #ifdef HAVE_VFX_MODIFICATION + #define VFX_SRP_ATTRIBUTES AttributesMesh + #define VaryingsMeshType VaryingsMeshToPS + #define VFX_SRP_VARYINGS VaryingsMeshType + #define VFX_SRP_SURFACE_INPUTS FragInputs + #endif + + VertexDescriptionInputs AttributesMeshToVertexDescriptionInputs(AttributesMesh input) + { + VertexDescriptionInputs output; + ZERO_INITIALIZE(VertexDescriptionInputs, output); + + output.ObjectSpaceNormal = input.normalOS; + output.ObjectSpaceTangent = input.tangentOS.xyz; + output.ObjectSpacePosition = input.positionOS; + + return output; + } + + VertexDescription GetVertexDescription(AttributesMesh input, float3 timeParameters + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + // build graph inputs + VertexDescriptionInputs vertexDescriptionInputs = AttributesMeshToVertexDescriptionInputs(input); + // Override time parameters with used one (This is required to correctly handle motion vectors for vertex animation based on time) + + // evaluate vertex graph + #ifdef HAVE_VFX_MODIFICATION + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + // Fetch the vertex graph properties for the particle instance. + GetElementVertexProperties(element, properties); + + VertexDescription vertexDescription = VertexDescriptionFunction(vertexDescriptionInputs, properties); + #else + VertexDescription vertexDescription = VertexDescriptionFunction(vertexDescriptionInputs); + #endif + return vertexDescription; + + } + + AttributesMesh ApplyMeshModification(AttributesMesh input, float3 timeParameters + #ifdef USE_CUSTOMINTERP_SUBSTRUCT + #ifdef TESSELLATION_ON + , inout VaryingsMeshToDS varyings + #else + , inout VaryingsMeshToPS varyings + #endif + #endif + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + VertexDescription vertexDescription = GetVertexDescription(input, timeParameters + #ifdef HAVE_VFX_MODIFICATION + , element + #endif + ); + + // copy graph output to the results + input.positionOS = vertexDescription.Position; + input.normalOS = vertexDescription.Normal; + input.tangentOS.xyz = vertexDescription.Tangent; + + + + return input; + } + + #if defined(_ADD_CUSTOM_VELOCITY) // For shader graph custom velocity + // Return precomputed Velocity in object space + float3 GetCustomVelocity(AttributesMesh input + #ifdef HAVE_VFX_MODIFICATION + , AttributesElement element + #endif + ) + { + VertexDescription vertexDescription = GetVertexDescription(input, _TimeParameters.xyz + #ifdef HAVE_VFX_MODIFICATION + , element + #endif + ); + return vertexDescription.CustomVelocity; + } + #endif + + FragInputs BuildFragInputs(VaryingsMeshToPS input) + { + FragInputs output; + ZERO_INITIALIZE(FragInputs, output); + + // Init to some default value to make the computer quiet (else it output 'divide by zero' warning even if value is not used). + // TODO: this is a really poor workaround, but the variable is used in a bunch of places + // to compute normals which are then passed on elsewhere to compute other values... + output.tangentToWorld = k_identity3x3; + output.positionSS = input.positionCS; // input.positionCS is SV_Position + + + #ifdef HAVE_VFX_MODIFICATION + // FragInputs from VFX come from two places: Interpolator or CBuffer. + #if VFX_USE_GRAPH_VALUES + uint instanceActiveIndex = asuint(UNITY_ACCESS_INSTANCED_PROP(PerInstance, _InstanceActiveIndex)); + /* WARNING: $splice Could not find named fragment 'VFXLoadGraphValues' */ + #endif + + /* WARNING: $splice Could not find named fragment 'VFXSetFragInputs' */ + + #endif + + // splice point to copy custom interpolator fields from varyings to frag inputs + + + return output; + } + + // existing HDRP code uses the combined function to go directly from packed to frag inputs + FragInputs UnpackVaryingsMeshToFragInputs(PackedVaryingsMeshToPS input) + { + UNITY_SETUP_INSTANCE_ID(input); + #if defined(HAVE_VFX_MODIFICATION) && defined(UNITY_INSTANCING_ENABLED) + unity_InstanceID = input.instanceID; + #endif + VaryingsMeshToPS unpacked = UnpackVaryingsMeshToPS(input); + return BuildFragInputs(unpacked); + } + SurfaceDescriptionInputs FragInputsToSurfaceDescriptionInputs(FragInputs input, float3 viewWS) + { + SurfaceDescriptionInputs output; + ZERO_INITIALIZE(SurfaceDescriptionInputs, output); + + #if defined(SHADER_STAGE_RAY_TRACING) + #else + #endif + output.TangentSpaceNormal = float3(0.0f, 0.0f, 1.0f); + + #if UNITY_UV_STARTS_AT_TOP + #else + #endif + + + + // splice point to copy frag inputs custom interpolator pack into the SDI + + + return output; + } + + // -------------------------------------------------- + // Build Surface Data (Specific Material) + + void ApplyDecalToSurfaceDataNoNormal(DecalSurfaceData decalSurfaceData, inout SurfaceData surfaceData); + + void ApplyDecalAndGetNormal(FragInputs fragInputs, PositionInputs posInput, SurfaceDescription surfaceDescription, + inout SurfaceData surfaceData) + { + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + #ifdef DECAL_NORMAL_BLENDING + // SG nodes don't ouptut surface gradients, so if decals require surf grad blending, we have to convert + // the normal to gradient before applying the decal. We then have to resolve the gradient back to world space + float3 normalTS; + + normalTS = SurfaceGradientFromTangentSpaceNormalAndFromTBN(surfaceDescription.NormalTS, + fragInputs.tangentToWorld[0], fragInputs.tangentToWorld[1]); + + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, fragInputs.tangentToWorld[2], normalTS); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + + GetNormalWS_SG(fragInputs, normalTS, surfaceData.normalWS, doubleSidedConstants); + #else + // normal delivered to master node + GetNormalWS(fragInputs, surfaceDescription.NormalTS, surfaceData.normalWS, doubleSidedConstants); + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + // Both uses and modifies 'surfaceData.normalWS'. + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, surfaceData.normalWS.xyz); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + #endif + } + void BuildSurfaceData(FragInputs fragInputs, inout SurfaceDescription surfaceDescription, float3 V, PositionInputs posInput, out SurfaceData surfaceData, out float3 bentNormalWS) + { + ZERO_INITIALIZE(SurfaceData, surfaceData); + + // specularOcclusion need to be init ahead of decal to quiet the compiler that modify the SurfaceData struct + // however specularOcclusion can come from the graph, so need to be init here so it can be override. + surfaceData.specularOcclusion = 1.0; + + surfaceData.baseColor = surfaceDescription.BaseColor; + surfaceData.perceptualSmoothness = surfaceDescription.Smoothness; + surfaceData.ambientOcclusion = surfaceDescription.Occlusion; + surfaceData.metallic = surfaceDescription.Metallic; + + #if defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE) || defined(_REFRACTION_THIN) + if (_EnableSSRefraction) + { + + surfaceData.transmittanceMask = (1.0 - surfaceDescription.Alpha); + surfaceDescription.Alpha = 1.0; + } + else + { + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + surfaceDescription.Alpha = 1.0; + } + #else + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + #endif + + // These static material feature allow compile time optimization + surfaceData.materialFeatures = MATERIALFEATUREFLAGS_LIT_STANDARD; + #ifdef _MATERIAL_FEATURE_SUBSURFACE_SCATTERING + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING; + #endif + + #ifdef _MATERIAL_FEATURE_TRANSMISSION + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_TRANSMISSION; + #endif + + #ifdef _MATERIAL_FEATURE_ANISOTROPY + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_ANISOTROPY; + + // Initialize the normal to something non-zero to avoid a div-zero warning for anisotropy. + surfaceData.normalWS = float3(0, 1, 0); + #endif + + #ifdef _MATERIAL_FEATURE_IRIDESCENCE + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_IRIDESCENCE; + #endif + + #ifdef _MATERIAL_FEATURE_SPECULAR_COLOR + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR; + #endif + + #ifdef _MATERIAL_FEATURE_CLEAR_COAT + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_CLEAR_COAT; + #endif + + #if defined (_MATERIAL_FEATURE_SPECULAR_COLOR) && defined (_ENERGY_CONSERVING_SPECULAR) + // Require to have setup baseColor + // Reproduce the energy conservation done in legacy Unity. Not ideal but better for compatibility and users can unchek it + surfaceData.baseColor *= (1.0 - Max3(surfaceData.specularColor.r, surfaceData.specularColor.g, surfaceData.specularColor.b)); + #endif + + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + ApplyDecalAndGetNormal(fragInputs, posInput, surfaceDescription, surfaceData); + + surfaceData.geomNormalWS = fragInputs.tangentToWorld[2]; + + surfaceData.tangentWS = normalize(fragInputs.tangentToWorld[0].xyz); // The tangent is not normalize in tangentToWorld for mikkt. TODO: Check if it expected that we normalize with Morten. Tag: SURFACE_GRADIENT + + + bentNormalWS = surfaceData.normalWS; + + surfaceData.tangentWS = Orthonormalize(surfaceData.tangentWS, surfaceData.normalWS); + + #ifdef DEBUG_DISPLAY + if (_DebugMipMapMode != DEBUGMIPMAPMODE_NONE) + { + // TODO: need to update mip info + surfaceData.metallic = 0; + } + + // We need to call ApplyDebugToSurfaceData after filling the surfarcedata and before filling builtinData + // as it can modify attribute use for static lighting + ApplyDebugToSurfaceData(fragInputs.tangentToWorld, surfaceData); + #endif + + // By default we use the ambient occlusion with Tri-ace trick (apply outside) for specular occlusion. + // If user provide bent normal then we process a better term + #if defined(_SPECULAR_OCCLUSION_CUSTOM) + // Just use the value passed through via the slot (not active otherwise) + #elif defined(_SPECULAR_OCCLUSION_FROM_AO_BENT_NORMAL) + // If we have bent normal and ambient occlusion, process a specular occlusion + surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData.normalWS, surfaceData.ambientOcclusion, PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness)); + #elif defined(_AMBIENT_OCCLUSION) && defined(_SPECULAR_OCCLUSION_FROM_AO) + surfaceData.specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(ClampNdotV(dot(surfaceData.normalWS, V)), surfaceData.ambientOcclusion, PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness)); + #endif + + #if defined(_ENABLE_GEOMETRIC_SPECULAR_AA) && !defined(SHADER_STAGE_RAY_TRACING) + surfaceData.perceptualSmoothness = GeometricNormalFiltering(surfaceData.perceptualSmoothness, fragInputs.tangentToWorld[2], surfaceDescription.SpecularAAScreenSpaceVariance, surfaceDescription.SpecularAAThreshold); + #endif + } + + // -------------------------------------------------- + // Get Surface And BuiltinData + + void GetSurfaceAndBuiltinData(FragInputs fragInputs, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData RAY_TRACING_OPTIONAL_PARAMETERS) + { + // 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 + LODDitheringTransition(ComputeFadeMaskSeed(V, posInput.positionSS), unity_LODFade.x); + #endif + #endif + + #ifndef SHADER_UNLIT + #ifdef _DOUBLESIDED_ON + float3 doubleSidedConstants = _DoubleSidedConstants.xyz; + #else + float3 doubleSidedConstants = float3(1.0, 1.0, 1.0); + #endif + + ApplyDoubleSidedFlipOrMirror(fragInputs, doubleSidedConstants); // Apply double sided flip on the vertex normal + #endif // SHADER_UNLIT + + SurfaceDescriptionInputs surfaceDescriptionInputs = FragInputsToSurfaceDescriptionInputs(fragInputs, V); + + #if defined(HAVE_VFX_MODIFICATION) + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + GetElementPixelProperties(fragInputs, properties); + + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs, properties); + #else + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs); + #endif + + // Perform alpha test very early to save performance (a killed pixel will not sample textures) + // TODO: split graph evaluation to grab just alpha dependencies first? tricky.. + #ifdef _ALPHATEST_ON + float alphaCutoff = surfaceDescription.AlphaClipThreshold; + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + // The TransparentDepthPrepass is also used with SSR transparent. + // If an artists enable transaprent SSR but not the TransparentDepthPrepass itself, then we use AlphaClipThreshold + // otherwise if TransparentDepthPrepass is enabled we use AlphaClipThresholdDepthPrepass + #elif SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_POSTPASS + // DepthPostpass always use its own alpha threshold + alphaCutoff = surfaceDescription.AlphaClipThresholdDepthPostpass; + #elif (SHADERPASS == SHADERPASS_SHADOWS) || (SHADERPASS == SHADERPASS_RAYTRACING_VISIBILITY) + // If use shadow threshold isn't enable we don't allow any test + #endif + + GENERIC_ALPHA_TEST(surfaceDescription.Alpha, alphaCutoff); + #endif + + #if !defined(SHADER_STAGE_RAY_TRACING) && _DEPTHOFFSET_ON + ApplyDepthOffsetPositionInput(V, surfaceDescription.DepthOffset, GetViewForwardDir(), GetWorldToHClipMatrix(), posInput); + #endif + + #ifndef SHADER_UNLIT + float3 bentNormalWS; + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData, bentNormalWS); + + #ifdef FRAG_INPUTS_USE_TEXCOORD1 + float4 lightmapTexCoord1 = fragInputs.texCoord1; + #else + float4 lightmapTexCoord1 = float4(0,0,0,0); + #endif + + #ifdef FRAG_INPUTS_USE_TEXCOORD2 + float4 lightmapTexCoord2 = fragInputs.texCoord2; + #else + float4 lightmapTexCoord2 = float4(0,0,0,0); + #endif + + // Builtin Data + // For back lighting we use the oposite vertex normal + InitBuiltinData(posInput, surfaceDescription.Alpha, bentNormalWS, -fragInputs.tangentToWorld[2], lightmapTexCoord1, lightmapTexCoord2, builtinData); + + #else + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData); + + ZERO_BUILTIN_INITIALIZE(builtinData); // No call to InitBuiltinData as we don't have any lighting + builtinData.opacity = surfaceDescription.Alpha; + + #if defined(DEBUG_DISPLAY) + // Light Layers are currently not used for the Unlit shader (because it is not lit) + // But Unlit objects do cast shadows according to their rendering layer mask, which is what we want to + // display in the light layers visualization mode, therefore we need the renderingLayers + builtinData.renderingLayers = GetMeshRenderingLightLayer(); + #endif + + #endif // SHADER_UNLIT + + #ifdef _ALPHATEST_ON + // Used for sharpening by alpha to mask - Alpha to covertage is only used with depth only and forward pass (no shadow pass, no transparent pass) + builtinData.alphaClipTreshold = alphaCutoff; + #endif + + // override sampleBakedGI - not used by Unlit + + builtinData.emissiveColor = surfaceDescription.Emission; + + // Note this will not fully work on transparent surfaces (can check with _SURFACE_TYPE_TRANSPARENT define) + // We will always overwrite vt feeback with the nearest. So behind transparent surfaces vt will not be resolved + // This is a limitation of the current MRT approach. + #ifdef UNITY_VIRTUAL_TEXTURING + #endif + + #if _DEPTHOFFSET_ON + builtinData.depthOffset = surfaceDescription.DepthOffset; + #endif + + // TODO: We should generate distortion / distortionBlur for non distortion pass + #if (SHADERPASS == SHADERPASS_DISTORTION) + builtinData.distortion = surfaceDescription.Distortion; + builtinData.distortionBlur = surfaceDescription.DistortionBlur; + #endif + + #ifndef SHADER_UNLIT + // PostInitBuiltinData call ApplyDebugToBuiltinData + PostInitBuiltinData(V, posInput, surfaceData, builtinData); + #else + ApplyDebugToBuiltinData(builtinData); + #endif + + RAY_TRACING_OPTIONAL_ALPHA_TEST_PASS + } + + // -------------------------------------------------- + // Main + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassConstant.hlsl" + + // -------------------------------------------------- + // Visual Effect Vertex Invocations + + #ifdef HAVE_VFX_MODIFICATION + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/VisualEffectVertex.hlsl" + #endif + + ENDHLSL + } + } + SubShader + { + PackageRequirements { + "org.happy-turtle.order-independent-transparency" + "com.unity.render-pipelines.high-definition" + } + + Tags + { + "RenderPipeline"="HDRenderPipeline" + "RenderType"="HDLitShader" + "Queue"="Transparent+0" + "DisableBatching"="False" + "ShaderGraphShader"="true" + "ShaderGraphTargetId"="HDLitSubTarget" + } + Pass + { + Name "IndirectDXR" + Tags + { + "LightMode" = "IndirectDXR" + } + + // Render State + // RenderState: + + // Debug + // + + // -------------------------------------------------- + // Pass + + HLSLPROGRAM + + // Pragmas + #pragma target 5.0 + #pragma raytracing surface_shader + #pragma only_renderers d3d11 xboxseries ps5 + + // Keywords + #pragma multi_compile _ MULTI_BOUNCE_INDIRECT + #pragma shader_feature _ _SURFACE_TYPE_TRANSPARENT + #pragma shader_feature_local _ _DOUBLESIDED_ON + #pragma shader_feature_local _ _ADD_PRECOMPUTED_VELOCITY + #pragma shader_feature_local _ _TRANSPARENT_WRITES_MOTION_VEC + #pragma shader_feature_local_fragment _ _ENABLE_FOG_ON_TRANSPARENT + #pragma multi_compile _ DEBUG_DISPLAY + #pragma shader_feature_local_fragment _ _DISABLE_DECALS + #pragma shader_feature_local_raytracing _ _DISABLE_DECALS + #pragma shader_feature_local_fragment _ _DISABLE_SSR + #pragma shader_feature_local_raytracing _ _DISABLE_SSR + #pragma shader_feature_local_fragment _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local_raytracing _ _DISABLE_SSR_TRANSPARENT + #pragma multi_compile _ LIGHTMAP_ON + #pragma multi_compile _ DIRLIGHTMAP_COMBINED + #pragma multi_compile_fragment PROBE_VOLUMES_OFF PROBE_VOLUMES_L1 PROBE_VOLUMES_L2 + #pragma multi_compile_raytracing PROBE_VOLUMES_OFF PROBE_VOLUMES_L1 PROBE_VOLUMES_L2 + #pragma multi_compile _ DYNAMICLIGHTMAP_ON + #pragma shader_feature_local _ _REFRACTION_PLANE _REFRACTION_SPHERE _REFRACTION_THIN + // GraphKeywords: + + // For custom interpolators to inject a substruct definition before FragInputs definition, + // allowing for FragInputs to capture CI's intended for ShaderGraph's SDI. + /* WARNING: $splice Could not find named fragment 'CustomInterpolatorPreInclude' */ + + + // TODO: Merge FragInputsVFX substruct with CustomInterpolators. + #ifdef HAVE_VFX_MODIFICATION + struct FragInputsVFX + { + /* WARNING: $splice Could not find named fragment 'FragInputsVFX' */ + }; + #endif + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl" // Required by Tessellation.hlsl + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Tessellation.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Texture.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl" // Required to be include before we include properties as it define DECLARE_STACK_CB + // Always include Shader Graph version + // Always include last to avoid double macros + #include "Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl" // Need to be here for Gradient struct definition + + // -------------------------------------------------- + // Defines + + // Attribute + #define ATTRIBUTES_NEED_NORMAL + #define ATTRIBUTES_NEED_TANGENT + #define ATTRIBUTES_NEED_TEXCOORD1 + #define ATTRIBUTES_NEED_TEXCOORD2 + #define VARYINGS_NEED_POSITION_WS + #define VARYINGS_NEED_TANGENT_TO_WORLD + #define VARYINGS_NEED_TEXCOORD1 + #define VARYINGS_NEED_TEXCOORD2 + + + //Strip down the FragInputs.hlsl (on graphics), so we can only optimize the interpolators we use. + //if by accident something requests contents of FragInputs.hlsl, it will be caught as a compiler error + //Frag inputs stripping is only enabled when FRAG_INPUTS_ENABLE_STRIPPING is set + #if !defined(SHADER_STAGE_RAY_TRACING) && SHADERPASS != SHADERPASS_RAYTRACING_GBUFFER && SHADERPASS != SHADERPASS_FULL_SCREEN_DEBUG + #define FRAG_INPUTS_ENABLE_STRIPPING + #endif + #define FRAG_INPUTS_USE_TEXCOORD1 + #define FRAG_INPUTS_USE_TEXCOORD2 + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl" + + + + #define SHADERPASS SHADERPASS_RAYTRACING_INDIRECT + #define SHADOW_LOW + #define RAYTRACING_SHADER_GRAPH_RAYTRACED + #define HAS_LIGHTLOOP 1 + + + // Following two define are a workaround introduce in 10.1.x for RaytracingQualityNode + // The ShaderGraph don't support correctly migration of this node as it serialize all the node data + // in the json file making it impossible to uprgrade. Until we get a fix, we do a workaround here + // to still allow us to rename the field and keyword of this node without breaking existing code. + #ifdef RAYTRACING_SHADER_GRAPH_DEFAULT + #define RAYTRACING_SHADER_GRAPH_HIGH + #endif + + #ifdef RAYTRACING_SHADER_GRAPH_RAYTRACED + #define RAYTRACING_SHADER_GRAPH_LOW + #endif + // end + + #ifndef SHADER_UNLIT + // We need isFrontFace when using double sided - it is not required for unlit as in case of unlit double sided only drive the cullmode + // VARYINGS_NEED_CULLFACE can be define by VaryingsMeshToPS.FaceSign input if a IsFrontFace Node is included in the shader graph. + #if defined(_DOUBLESIDED_ON) && !defined(VARYINGS_NEED_CULLFACE) + #define VARYINGS_NEED_CULLFACE + #endif + #endif + + // Specific Material Define + #define _SPECULAR_OCCLUSION_FROM_AO 1 + #define _ENERGY_CONSERVING_SPECULAR 1 + + // If we use subsurface scattering, enable output split lighting (for forward pass) + #if defined(_MATERIAL_FEATURE_SUBSURFACE_SCATTERING) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define OUTPUT_SPLIT_LIGHTING + #endif + + // This shader support recursive rendering for raytracing + #define HAVE_RECURSIVE_RENDERING + + // In Path Tracing, For all single-sided, refractive materials, we want to force a thin refraction model + #if (SHADERPASS == SHADERPASS_PATH_TRACING) && !defined(_DOUBLESIDED_ON) && (defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE)) + #undef _REFRACTION_PLANE + #undef _REFRACTION_SPHERE + #define _REFRACTION_THIN + #endif + // Caution: we can use the define SHADER_UNLIT onlit after the above Material include as it is the Unlit template who define it + + // To handle SSR on transparent correctly with a possibility to enable/disable it per framesettings + // we should have a code like this: + // if !defined(_DISABLE_SSR_TRANSPARENT) + // pragma multi_compile _ WRITE_NORMAL_BUFFER + // endif + // i.e we enable the multicompile only if we can receive SSR or not, and then C# code drive + // it based on if SSR transparent in frame settings and not (and stripper can strip it). + // this is currently not possible with our current preprocessor as _DISABLE_SSR_TRANSPARENT is a keyword not a define + // so instead we used this and chose to pay the extra cost of normal write even if SSR transaprent is disabled. + // Ideally the shader graph generator should handle it but condition below can't be handle correctly for now. + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + #if !defined(_DISABLE_SSR_TRANSPARENT) && !defined(SHADER_UNLIT) + #define WRITE_NORMAL_BUFFER + #endif + #endif + + #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) + // Don't do it with debug display mode as it is possible there is no depth prepass in this case + #if !defined(_SURFACE_TYPE_TRANSPARENT) + #if SHADERPASS == SHADERPASS_FORWARD + #define SHADERPASS_FORWARD_BYPASS_ALPHA_TEST + #elif SHADERPASS == SHADERPASS_GBUFFER + #define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST + #endif + #endif + #endif + + // Define _DEFERRED_CAPABLE_MATERIAL for shader capable to run in deferred pass + #if defined(SHADER_LIT) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define _DEFERRED_CAPABLE_MATERIAL + #endif + + // Translate transparent motion vector define + #if defined(_TRANSPARENT_WRITES_MOTION_VEC) && defined(_SURFACE_TYPE_TRANSPARENT) + #define _WRITE_TRANSPARENT_MOTION_VECTOR + #endif + + // -- Graph Properties + CBUFFER_START(UnityPerMaterial) + float4 _Color; + float4 _EmissionColor; + float _UseShadowThreshold; + float4 _DoubleSidedConstants; + float _BlendMode; + float _EnableBlendModePreserveSpecularLighting; + float _RayTracing; + float _RefractionModel; + CBUFFER_END + + + // Object and Global properties + + // -- Property used by ScenePickingPass + #ifdef SCENEPICKINGPASS + float4 _SelectionID; + #endif + + // -- Properties used by SceneSelectionPass + #ifdef SCENESELECTIONPASS + int _ObjectId; + int _PassValue; + #endif + + // Includes + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingMacros.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/ShaderVariablesRaytracing.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/ShaderVariablesRaytracingLightLoop.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingIntersection.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/Lighting.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoopDef.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/Lit.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitRaytracing.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/BuiltinUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/MaterialUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingLightLoop.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RayTracingCommon.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderGraphFunctions.hlsl" + // GraphIncludes: + + // -------------------------------------------------- + // Structs and Packing + + struct SurfaceDescriptionInputs + { + float3 TangentSpaceNormal; + }; + + //Interpolator Packs: + + // -------------------------------------------------- + // Graph + + + // Graph Functions + // GraphFunctions: + + // Graph Vertex + // GraphVertex: + + // Graph Pixel + struct SurfaceDescription + { + float3 BaseColor; + float3 Emission; + float Alpha; + float3 BentNormal; + float Smoothness; + float Occlusion; + float3 NormalTS; + float Metallic; + }; + + SurfaceDescription SurfaceDescriptionFunction(SurfaceDescriptionInputs IN) + { + SurfaceDescription surface = (SurfaceDescription)0; + float4 _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4 = _Color; + float _Split_cace9cff304a4c5d84b5305897d09aa9_R_1_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[0]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_G_2_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[1]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_B_3_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[2]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[3]; + surface.BaseColor = (_Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4.xyz); + surface.Emission = float3(0, 0, 0); + surface.Alpha = _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float; + surface.BentNormal = IN.TangentSpaceNormal; + surface.Smoothness = 0.5; + surface.Occlusion = 1; + surface.NormalTS = IN.TangentSpaceNormal; + surface.Metallic = 0; + return surface; + } + + // -------------------------------------------------- + // Build Graph Inputs + #ifdef HAVE_VFX_MODIFICATION + #define VFX_SRP_ATTRIBUTES AttributesMesh + #define VaryingsMeshType VaryingsMeshToPS + #define VFX_SRP_VARYINGS VaryingsMeshType + #define VFX_SRP_SURFACE_INPUTS FragInputs + #endif + SurfaceDescriptionInputs FragInputsToSurfaceDescriptionInputs(FragInputs input, float3 viewWS) + { + SurfaceDescriptionInputs output; + ZERO_INITIALIZE(SurfaceDescriptionInputs, output); + + #if defined(SHADER_STAGE_RAY_TRACING) + #else + #endif + output.TangentSpaceNormal = float3(0.0f, 0.0f, 1.0f); + + #if UNITY_UV_STARTS_AT_TOP + #else + #endif + + + + // splice point to copy frag inputs custom interpolator pack into the SDI + /* WARNING: $splice Could not find named fragment 'CustomInterpolatorCopyToSDI' */ + + return output; + } + + // -------------------------------------------------- + // Build Surface Data (Specific Material) + + void ApplyDecalToSurfaceDataNoNormal(DecalSurfaceData decalSurfaceData, inout SurfaceData surfaceData); + + void ApplyDecalAndGetNormal(FragInputs fragInputs, PositionInputs posInput, SurfaceDescription surfaceDescription, + inout SurfaceData surfaceData) + { + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + #ifdef DECAL_NORMAL_BLENDING + // SG nodes don't ouptut surface gradients, so if decals require surf grad blending, we have to convert + // the normal to gradient before applying the decal. We then have to resolve the gradient back to world space + float3 normalTS; + + normalTS = SurfaceGradientFromTangentSpaceNormalAndFromTBN(surfaceDescription.NormalTS, + fragInputs.tangentToWorld[0], fragInputs.tangentToWorld[1]); + + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, fragInputs.tangentToWorld[2], normalTS); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + + GetNormalWS_SG(fragInputs, normalTS, surfaceData.normalWS, doubleSidedConstants); + #else + // normal delivered to master node + GetNormalWS(fragInputs, surfaceDescription.NormalTS, surfaceData.normalWS, doubleSidedConstants); + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + // Both uses and modifies 'surfaceData.normalWS'. + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, surfaceData.normalWS.xyz); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + #endif + } + void BuildSurfaceData(FragInputs fragInputs, inout SurfaceDescription surfaceDescription, float3 V, PositionInputs posInput, out SurfaceData surfaceData, out float3 bentNormalWS) + { + ZERO_INITIALIZE(SurfaceData, surfaceData); + + // specularOcclusion need to be init ahead of decal to quiet the compiler that modify the SurfaceData struct + // however specularOcclusion can come from the graph, so need to be init here so it can be override. + surfaceData.specularOcclusion = 1.0; + + surfaceData.baseColor = surfaceDescription.BaseColor; + surfaceData.perceptualSmoothness = surfaceDescription.Smoothness; + surfaceData.ambientOcclusion = surfaceDescription.Occlusion; + surfaceData.metallic = surfaceDescription.Metallic; + + #if defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE) || defined(_REFRACTION_THIN) + if (_EnableSSRefraction) + { + + surfaceData.transmittanceMask = (1.0 - surfaceDescription.Alpha); + surfaceDescription.Alpha = 1.0; + } + else + { + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + surfaceDescription.Alpha = 1.0; + } + #else + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + #endif + + // These static material feature allow compile time optimization + surfaceData.materialFeatures = MATERIALFEATUREFLAGS_LIT_STANDARD; + #ifdef _MATERIAL_FEATURE_SUBSURFACE_SCATTERING + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING; + #endif + + #ifdef _MATERIAL_FEATURE_TRANSMISSION + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_TRANSMISSION; + #endif + + #ifdef _MATERIAL_FEATURE_ANISOTROPY + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_ANISOTROPY; + + // Initialize the normal to something non-zero to avoid a div-zero warning for anisotropy. + surfaceData.normalWS = float3(0, 1, 0); + #endif + + #ifdef _MATERIAL_FEATURE_IRIDESCENCE + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_IRIDESCENCE; + #endif + + #ifdef _MATERIAL_FEATURE_SPECULAR_COLOR + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR; + #endif + + #ifdef _MATERIAL_FEATURE_CLEAR_COAT + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_CLEAR_COAT; + #endif + + #if defined (_MATERIAL_FEATURE_SPECULAR_COLOR) && defined (_ENERGY_CONSERVING_SPECULAR) + // Require to have setup baseColor + // Reproduce the energy conservation done in legacy Unity. Not ideal but better for compatibility and users can unchek it + surfaceData.baseColor *= (1.0 - Max3(surfaceData.specularColor.r, surfaceData.specularColor.g, surfaceData.specularColor.b)); + #endif + + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + ApplyDecalAndGetNormal(fragInputs, posInput, surfaceDescription, surfaceData); + + surfaceData.geomNormalWS = fragInputs.tangentToWorld[2]; + + surfaceData.tangentWS = normalize(fragInputs.tangentToWorld[0].xyz); // The tangent is not normalize in tangentToWorld for mikkt. TODO: Check if it expected that we normalize with Morten. Tag: SURFACE_GRADIENT + + + bentNormalWS = surfaceData.normalWS; + + surfaceData.tangentWS = Orthonormalize(surfaceData.tangentWS, surfaceData.normalWS); + + #ifdef DEBUG_DISPLAY + if (_DebugMipMapMode != DEBUGMIPMAPMODE_NONE) + { + // TODO: need to update mip info + surfaceData.metallic = 0; + } + + // We need to call ApplyDebugToSurfaceData after filling the surfarcedata and before filling builtinData + // as it can modify attribute use for static lighting + ApplyDebugToSurfaceData(fragInputs.tangentToWorld, surfaceData); + #endif + + // By default we use the ambient occlusion with Tri-ace trick (apply outside) for specular occlusion. + // If user provide bent normal then we process a better term + #if defined(_SPECULAR_OCCLUSION_CUSTOM) + // Just use the value passed through via the slot (not active otherwise) + #elif defined(_SPECULAR_OCCLUSION_FROM_AO_BENT_NORMAL) + // If we have bent normal and ambient occlusion, process a specular occlusion + surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData.normalWS, surfaceData.ambientOcclusion, PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness)); + #elif defined(_AMBIENT_OCCLUSION) && defined(_SPECULAR_OCCLUSION_FROM_AO) + surfaceData.specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(ClampNdotV(dot(surfaceData.normalWS, V)), surfaceData.ambientOcclusion, PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness)); + #endif + + #if defined(_ENABLE_GEOMETRIC_SPECULAR_AA) && !defined(SHADER_STAGE_RAY_TRACING) + surfaceData.perceptualSmoothness = GeometricNormalFiltering(surfaceData.perceptualSmoothness, fragInputs.tangentToWorld[2], surfaceDescription.SpecularAAScreenSpaceVariance, surfaceDescription.SpecularAAThreshold); + #endif + } + + // -------------------------------------------------- + // Get Surface And BuiltinData + + void GetSurfaceAndBuiltinData(FragInputs fragInputs, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData RAY_TRACING_OPTIONAL_PARAMETERS) + { + // 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 + LODDitheringTransition(ComputeFadeMaskSeed(V, posInput.positionSS), unity_LODFade.x); + #endif + #endif + + #ifndef SHADER_UNLIT + #ifdef _DOUBLESIDED_ON + float3 doubleSidedConstants = _DoubleSidedConstants.xyz; + #else + float3 doubleSidedConstants = float3(1.0, 1.0, 1.0); + #endif + + ApplyDoubleSidedFlipOrMirror(fragInputs, doubleSidedConstants); // Apply double sided flip on the vertex normal + #endif // SHADER_UNLIT + + SurfaceDescriptionInputs surfaceDescriptionInputs = FragInputsToSurfaceDescriptionInputs(fragInputs, V); + + #if defined(HAVE_VFX_MODIFICATION) + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + GetElementPixelProperties(fragInputs, properties); + + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs, properties); + #else + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs); + #endif + + // Perform alpha test very early to save performance (a killed pixel will not sample textures) + // TODO: split graph evaluation to grab just alpha dependencies first? tricky.. + #ifdef _ALPHATEST_ON + float alphaCutoff = surfaceDescription.AlphaClipThreshold; + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + // The TransparentDepthPrepass is also used with SSR transparent. + // If an artists enable transaprent SSR but not the TransparentDepthPrepass itself, then we use AlphaClipThreshold + // otherwise if TransparentDepthPrepass is enabled we use AlphaClipThresholdDepthPrepass + #elif SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_POSTPASS + // DepthPostpass always use its own alpha threshold + alphaCutoff = surfaceDescription.AlphaClipThresholdDepthPostpass; + #elif (SHADERPASS == SHADERPASS_SHADOWS) || (SHADERPASS == SHADERPASS_RAYTRACING_VISIBILITY) + // If use shadow threshold isn't enable we don't allow any test + #endif + + GENERIC_ALPHA_TEST(surfaceDescription.Alpha, alphaCutoff); + #endif + + #if !defined(SHADER_STAGE_RAY_TRACING) && _DEPTHOFFSET_ON + ApplyDepthOffsetPositionInput(V, surfaceDescription.DepthOffset, GetViewForwardDir(), GetWorldToHClipMatrix(), posInput); + #endif + + #ifndef SHADER_UNLIT + float3 bentNormalWS; + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData, bentNormalWS); + + #ifdef FRAG_INPUTS_USE_TEXCOORD1 + float4 lightmapTexCoord1 = fragInputs.texCoord1; + #else + float4 lightmapTexCoord1 = float4(0,0,0,0); + #endif + + #ifdef FRAG_INPUTS_USE_TEXCOORD2 + float4 lightmapTexCoord2 = fragInputs.texCoord2; + #else + float4 lightmapTexCoord2 = float4(0,0,0,0); + #endif + + // Builtin Data + // For back lighting we use the oposite vertex normal + InitBuiltinData(posInput, surfaceDescription.Alpha, bentNormalWS, -fragInputs.tangentToWorld[2], lightmapTexCoord1, lightmapTexCoord2, builtinData); + + #else + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData); + + ZERO_BUILTIN_INITIALIZE(builtinData); // No call to InitBuiltinData as we don't have any lighting + builtinData.opacity = surfaceDescription.Alpha; + + #if defined(DEBUG_DISPLAY) + // Light Layers are currently not used for the Unlit shader (because it is not lit) + // But Unlit objects do cast shadows according to their rendering layer mask, which is what we want to + // display in the light layers visualization mode, therefore we need the renderingLayers + builtinData.renderingLayers = GetMeshRenderingLightLayer(); + #endif + + #endif // SHADER_UNLIT + + #ifdef _ALPHATEST_ON + // Used for sharpening by alpha to mask - Alpha to covertage is only used with depth only and forward pass (no shadow pass, no transparent pass) + builtinData.alphaClipTreshold = alphaCutoff; + #endif + + // override sampleBakedGI - not used by Unlit + + builtinData.emissiveColor = surfaceDescription.Emission; + + // Note this will not fully work on transparent surfaces (can check with _SURFACE_TYPE_TRANSPARENT define) + // We will always overwrite vt feeback with the nearest. So behind transparent surfaces vt will not be resolved + // This is a limitation of the current MRT approach. + #ifdef UNITY_VIRTUAL_TEXTURING + #endif + + #if _DEPTHOFFSET_ON + builtinData.depthOffset = surfaceDescription.DepthOffset; + #endif + + // TODO: We should generate distortion / distortionBlur for non distortion pass + #if (SHADERPASS == SHADERPASS_DISTORTION) + builtinData.distortion = surfaceDescription.Distortion; + builtinData.distortionBlur = surfaceDescription.DistortionBlur; + #endif + + #ifndef SHADER_UNLIT + // PostInitBuiltinData call ApplyDebugToBuiltinData + PostInitBuiltinData(V, posInput, surfaceData, builtinData); + #else + ApplyDebugToBuiltinData(builtinData); + #endif + + RAY_TRACING_OPTIONAL_ALPHA_TEST_PASS + } + + // -------------------------------------------------- + // Main + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassRaytracingIndirect.hlsl" + + // -------------------------------------------------- + // Visual Effect Vertex Invocations + + #ifdef HAVE_VFX_MODIFICATION + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/VisualEffectVertex.hlsl" + #endif + + ENDHLSL + } + Pass + { + Name "VisibilityDXR" + Tags + { + "LightMode" = "VisibilityDXR" + } + + // Render State + // RenderState: + + // Debug + // + + // -------------------------------------------------- + // Pass + + HLSLPROGRAM + + // Pragmas + #pragma target 5.0 + #pragma raytracing surface_shader + #pragma only_renderers d3d11 xboxseries ps5 + + // Keywords + #pragma multi_compile _ TRANSPARENT_COLOR_SHADOW + #pragma shader_feature _ _SURFACE_TYPE_TRANSPARENT + #pragma shader_feature_local _ _DOUBLESIDED_ON + #pragma shader_feature_local _ _ADD_PRECOMPUTED_VELOCITY + #pragma shader_feature_local _ _TRANSPARENT_WRITES_MOTION_VEC + #pragma shader_feature_local_fragment _ _ENABLE_FOG_ON_TRANSPARENT + #pragma shader_feature_local_fragment _ _DISABLE_DECALS + #pragma shader_feature_local_raytracing _ _DISABLE_DECALS + #pragma shader_feature_local_fragment _ _DISABLE_SSR + #pragma shader_feature_local_raytracing _ _DISABLE_SSR + #pragma shader_feature_local_fragment _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local_raytracing _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local _ _REFRACTION_PLANE _REFRACTION_SPHERE _REFRACTION_THIN + // GraphKeywords: + + // For custom interpolators to inject a substruct definition before FragInputs definition, + // allowing for FragInputs to capture CI's intended for ShaderGraph's SDI. + /* WARNING: $splice Could not find named fragment 'CustomInterpolatorPreInclude' */ + + + // TODO: Merge FragInputsVFX substruct with CustomInterpolators. + #ifdef HAVE_VFX_MODIFICATION + struct FragInputsVFX + { + /* WARNING: $splice Could not find named fragment 'FragInputsVFX' */ + }; + #endif + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl" // Required by Tessellation.hlsl + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Tessellation.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Texture.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl" // Required to be include before we include properties as it define DECLARE_STACK_CB + // Always include Shader Graph version + // Always include last to avoid double macros + #include "Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl" // Need to be here for Gradient struct definition + + // -------------------------------------------------- + // Defines + + // Attribute + + + //Strip down the FragInputs.hlsl (on graphics), so we can only optimize the interpolators we use. + //if by accident something requests contents of FragInputs.hlsl, it will be caught as a compiler error + //Frag inputs stripping is only enabled when FRAG_INPUTS_ENABLE_STRIPPING is set + #if !defined(SHADER_STAGE_RAY_TRACING) && SHADERPASS != SHADERPASS_RAYTRACING_GBUFFER && SHADERPASS != SHADERPASS_FULL_SCREEN_DEBUG + #define FRAG_INPUTS_ENABLE_STRIPPING + #endif + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl" + + + + #define SHADERPASS SHADERPASS_RAYTRACING_VISIBILITY + #define RAYTRACING_SHADER_GRAPH_RAYTRACED + + + // Following two define are a workaround introduce in 10.1.x for RaytracingQualityNode + // The ShaderGraph don't support correctly migration of this node as it serialize all the node data + // in the json file making it impossible to uprgrade. Until we get a fix, we do a workaround here + // to still allow us to rename the field and keyword of this node without breaking existing code. + #ifdef RAYTRACING_SHADER_GRAPH_DEFAULT + #define RAYTRACING_SHADER_GRAPH_HIGH + #endif + + #ifdef RAYTRACING_SHADER_GRAPH_RAYTRACED + #define RAYTRACING_SHADER_GRAPH_LOW + #endif + // end + + #ifndef SHADER_UNLIT + // We need isFrontFace when using double sided - it is not required for unlit as in case of unlit double sided only drive the cullmode + // VARYINGS_NEED_CULLFACE can be define by VaryingsMeshToPS.FaceSign input if a IsFrontFace Node is included in the shader graph. + #if defined(_DOUBLESIDED_ON) && !defined(VARYINGS_NEED_CULLFACE) + #define VARYINGS_NEED_CULLFACE + #endif + #endif + + // Specific Material Define + #define _SPECULAR_OCCLUSION_FROM_AO 1 + #define _ENERGY_CONSERVING_SPECULAR 1 + + // If we use subsurface scattering, enable output split lighting (for forward pass) + #if defined(_MATERIAL_FEATURE_SUBSURFACE_SCATTERING) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define OUTPUT_SPLIT_LIGHTING + #endif + + // This shader support recursive rendering for raytracing + #define HAVE_RECURSIVE_RENDERING + + // In Path Tracing, For all single-sided, refractive materials, we want to force a thin refraction model + #if (SHADERPASS == SHADERPASS_PATH_TRACING) && !defined(_DOUBLESIDED_ON) && (defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE)) + #undef _REFRACTION_PLANE + #undef _REFRACTION_SPHERE + #define _REFRACTION_THIN + #endif + // Caution: we can use the define SHADER_UNLIT onlit after the above Material include as it is the Unlit template who define it + + // To handle SSR on transparent correctly with a possibility to enable/disable it per framesettings + // we should have a code like this: + // if !defined(_DISABLE_SSR_TRANSPARENT) + // pragma multi_compile _ WRITE_NORMAL_BUFFER + // endif + // i.e we enable the multicompile only if we can receive SSR or not, and then C# code drive + // it based on if SSR transparent in frame settings and not (and stripper can strip it). + // this is currently not possible with our current preprocessor as _DISABLE_SSR_TRANSPARENT is a keyword not a define + // so instead we used this and chose to pay the extra cost of normal write even if SSR transaprent is disabled. + // Ideally the shader graph generator should handle it but condition below can't be handle correctly for now. + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + #if !defined(_DISABLE_SSR_TRANSPARENT) && !defined(SHADER_UNLIT) + #define WRITE_NORMAL_BUFFER + #endif + #endif + + #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) + // Don't do it with debug display mode as it is possible there is no depth prepass in this case + #if !defined(_SURFACE_TYPE_TRANSPARENT) + #if SHADERPASS == SHADERPASS_FORWARD + #define SHADERPASS_FORWARD_BYPASS_ALPHA_TEST + #elif SHADERPASS == SHADERPASS_GBUFFER + #define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST + #endif + #endif + #endif + + // Define _DEFERRED_CAPABLE_MATERIAL for shader capable to run in deferred pass + #if defined(SHADER_LIT) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define _DEFERRED_CAPABLE_MATERIAL + #endif + + // Translate transparent motion vector define + #if defined(_TRANSPARENT_WRITES_MOTION_VEC) && defined(_SURFACE_TYPE_TRANSPARENT) + #define _WRITE_TRANSPARENT_MOTION_VECTOR + #endif + + // -- Graph Properties + CBUFFER_START(UnityPerMaterial) + float4 _Color; + float4 _EmissionColor; + float _UseShadowThreshold; + float4 _DoubleSidedConstants; + float _BlendMode; + float _EnableBlendModePreserveSpecularLighting; + float _RayTracing; + float _RefractionModel; + CBUFFER_END + + + // Object and Global properties + + // -- Property used by ScenePickingPass + #ifdef SCENEPICKINGPASS + float4 _SelectionID; + #endif + + // -- Properties used by SceneSelectionPass + #ifdef SCENESELECTIONPASS + int _ObjectId; + int _PassValue; + #endif + + // Includes + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingMacros.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/ShaderVariablesRaytracing.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/ShaderVariablesRaytracingLightLoop.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingIntersection.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/Lit.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitRaytracing.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/BuiltinUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/MaterialUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RayTracingCommon.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderGraphFunctions.hlsl" + // GraphIncludes: + + // -------------------------------------------------- + // Structs and Packing + + struct SurfaceDescriptionInputs + { + float3 TangentSpaceNormal; + }; + + //Interpolator Packs: + + // -------------------------------------------------- + // Graph + + + // Graph Functions + // GraphFunctions: + + // Graph Vertex + // GraphVertex: + + // Graph Pixel + struct SurfaceDescription + { + float3 BaseColor; + float3 Emission; + float Alpha; + float3 BentNormal; + float Smoothness; + float Occlusion; + float3 NormalTS; + float Metallic; + }; + + SurfaceDescription SurfaceDescriptionFunction(SurfaceDescriptionInputs IN) + { + SurfaceDescription surface = (SurfaceDescription)0; + float4 _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4 = _Color; + float _Split_cace9cff304a4c5d84b5305897d09aa9_R_1_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[0]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_G_2_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[1]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_B_3_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[2]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[3]; + surface.BaseColor = (_Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4.xyz); + surface.Emission = float3(0, 0, 0); + surface.Alpha = _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float; + surface.BentNormal = IN.TangentSpaceNormal; + surface.Smoothness = 0.5; + surface.Occlusion = 1; + surface.NormalTS = IN.TangentSpaceNormal; + surface.Metallic = 0; + return surface; + } + + // -------------------------------------------------- + // Build Graph Inputs + #ifdef HAVE_VFX_MODIFICATION + #define VFX_SRP_ATTRIBUTES AttributesMesh + #define VaryingsMeshType VaryingsMeshToPS + #define VFX_SRP_VARYINGS VaryingsMeshType + #define VFX_SRP_SURFACE_INPUTS FragInputs + #endif + SurfaceDescriptionInputs FragInputsToSurfaceDescriptionInputs(FragInputs input, float3 viewWS) + { + SurfaceDescriptionInputs output; + ZERO_INITIALIZE(SurfaceDescriptionInputs, output); + + #if defined(SHADER_STAGE_RAY_TRACING) + #else + #endif + output.TangentSpaceNormal = float3(0.0f, 0.0f, 1.0f); + + #if UNITY_UV_STARTS_AT_TOP + #else + #endif + + + + // splice point to copy frag inputs custom interpolator pack into the SDI + /* WARNING: $splice Could not find named fragment 'CustomInterpolatorCopyToSDI' */ + + return output; + } + + // -------------------------------------------------- + // Build Surface Data (Specific Material) + + void ApplyDecalToSurfaceDataNoNormal(DecalSurfaceData decalSurfaceData, inout SurfaceData surfaceData); + + void ApplyDecalAndGetNormal(FragInputs fragInputs, PositionInputs posInput, SurfaceDescription surfaceDescription, + inout SurfaceData surfaceData) + { + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + #ifdef DECAL_NORMAL_BLENDING + // SG nodes don't ouptut surface gradients, so if decals require surf grad blending, we have to convert + // the normal to gradient before applying the decal. We then have to resolve the gradient back to world space + float3 normalTS; + + normalTS = SurfaceGradientFromTangentSpaceNormalAndFromTBN(surfaceDescription.NormalTS, + fragInputs.tangentToWorld[0], fragInputs.tangentToWorld[1]); + + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, fragInputs.tangentToWorld[2], normalTS); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + + GetNormalWS_SG(fragInputs, normalTS, surfaceData.normalWS, doubleSidedConstants); + #else + // normal delivered to master node + GetNormalWS(fragInputs, surfaceDescription.NormalTS, surfaceData.normalWS, doubleSidedConstants); + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + // Both uses and modifies 'surfaceData.normalWS'. + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, surfaceData.normalWS.xyz); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + #endif + } + void BuildSurfaceData(FragInputs fragInputs, inout SurfaceDescription surfaceDescription, float3 V, PositionInputs posInput, out SurfaceData surfaceData, out float3 bentNormalWS) + { + ZERO_INITIALIZE(SurfaceData, surfaceData); + + // specularOcclusion need to be init ahead of decal to quiet the compiler that modify the SurfaceData struct + // however specularOcclusion can come from the graph, so need to be init here so it can be override. + surfaceData.specularOcclusion = 1.0; + + surfaceData.baseColor = surfaceDescription.BaseColor; + surfaceData.perceptualSmoothness = surfaceDescription.Smoothness; + surfaceData.ambientOcclusion = surfaceDescription.Occlusion; + surfaceData.metallic = surfaceDescription.Metallic; + + #if defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE) || defined(_REFRACTION_THIN) + if (_EnableSSRefraction) + { + + surfaceData.transmittanceMask = (1.0 - surfaceDescription.Alpha); + surfaceDescription.Alpha = 1.0; + } + else + { + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + surfaceDescription.Alpha = 1.0; + } + #else + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + #endif + + // These static material feature allow compile time optimization + surfaceData.materialFeatures = MATERIALFEATUREFLAGS_LIT_STANDARD; + #ifdef _MATERIAL_FEATURE_SUBSURFACE_SCATTERING + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING; + #endif + + #ifdef _MATERIAL_FEATURE_TRANSMISSION + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_TRANSMISSION; + #endif + + #ifdef _MATERIAL_FEATURE_ANISOTROPY + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_ANISOTROPY; + + // Initialize the normal to something non-zero to avoid a div-zero warning for anisotropy. + surfaceData.normalWS = float3(0, 1, 0); + #endif + + #ifdef _MATERIAL_FEATURE_IRIDESCENCE + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_IRIDESCENCE; + #endif + + #ifdef _MATERIAL_FEATURE_SPECULAR_COLOR + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR; + #endif + + #ifdef _MATERIAL_FEATURE_CLEAR_COAT + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_CLEAR_COAT; + #endif + + #if defined (_MATERIAL_FEATURE_SPECULAR_COLOR) && defined (_ENERGY_CONSERVING_SPECULAR) + // Require to have setup baseColor + // Reproduce the energy conservation done in legacy Unity. Not ideal but better for compatibility and users can unchek it + surfaceData.baseColor *= (1.0 - Max3(surfaceData.specularColor.r, surfaceData.specularColor.g, surfaceData.specularColor.b)); + #endif + + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + ApplyDecalAndGetNormal(fragInputs, posInput, surfaceDescription, surfaceData); + + surfaceData.geomNormalWS = fragInputs.tangentToWorld[2]; + + surfaceData.tangentWS = normalize(fragInputs.tangentToWorld[0].xyz); // The tangent is not normalize in tangentToWorld for mikkt. TODO: Check if it expected that we normalize with Morten. Tag: SURFACE_GRADIENT + + + bentNormalWS = surfaceData.normalWS; + + surfaceData.tangentWS = Orthonormalize(surfaceData.tangentWS, surfaceData.normalWS); + + #ifdef DEBUG_DISPLAY + if (_DebugMipMapMode != DEBUGMIPMAPMODE_NONE) + { + // TODO: need to update mip info + surfaceData.metallic = 0; + } + + // We need to call ApplyDebugToSurfaceData after filling the surfarcedata and before filling builtinData + // as it can modify attribute use for static lighting + ApplyDebugToSurfaceData(fragInputs.tangentToWorld, surfaceData); + #endif + + // By default we use the ambient occlusion with Tri-ace trick (apply outside) for specular occlusion. + // If user provide bent normal then we process a better term + #if defined(_SPECULAR_OCCLUSION_CUSTOM) + // Just use the value passed through via the slot (not active otherwise) + #elif defined(_SPECULAR_OCCLUSION_FROM_AO_BENT_NORMAL) + // If we have bent normal and ambient occlusion, process a specular occlusion + surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData.normalWS, surfaceData.ambientOcclusion, PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness)); + #elif defined(_AMBIENT_OCCLUSION) && defined(_SPECULAR_OCCLUSION_FROM_AO) + surfaceData.specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(ClampNdotV(dot(surfaceData.normalWS, V)), surfaceData.ambientOcclusion, PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness)); + #endif + + #if defined(_ENABLE_GEOMETRIC_SPECULAR_AA) && !defined(SHADER_STAGE_RAY_TRACING) + surfaceData.perceptualSmoothness = GeometricNormalFiltering(surfaceData.perceptualSmoothness, fragInputs.tangentToWorld[2], surfaceDescription.SpecularAAScreenSpaceVariance, surfaceDescription.SpecularAAThreshold); + #endif + } + + // -------------------------------------------------- + // Get Surface And BuiltinData + + void GetSurfaceAndBuiltinData(FragInputs fragInputs, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData RAY_TRACING_OPTIONAL_PARAMETERS) + { + // 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 + LODDitheringTransition(ComputeFadeMaskSeed(V, posInput.positionSS), unity_LODFade.x); + #endif + #endif + + #ifndef SHADER_UNLIT + #ifdef _DOUBLESIDED_ON + float3 doubleSidedConstants = _DoubleSidedConstants.xyz; + #else + float3 doubleSidedConstants = float3(1.0, 1.0, 1.0); + #endif + + ApplyDoubleSidedFlipOrMirror(fragInputs, doubleSidedConstants); // Apply double sided flip on the vertex normal + #endif // SHADER_UNLIT + + SurfaceDescriptionInputs surfaceDescriptionInputs = FragInputsToSurfaceDescriptionInputs(fragInputs, V); + + #if defined(HAVE_VFX_MODIFICATION) + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + GetElementPixelProperties(fragInputs, properties); + + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs, properties); + #else + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs); + #endif + + // Perform alpha test very early to save performance (a killed pixel will not sample textures) + // TODO: split graph evaluation to grab just alpha dependencies first? tricky.. + #ifdef _ALPHATEST_ON + float alphaCutoff = surfaceDescription.AlphaClipThreshold; + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + // The TransparentDepthPrepass is also used with SSR transparent. + // If an artists enable transaprent SSR but not the TransparentDepthPrepass itself, then we use AlphaClipThreshold + // otherwise if TransparentDepthPrepass is enabled we use AlphaClipThresholdDepthPrepass + #elif SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_POSTPASS + // DepthPostpass always use its own alpha threshold + alphaCutoff = surfaceDescription.AlphaClipThresholdDepthPostpass; + #elif (SHADERPASS == SHADERPASS_SHADOWS) || (SHADERPASS == SHADERPASS_RAYTRACING_VISIBILITY) + // If use shadow threshold isn't enable we don't allow any test + #endif + + GENERIC_ALPHA_TEST(surfaceDescription.Alpha, alphaCutoff); + #endif + + #if !defined(SHADER_STAGE_RAY_TRACING) && _DEPTHOFFSET_ON + ApplyDepthOffsetPositionInput(V, surfaceDescription.DepthOffset, GetViewForwardDir(), GetWorldToHClipMatrix(), posInput); + #endif + + #ifndef SHADER_UNLIT + float3 bentNormalWS; + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData, bentNormalWS); + + #ifdef FRAG_INPUTS_USE_TEXCOORD1 + float4 lightmapTexCoord1 = fragInputs.texCoord1; + #else + float4 lightmapTexCoord1 = float4(0,0,0,0); + #endif + + #ifdef FRAG_INPUTS_USE_TEXCOORD2 + float4 lightmapTexCoord2 = fragInputs.texCoord2; + #else + float4 lightmapTexCoord2 = float4(0,0,0,0); + #endif + + // Builtin Data + // For back lighting we use the oposite vertex normal + InitBuiltinData(posInput, surfaceDescription.Alpha, bentNormalWS, -fragInputs.tangentToWorld[2], lightmapTexCoord1, lightmapTexCoord2, builtinData); + + #else + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData); + + ZERO_BUILTIN_INITIALIZE(builtinData); // No call to InitBuiltinData as we don't have any lighting + builtinData.opacity = surfaceDescription.Alpha; + + #if defined(DEBUG_DISPLAY) + // Light Layers are currently not used for the Unlit shader (because it is not lit) + // But Unlit objects do cast shadows according to their rendering layer mask, which is what we want to + // display in the light layers visualization mode, therefore we need the renderingLayers + builtinData.renderingLayers = GetMeshRenderingLightLayer(); + #endif + + #endif // SHADER_UNLIT + + #ifdef _ALPHATEST_ON + // Used for sharpening by alpha to mask - Alpha to covertage is only used with depth only and forward pass (no shadow pass, no transparent pass) + builtinData.alphaClipTreshold = alphaCutoff; + #endif + + // override sampleBakedGI - not used by Unlit + + builtinData.emissiveColor = surfaceDescription.Emission; + + // Note this will not fully work on transparent surfaces (can check with _SURFACE_TYPE_TRANSPARENT define) + // We will always overwrite vt feeback with the nearest. So behind transparent surfaces vt will not be resolved + // This is a limitation of the current MRT approach. + #ifdef UNITY_VIRTUAL_TEXTURING + #endif + + #if _DEPTHOFFSET_ON + builtinData.depthOffset = surfaceDescription.DepthOffset; + #endif + + // TODO: We should generate distortion / distortionBlur for non distortion pass + #if (SHADERPASS == SHADERPASS_DISTORTION) + builtinData.distortion = surfaceDescription.Distortion; + builtinData.distortionBlur = surfaceDescription.DistortionBlur; + #endif + + #ifndef SHADER_UNLIT + // PostInitBuiltinData call ApplyDebugToBuiltinData + PostInitBuiltinData(V, posInput, surfaceData, builtinData); + #else + ApplyDebugToBuiltinData(builtinData); + #endif + + RAY_TRACING_OPTIONAL_ALPHA_TEST_PASS + } + + // -------------------------------------------------- + // Main + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassRaytracingVisibility.hlsl" + + // -------------------------------------------------- + // Visual Effect Vertex Invocations + + #ifdef HAVE_VFX_MODIFICATION + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/VisualEffectVertex.hlsl" + #endif + + ENDHLSL + } + Pass + { + Name "ForwardDXR" + Tags + { + "LightMode" = "ForwardDXR" + } + + // Render State + // RenderState: + + // Debug + // + + // -------------------------------------------------- + // Pass + + HLSLPROGRAM + + // Pragmas + #pragma target 5.0 + #pragma raytracing surface_shader + #pragma only_renderers d3d11 xboxseries ps5 + + // Keywords + #pragma shader_feature _ _SURFACE_TYPE_TRANSPARENT + #pragma shader_feature_local _ _DOUBLESIDED_ON + #pragma shader_feature_local _ _ADD_PRECOMPUTED_VELOCITY + #pragma shader_feature_local _ _TRANSPARENT_WRITES_MOTION_VEC + #pragma shader_feature_local_fragment _ _ENABLE_FOG_ON_TRANSPARENT + #pragma multi_compile _ DEBUG_DISPLAY + #pragma shader_feature_local_fragment _ _DISABLE_DECALS + #pragma shader_feature_local_raytracing _ _DISABLE_DECALS + #pragma shader_feature_local_fragment _ _DISABLE_SSR + #pragma shader_feature_local_raytracing _ _DISABLE_SSR + #pragma shader_feature_local_fragment _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local_raytracing _ _DISABLE_SSR_TRANSPARENT + #pragma multi_compile _ LIGHTMAP_ON + #pragma multi_compile _ DIRLIGHTMAP_COMBINED + #pragma multi_compile_fragment PROBE_VOLUMES_OFF PROBE_VOLUMES_L1 PROBE_VOLUMES_L2 + #pragma multi_compile_raytracing PROBE_VOLUMES_OFF PROBE_VOLUMES_L1 PROBE_VOLUMES_L2 + #pragma multi_compile _ DYNAMICLIGHTMAP_ON + #pragma shader_feature_local _ _REFRACTION_PLANE _REFRACTION_SPHERE _REFRACTION_THIN + // GraphKeywords: + + // For custom interpolators to inject a substruct definition before FragInputs definition, + // allowing for FragInputs to capture CI's intended for ShaderGraph's SDI. + /* WARNING: $splice Could not find named fragment 'CustomInterpolatorPreInclude' */ + + + // TODO: Merge FragInputsVFX substruct with CustomInterpolators. + #ifdef HAVE_VFX_MODIFICATION + struct FragInputsVFX + { + /* WARNING: $splice Could not find named fragment 'FragInputsVFX' */ + }; + #endif + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl" // Required by Tessellation.hlsl + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Tessellation.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Texture.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl" // Required to be include before we include properties as it define DECLARE_STACK_CB + // Always include Shader Graph version + // Always include last to avoid double macros + #include "Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl" // Need to be here for Gradient struct definition + + // -------------------------------------------------- + // Defines + + // Attribute + #define ATTRIBUTES_NEED_NORMAL + #define ATTRIBUTES_NEED_TANGENT + #define ATTRIBUTES_NEED_TEXCOORD1 + #define ATTRIBUTES_NEED_TEXCOORD2 + #define VARYINGS_NEED_POSITION_WS + #define VARYINGS_NEED_TANGENT_TO_WORLD + #define VARYINGS_NEED_TEXCOORD1 + #define VARYINGS_NEED_TEXCOORD2 + + + //Strip down the FragInputs.hlsl (on graphics), so we can only optimize the interpolators we use. + //if by accident something requests contents of FragInputs.hlsl, it will be caught as a compiler error + //Frag inputs stripping is only enabled when FRAG_INPUTS_ENABLE_STRIPPING is set + #if !defined(SHADER_STAGE_RAY_TRACING) && SHADERPASS != SHADERPASS_RAYTRACING_GBUFFER && SHADERPASS != SHADERPASS_FULL_SCREEN_DEBUG + #define FRAG_INPUTS_ENABLE_STRIPPING + #endif + #define FRAG_INPUTS_USE_TEXCOORD1 + #define FRAG_INPUTS_USE_TEXCOORD2 + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl" + + + + #define SHADERPASS SHADERPASS_RAYTRACING_FORWARD + #define SHADOW_LOW + #define RAYTRACING_SHADER_GRAPH_RAYTRACED + #define HAS_LIGHTLOOP 1 + + + // Following two define are a workaround introduce in 10.1.x for RaytracingQualityNode + // The ShaderGraph don't support correctly migration of this node as it serialize all the node data + // in the json file making it impossible to uprgrade. Until we get a fix, we do a workaround here + // to still allow us to rename the field and keyword of this node without breaking existing code. + #ifdef RAYTRACING_SHADER_GRAPH_DEFAULT + #define RAYTRACING_SHADER_GRAPH_HIGH + #endif + + #ifdef RAYTRACING_SHADER_GRAPH_RAYTRACED + #define RAYTRACING_SHADER_GRAPH_LOW + #endif + // end + + #ifndef SHADER_UNLIT + // We need isFrontFace when using double sided - it is not required for unlit as in case of unlit double sided only drive the cullmode + // VARYINGS_NEED_CULLFACE can be define by VaryingsMeshToPS.FaceSign input if a IsFrontFace Node is included in the shader graph. + #if defined(_DOUBLESIDED_ON) && !defined(VARYINGS_NEED_CULLFACE) + #define VARYINGS_NEED_CULLFACE + #endif + #endif + + // Specific Material Define + #define _SPECULAR_OCCLUSION_FROM_AO 1 + #define _ENERGY_CONSERVING_SPECULAR 1 + + // If we use subsurface scattering, enable output split lighting (for forward pass) + #if defined(_MATERIAL_FEATURE_SUBSURFACE_SCATTERING) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define OUTPUT_SPLIT_LIGHTING + #endif + + // This shader support recursive rendering for raytracing + #define HAVE_RECURSIVE_RENDERING + + // In Path Tracing, For all single-sided, refractive materials, we want to force a thin refraction model + #if (SHADERPASS == SHADERPASS_PATH_TRACING) && !defined(_DOUBLESIDED_ON) && (defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE)) + #undef _REFRACTION_PLANE + #undef _REFRACTION_SPHERE + #define _REFRACTION_THIN + #endif + // Caution: we can use the define SHADER_UNLIT onlit after the above Material include as it is the Unlit template who define it + + // To handle SSR on transparent correctly with a possibility to enable/disable it per framesettings + // we should have a code like this: + // if !defined(_DISABLE_SSR_TRANSPARENT) + // pragma multi_compile _ WRITE_NORMAL_BUFFER + // endif + // i.e we enable the multicompile only if we can receive SSR or not, and then C# code drive + // it based on if SSR transparent in frame settings and not (and stripper can strip it). + // this is currently not possible with our current preprocessor as _DISABLE_SSR_TRANSPARENT is a keyword not a define + // so instead we used this and chose to pay the extra cost of normal write even if SSR transaprent is disabled. + // Ideally the shader graph generator should handle it but condition below can't be handle correctly for now. + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + #if !defined(_DISABLE_SSR_TRANSPARENT) && !defined(SHADER_UNLIT) + #define WRITE_NORMAL_BUFFER + #endif + #endif + + #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) + // Don't do it with debug display mode as it is possible there is no depth prepass in this case + #if !defined(_SURFACE_TYPE_TRANSPARENT) + #if SHADERPASS == SHADERPASS_FORWARD + #define SHADERPASS_FORWARD_BYPASS_ALPHA_TEST + #elif SHADERPASS == SHADERPASS_GBUFFER + #define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST + #endif + #endif + #endif + + // Define _DEFERRED_CAPABLE_MATERIAL for shader capable to run in deferred pass + #if defined(SHADER_LIT) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define _DEFERRED_CAPABLE_MATERIAL + #endif + + // Translate transparent motion vector define + #if defined(_TRANSPARENT_WRITES_MOTION_VEC) && defined(_SURFACE_TYPE_TRANSPARENT) + #define _WRITE_TRANSPARENT_MOTION_VECTOR + #endif + + // -- Graph Properties + CBUFFER_START(UnityPerMaterial) + float4 _Color; + float4 _EmissionColor; + float _UseShadowThreshold; + float4 _DoubleSidedConstants; + float _BlendMode; + float _EnableBlendModePreserveSpecularLighting; + float _RayTracing; + float _RefractionModel; + CBUFFER_END + + + // Object and Global properties + + // -- Property used by ScenePickingPass + #ifdef SCENEPICKINGPASS + float4 _SelectionID; + #endif + + // -- Properties used by SceneSelectionPass + #ifdef SCENESELECTIONPASS + int _ObjectId; + int _PassValue; + #endif + + // Includes + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingMacros.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/ShaderVariablesRaytracing.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/ShaderVariablesRaytracingLightLoop.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingIntersection.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/Lighting.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoopDef.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/Lit.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitRaytracing.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/BuiltinUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/MaterialUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingLightLoop.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RayTracingCommon.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderGraphFunctions.hlsl" + // GraphIncludes: + + // -------------------------------------------------- + // Structs and Packing + + struct SurfaceDescriptionInputs + { + float3 TangentSpaceNormal; + }; + + //Interpolator Packs: + + // -------------------------------------------------- + // Graph + + + // Graph Functions + // GraphFunctions: + + // Graph Vertex + // GraphVertex: + + // Graph Pixel + struct SurfaceDescription + { + float3 BaseColor; + float3 Emission; + float Alpha; + float3 BentNormal; + float Smoothness; + float Occlusion; + float3 NormalTS; + float Metallic; + }; + + SurfaceDescription SurfaceDescriptionFunction(SurfaceDescriptionInputs IN) + { + SurfaceDescription surface = (SurfaceDescription)0; + float4 _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4 = _Color; + float _Split_cace9cff304a4c5d84b5305897d09aa9_R_1_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[0]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_G_2_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[1]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_B_3_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[2]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[3]; + surface.BaseColor = (_Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4.xyz); + surface.Emission = float3(0, 0, 0); + surface.Alpha = _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float; + surface.BentNormal = IN.TangentSpaceNormal; + surface.Smoothness = 0.5; + surface.Occlusion = 1; + surface.NormalTS = IN.TangentSpaceNormal; + surface.Metallic = 0; + return surface; + } + + // -------------------------------------------------- + // Build Graph Inputs + #ifdef HAVE_VFX_MODIFICATION + #define VFX_SRP_ATTRIBUTES AttributesMesh + #define VaryingsMeshType VaryingsMeshToPS + #define VFX_SRP_VARYINGS VaryingsMeshType + #define VFX_SRP_SURFACE_INPUTS FragInputs + #endif + SurfaceDescriptionInputs FragInputsToSurfaceDescriptionInputs(FragInputs input, float3 viewWS) + { + SurfaceDescriptionInputs output; + ZERO_INITIALIZE(SurfaceDescriptionInputs, output); + + #if defined(SHADER_STAGE_RAY_TRACING) + #else + #endif + output.TangentSpaceNormal = float3(0.0f, 0.0f, 1.0f); + + #if UNITY_UV_STARTS_AT_TOP + #else + #endif + + + + // splice point to copy frag inputs custom interpolator pack into the SDI + /* WARNING: $splice Could not find named fragment 'CustomInterpolatorCopyToSDI' */ + + return output; + } + + // -------------------------------------------------- + // Build Surface Data (Specific Material) + + void ApplyDecalToSurfaceDataNoNormal(DecalSurfaceData decalSurfaceData, inout SurfaceData surfaceData); + + void ApplyDecalAndGetNormal(FragInputs fragInputs, PositionInputs posInput, SurfaceDescription surfaceDescription, + inout SurfaceData surfaceData) + { + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + #ifdef DECAL_NORMAL_BLENDING + // SG nodes don't ouptut surface gradients, so if decals require surf grad blending, we have to convert + // the normal to gradient before applying the decal. We then have to resolve the gradient back to world space + float3 normalTS; + + normalTS = SurfaceGradientFromTangentSpaceNormalAndFromTBN(surfaceDescription.NormalTS, + fragInputs.tangentToWorld[0], fragInputs.tangentToWorld[1]); + + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, fragInputs.tangentToWorld[2], normalTS); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + + GetNormalWS_SG(fragInputs, normalTS, surfaceData.normalWS, doubleSidedConstants); + #else + // normal delivered to master node + GetNormalWS(fragInputs, surfaceDescription.NormalTS, surfaceData.normalWS, doubleSidedConstants); + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + // Both uses and modifies 'surfaceData.normalWS'. + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, surfaceData.normalWS.xyz); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + #endif + } + void BuildSurfaceData(FragInputs fragInputs, inout SurfaceDescription surfaceDescription, float3 V, PositionInputs posInput, out SurfaceData surfaceData, out float3 bentNormalWS) + { + ZERO_INITIALIZE(SurfaceData, surfaceData); + + // specularOcclusion need to be init ahead of decal to quiet the compiler that modify the SurfaceData struct + // however specularOcclusion can come from the graph, so need to be init here so it can be override. + surfaceData.specularOcclusion = 1.0; + + surfaceData.baseColor = surfaceDescription.BaseColor; + surfaceData.perceptualSmoothness = surfaceDescription.Smoothness; + surfaceData.ambientOcclusion = surfaceDescription.Occlusion; + surfaceData.metallic = surfaceDescription.Metallic; + + #if defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE) || defined(_REFRACTION_THIN) + if (_EnableSSRefraction) + { + + surfaceData.transmittanceMask = (1.0 - surfaceDescription.Alpha); + surfaceDescription.Alpha = 1.0; + } + else + { + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + surfaceDescription.Alpha = 1.0; + } + #else + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + #endif + + // These static material feature allow compile time optimization + surfaceData.materialFeatures = MATERIALFEATUREFLAGS_LIT_STANDARD; + #ifdef _MATERIAL_FEATURE_SUBSURFACE_SCATTERING + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING; + #endif + + #ifdef _MATERIAL_FEATURE_TRANSMISSION + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_TRANSMISSION; + #endif + + #ifdef _MATERIAL_FEATURE_ANISOTROPY + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_ANISOTROPY; + + // Initialize the normal to something non-zero to avoid a div-zero warning for anisotropy. + surfaceData.normalWS = float3(0, 1, 0); + #endif + + #ifdef _MATERIAL_FEATURE_IRIDESCENCE + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_IRIDESCENCE; + #endif + + #ifdef _MATERIAL_FEATURE_SPECULAR_COLOR + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR; + #endif + + #ifdef _MATERIAL_FEATURE_CLEAR_COAT + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_CLEAR_COAT; + #endif + + #if defined (_MATERIAL_FEATURE_SPECULAR_COLOR) && defined (_ENERGY_CONSERVING_SPECULAR) + // Require to have setup baseColor + // Reproduce the energy conservation done in legacy Unity. Not ideal but better for compatibility and users can unchek it + surfaceData.baseColor *= (1.0 - Max3(surfaceData.specularColor.r, surfaceData.specularColor.g, surfaceData.specularColor.b)); + #endif + + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + ApplyDecalAndGetNormal(fragInputs, posInput, surfaceDescription, surfaceData); + + surfaceData.geomNormalWS = fragInputs.tangentToWorld[2]; + + surfaceData.tangentWS = normalize(fragInputs.tangentToWorld[0].xyz); // The tangent is not normalize in tangentToWorld for mikkt. TODO: Check if it expected that we normalize with Morten. Tag: SURFACE_GRADIENT + + + bentNormalWS = surfaceData.normalWS; + + surfaceData.tangentWS = Orthonormalize(surfaceData.tangentWS, surfaceData.normalWS); + + #ifdef DEBUG_DISPLAY + if (_DebugMipMapMode != DEBUGMIPMAPMODE_NONE) + { + // TODO: need to update mip info + surfaceData.metallic = 0; + } + + // We need to call ApplyDebugToSurfaceData after filling the surfarcedata and before filling builtinData + // as it can modify attribute use for static lighting + ApplyDebugToSurfaceData(fragInputs.tangentToWorld, surfaceData); + #endif + + // By default we use the ambient occlusion with Tri-ace trick (apply outside) for specular occlusion. + // If user provide bent normal then we process a better term + #if defined(_SPECULAR_OCCLUSION_CUSTOM) + // Just use the value passed through via the slot (not active otherwise) + #elif defined(_SPECULAR_OCCLUSION_FROM_AO_BENT_NORMAL) + // If we have bent normal and ambient occlusion, process a specular occlusion + surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData.normalWS, surfaceData.ambientOcclusion, PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness)); + #elif defined(_AMBIENT_OCCLUSION) && defined(_SPECULAR_OCCLUSION_FROM_AO) + surfaceData.specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(ClampNdotV(dot(surfaceData.normalWS, V)), surfaceData.ambientOcclusion, PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness)); + #endif + + #if defined(_ENABLE_GEOMETRIC_SPECULAR_AA) && !defined(SHADER_STAGE_RAY_TRACING) + surfaceData.perceptualSmoothness = GeometricNormalFiltering(surfaceData.perceptualSmoothness, fragInputs.tangentToWorld[2], surfaceDescription.SpecularAAScreenSpaceVariance, surfaceDescription.SpecularAAThreshold); + #endif + } + + // -------------------------------------------------- + // Get Surface And BuiltinData + + void GetSurfaceAndBuiltinData(FragInputs fragInputs, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData RAY_TRACING_OPTIONAL_PARAMETERS) + { + // 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 + LODDitheringTransition(ComputeFadeMaskSeed(V, posInput.positionSS), unity_LODFade.x); + #endif + #endif + + #ifndef SHADER_UNLIT + #ifdef _DOUBLESIDED_ON + float3 doubleSidedConstants = _DoubleSidedConstants.xyz; + #else + float3 doubleSidedConstants = float3(1.0, 1.0, 1.0); + #endif + + ApplyDoubleSidedFlipOrMirror(fragInputs, doubleSidedConstants); // Apply double sided flip on the vertex normal + #endif // SHADER_UNLIT + + SurfaceDescriptionInputs surfaceDescriptionInputs = FragInputsToSurfaceDescriptionInputs(fragInputs, V); + + #if defined(HAVE_VFX_MODIFICATION) + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + GetElementPixelProperties(fragInputs, properties); + + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs, properties); + #else + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs); + #endif + + // Perform alpha test very early to save performance (a killed pixel will not sample textures) + // TODO: split graph evaluation to grab just alpha dependencies first? tricky.. + #ifdef _ALPHATEST_ON + float alphaCutoff = surfaceDescription.AlphaClipThreshold; + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + // The TransparentDepthPrepass is also used with SSR transparent. + // If an artists enable transaprent SSR but not the TransparentDepthPrepass itself, then we use AlphaClipThreshold + // otherwise if TransparentDepthPrepass is enabled we use AlphaClipThresholdDepthPrepass + #elif SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_POSTPASS + // DepthPostpass always use its own alpha threshold + alphaCutoff = surfaceDescription.AlphaClipThresholdDepthPostpass; + #elif (SHADERPASS == SHADERPASS_SHADOWS) || (SHADERPASS == SHADERPASS_RAYTRACING_VISIBILITY) + // If use shadow threshold isn't enable we don't allow any test + #endif + + GENERIC_ALPHA_TEST(surfaceDescription.Alpha, alphaCutoff); + #endif + + #if !defined(SHADER_STAGE_RAY_TRACING) && _DEPTHOFFSET_ON + ApplyDepthOffsetPositionInput(V, surfaceDescription.DepthOffset, GetViewForwardDir(), GetWorldToHClipMatrix(), posInput); + #endif + + #ifndef SHADER_UNLIT + float3 bentNormalWS; + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData, bentNormalWS); + + #ifdef FRAG_INPUTS_USE_TEXCOORD1 + float4 lightmapTexCoord1 = fragInputs.texCoord1; + #else + float4 lightmapTexCoord1 = float4(0,0,0,0); + #endif + + #ifdef FRAG_INPUTS_USE_TEXCOORD2 + float4 lightmapTexCoord2 = fragInputs.texCoord2; + #else + float4 lightmapTexCoord2 = float4(0,0,0,0); + #endif + + // Builtin Data + // For back lighting we use the oposite vertex normal + InitBuiltinData(posInput, surfaceDescription.Alpha, bentNormalWS, -fragInputs.tangentToWorld[2], lightmapTexCoord1, lightmapTexCoord2, builtinData); + + #else + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData); + + ZERO_BUILTIN_INITIALIZE(builtinData); // No call to InitBuiltinData as we don't have any lighting + builtinData.opacity = surfaceDescription.Alpha; + + #if defined(DEBUG_DISPLAY) + // Light Layers are currently not used for the Unlit shader (because it is not lit) + // But Unlit objects do cast shadows according to their rendering layer mask, which is what we want to + // display in the light layers visualization mode, therefore we need the renderingLayers + builtinData.renderingLayers = GetMeshRenderingLightLayer(); + #endif + + #endif // SHADER_UNLIT + + #ifdef _ALPHATEST_ON + // Used for sharpening by alpha to mask - Alpha to covertage is only used with depth only and forward pass (no shadow pass, no transparent pass) + builtinData.alphaClipTreshold = alphaCutoff; + #endif + + // override sampleBakedGI - not used by Unlit + + builtinData.emissiveColor = surfaceDescription.Emission; + + // Note this will not fully work on transparent surfaces (can check with _SURFACE_TYPE_TRANSPARENT define) + // We will always overwrite vt feeback with the nearest. So behind transparent surfaces vt will not be resolved + // This is a limitation of the current MRT approach. + #ifdef UNITY_VIRTUAL_TEXTURING + #endif + + #if _DEPTHOFFSET_ON + builtinData.depthOffset = surfaceDescription.DepthOffset; + #endif + + // TODO: We should generate distortion / distortionBlur for non distortion pass + #if (SHADERPASS == SHADERPASS_DISTORTION) + builtinData.distortion = surfaceDescription.Distortion; + builtinData.distortionBlur = surfaceDescription.DistortionBlur; + #endif + + #ifndef SHADER_UNLIT + // PostInitBuiltinData call ApplyDebugToBuiltinData + PostInitBuiltinData(V, posInput, surfaceData, builtinData); + #else + ApplyDebugToBuiltinData(builtinData); + #endif + + RAY_TRACING_OPTIONAL_ALPHA_TEST_PASS + } + + // -------------------------------------------------- + // Main + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassRaytracingForward.hlsl" + + // -------------------------------------------------- + // Visual Effect Vertex Invocations + + #ifdef HAVE_VFX_MODIFICATION + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/VisualEffectVertex.hlsl" + #endif + + ENDHLSL + } + Pass + { + Name "GBufferDXR" + Tags + { + "LightMode" = "GBufferDXR" + } + + // Render State + // RenderState: + + // Debug + // + + // -------------------------------------------------- + // Pass + + HLSLPROGRAM + + // Pragmas + #pragma target 5.0 + #pragma raytracing surface_shader + #pragma only_renderers d3d11 xboxseries ps5 + + // Keywords + #pragma multi_compile _ MINIMAL_GBUFFER + #pragma shader_feature _ _SURFACE_TYPE_TRANSPARENT + #pragma shader_feature_local _ _DOUBLESIDED_ON + #pragma shader_feature_local _ _ADD_PRECOMPUTED_VELOCITY + #pragma shader_feature_local _ _TRANSPARENT_WRITES_MOTION_VEC + #pragma shader_feature_local_fragment _ _ENABLE_FOG_ON_TRANSPARENT + #pragma multi_compile _ DEBUG_DISPLAY + #pragma shader_feature_local_fragment _ _DISABLE_DECALS + #pragma shader_feature_local_raytracing _ _DISABLE_DECALS + #pragma shader_feature_local_fragment _ _DISABLE_SSR + #pragma shader_feature_local_raytracing _ _DISABLE_SSR + #pragma shader_feature_local_fragment _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local_raytracing _ _DISABLE_SSR_TRANSPARENT + #pragma multi_compile _ LIGHTMAP_ON + #pragma multi_compile _ DIRLIGHTMAP_COMBINED + #pragma multi_compile_fragment PROBE_VOLUMES_OFF PROBE_VOLUMES_L1 PROBE_VOLUMES_L2 + #pragma multi_compile_raytracing PROBE_VOLUMES_OFF PROBE_VOLUMES_L1 PROBE_VOLUMES_L2 + #pragma multi_compile _ DYNAMICLIGHTMAP_ON + #pragma shader_feature_local _ _REFRACTION_PLANE _REFRACTION_SPHERE _REFRACTION_THIN + // GraphKeywords: + + // For custom interpolators to inject a substruct definition before FragInputs definition, + // allowing for FragInputs to capture CI's intended for ShaderGraph's SDI. + /* WARNING: $splice Could not find named fragment 'CustomInterpolatorPreInclude' */ + + + // TODO: Merge FragInputsVFX substruct with CustomInterpolators. + #ifdef HAVE_VFX_MODIFICATION + struct FragInputsVFX + { + /* WARNING: $splice Could not find named fragment 'FragInputsVFX' */ + }; + #endif + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl" // Required by Tessellation.hlsl + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Tessellation.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Texture.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl" // Required to be include before we include properties as it define DECLARE_STACK_CB + // Always include Shader Graph version + // Always include last to avoid double macros + #include "Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl" // Need to be here for Gradient struct definition + + // -------------------------------------------------- + // Defines + + // Attribute + #define ATTRIBUTES_NEED_NORMAL + #define ATTRIBUTES_NEED_TANGENT + #define ATTRIBUTES_NEED_TEXCOORD1 + #define ATTRIBUTES_NEED_TEXCOORD2 + #define VARYINGS_NEED_POSITION_WS + #define VARYINGS_NEED_TANGENT_TO_WORLD + #define VARYINGS_NEED_TEXCOORD1 + #define VARYINGS_NEED_TEXCOORD2 + + + //Strip down the FragInputs.hlsl (on graphics), so we can only optimize the interpolators we use. + //if by accident something requests contents of FragInputs.hlsl, it will be caught as a compiler error + //Frag inputs stripping is only enabled when FRAG_INPUTS_ENABLE_STRIPPING is set + #if !defined(SHADER_STAGE_RAY_TRACING) && SHADERPASS != SHADERPASS_RAYTRACING_GBUFFER && SHADERPASS != SHADERPASS_FULL_SCREEN_DEBUG + #define FRAG_INPUTS_ENABLE_STRIPPING + #endif + #define FRAG_INPUTS_USE_TEXCOORD1 + #define FRAG_INPUTS_USE_TEXCOORD2 + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl" + + + + #define SHADERPASS SHADERPASS_RAYTRACING_GBUFFER + #define SHADOW_LOW + #define RAYTRACING_SHADER_GRAPH_RAYTRACED + + + // Following two define are a workaround introduce in 10.1.x for RaytracingQualityNode + // The ShaderGraph don't support correctly migration of this node as it serialize all the node data + // in the json file making it impossible to uprgrade. Until we get a fix, we do a workaround here + // to still allow us to rename the field and keyword of this node without breaking existing code. + #ifdef RAYTRACING_SHADER_GRAPH_DEFAULT + #define RAYTRACING_SHADER_GRAPH_HIGH + #endif + + #ifdef RAYTRACING_SHADER_GRAPH_RAYTRACED + #define RAYTRACING_SHADER_GRAPH_LOW + #endif + // end + + #ifndef SHADER_UNLIT + // We need isFrontFace when using double sided - it is not required for unlit as in case of unlit double sided only drive the cullmode + // VARYINGS_NEED_CULLFACE can be define by VaryingsMeshToPS.FaceSign input if a IsFrontFace Node is included in the shader graph. + #if defined(_DOUBLESIDED_ON) && !defined(VARYINGS_NEED_CULLFACE) + #define VARYINGS_NEED_CULLFACE + #endif + #endif + + // Specific Material Define + #define _SPECULAR_OCCLUSION_FROM_AO 1 + #define _ENERGY_CONSERVING_SPECULAR 1 + + // If we use subsurface scattering, enable output split lighting (for forward pass) + #if defined(_MATERIAL_FEATURE_SUBSURFACE_SCATTERING) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define OUTPUT_SPLIT_LIGHTING + #endif + + // This shader support recursive rendering for raytracing + #define HAVE_RECURSIVE_RENDERING + + // In Path Tracing, For all single-sided, refractive materials, we want to force a thin refraction model + #if (SHADERPASS == SHADERPASS_PATH_TRACING) && !defined(_DOUBLESIDED_ON) && (defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE)) + #undef _REFRACTION_PLANE + #undef _REFRACTION_SPHERE + #define _REFRACTION_THIN + #endif + // Caution: we can use the define SHADER_UNLIT onlit after the above Material include as it is the Unlit template who define it + + // To handle SSR on transparent correctly with a possibility to enable/disable it per framesettings + // we should have a code like this: + // if !defined(_DISABLE_SSR_TRANSPARENT) + // pragma multi_compile _ WRITE_NORMAL_BUFFER + // endif + // i.e we enable the multicompile only if we can receive SSR or not, and then C# code drive + // it based on if SSR transparent in frame settings and not (and stripper can strip it). + // this is currently not possible with our current preprocessor as _DISABLE_SSR_TRANSPARENT is a keyword not a define + // so instead we used this and chose to pay the extra cost of normal write even if SSR transaprent is disabled. + // Ideally the shader graph generator should handle it but condition below can't be handle correctly for now. + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + #if !defined(_DISABLE_SSR_TRANSPARENT) && !defined(SHADER_UNLIT) + #define WRITE_NORMAL_BUFFER + #endif + #endif + + #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) + // Don't do it with debug display mode as it is possible there is no depth prepass in this case + #if !defined(_SURFACE_TYPE_TRANSPARENT) + #if SHADERPASS == SHADERPASS_FORWARD + #define SHADERPASS_FORWARD_BYPASS_ALPHA_TEST + #elif SHADERPASS == SHADERPASS_GBUFFER + #define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST + #endif + #endif + #endif + + // Define _DEFERRED_CAPABLE_MATERIAL for shader capable to run in deferred pass + #if defined(SHADER_LIT) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define _DEFERRED_CAPABLE_MATERIAL + #endif + + // Translate transparent motion vector define + #if defined(_TRANSPARENT_WRITES_MOTION_VEC) && defined(_SURFACE_TYPE_TRANSPARENT) + #define _WRITE_TRANSPARENT_MOTION_VECTOR + #endif + + // -- Graph Properties + CBUFFER_START(UnityPerMaterial) + float4 _Color; + float4 _EmissionColor; + float _UseShadowThreshold; + float4 _DoubleSidedConstants; + float _BlendMode; + float _EnableBlendModePreserveSpecularLighting; + float _RayTracing; + float _RefractionModel; + CBUFFER_END + + + // Object and Global properties + + // -- Property used by ScenePickingPass + #ifdef SCENEPICKINGPASS + float4 _SelectionID; + #endif + + // -- Properties used by SceneSelectionPass + #ifdef SCENESELECTIONPASS + int _ObjectId; + int _PassValue; + #endif + + // Includes + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingMacros.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/ShaderVariablesRaytracing.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/ShaderVariablesRaytracingLightLoop.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Deferred/RaytracingIntersectonGBuffer.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/Lit.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/StandardLit/StandardLit.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitRaytracing.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/BuiltinUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/MaterialUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RayTracingCommon.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderGraphFunctions.hlsl" + // GraphIncludes: + + // -------------------------------------------------- + // Structs and Packing + + struct SurfaceDescriptionInputs + { + float3 TangentSpaceNormal; + }; + + //Interpolator Packs: + + // -------------------------------------------------- + // Graph + + + // Graph Functions + // GraphFunctions: + + // Graph Vertex + // GraphVertex: + + // Graph Pixel + struct SurfaceDescription + { + float3 BaseColor; + float3 Emission; + float Alpha; + float3 BentNormal; + float Smoothness; + float Occlusion; + float3 NormalTS; + float Metallic; + }; + + SurfaceDescription SurfaceDescriptionFunction(SurfaceDescriptionInputs IN) + { + SurfaceDescription surface = (SurfaceDescription)0; + float4 _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4 = _Color; + float _Split_cace9cff304a4c5d84b5305897d09aa9_R_1_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[0]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_G_2_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[1]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_B_3_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[2]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[3]; + surface.BaseColor = (_Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4.xyz); + surface.Emission = float3(0, 0, 0); + surface.Alpha = _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float; + surface.BentNormal = IN.TangentSpaceNormal; + surface.Smoothness = 0.5; + surface.Occlusion = 1; + surface.NormalTS = IN.TangentSpaceNormal; + surface.Metallic = 0; + return surface; + } + + // -------------------------------------------------- + // Build Graph Inputs + #ifdef HAVE_VFX_MODIFICATION + #define VFX_SRP_ATTRIBUTES AttributesMesh + #define VaryingsMeshType VaryingsMeshToPS + #define VFX_SRP_VARYINGS VaryingsMeshType + #define VFX_SRP_SURFACE_INPUTS FragInputs + #endif + SurfaceDescriptionInputs FragInputsToSurfaceDescriptionInputs(FragInputs input, float3 viewWS) + { + SurfaceDescriptionInputs output; + ZERO_INITIALIZE(SurfaceDescriptionInputs, output); + + #if defined(SHADER_STAGE_RAY_TRACING) + #else + #endif + output.TangentSpaceNormal = float3(0.0f, 0.0f, 1.0f); + + #if UNITY_UV_STARTS_AT_TOP + #else + #endif + + + + // splice point to copy frag inputs custom interpolator pack into the SDI + /* WARNING: $splice Could not find named fragment 'CustomInterpolatorCopyToSDI' */ + + return output; + } + + // -------------------------------------------------- + // Build Surface Data (Specific Material) + + void ApplyDecalToSurfaceDataNoNormal(DecalSurfaceData decalSurfaceData, inout SurfaceData surfaceData); + + void ApplyDecalAndGetNormal(FragInputs fragInputs, PositionInputs posInput, SurfaceDescription surfaceDescription, + inout SurfaceData surfaceData) + { + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + #ifdef DECAL_NORMAL_BLENDING + // SG nodes don't ouptut surface gradients, so if decals require surf grad blending, we have to convert + // the normal to gradient before applying the decal. We then have to resolve the gradient back to world space + float3 normalTS; + + normalTS = SurfaceGradientFromTangentSpaceNormalAndFromTBN(surfaceDescription.NormalTS, + fragInputs.tangentToWorld[0], fragInputs.tangentToWorld[1]); + + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, fragInputs.tangentToWorld[2], normalTS); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + + GetNormalWS_SG(fragInputs, normalTS, surfaceData.normalWS, doubleSidedConstants); + #else + // normal delivered to master node + GetNormalWS(fragInputs, surfaceDescription.NormalTS, surfaceData.normalWS, doubleSidedConstants); + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + // Both uses and modifies 'surfaceData.normalWS'. + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, surfaceData.normalWS.xyz); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + #endif + } + void BuildSurfaceData(FragInputs fragInputs, inout SurfaceDescription surfaceDescription, float3 V, PositionInputs posInput, out SurfaceData surfaceData, out float3 bentNormalWS) + { + ZERO_INITIALIZE(SurfaceData, surfaceData); + + // specularOcclusion need to be init ahead of decal to quiet the compiler that modify the SurfaceData struct + // however specularOcclusion can come from the graph, so need to be init here so it can be override. + surfaceData.specularOcclusion = 1.0; + + surfaceData.baseColor = surfaceDescription.BaseColor; + surfaceData.perceptualSmoothness = surfaceDescription.Smoothness; + surfaceData.ambientOcclusion = surfaceDescription.Occlusion; + surfaceData.metallic = surfaceDescription.Metallic; + + #if defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE) || defined(_REFRACTION_THIN) + if (_EnableSSRefraction) + { + + surfaceData.transmittanceMask = (1.0 - surfaceDescription.Alpha); + surfaceDescription.Alpha = 1.0; + } + else + { + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + surfaceDescription.Alpha = 1.0; + } + #else + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + #endif + + // These static material feature allow compile time optimization + surfaceData.materialFeatures = MATERIALFEATUREFLAGS_LIT_STANDARD; + #ifdef _MATERIAL_FEATURE_SUBSURFACE_SCATTERING + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING; + #endif + + #ifdef _MATERIAL_FEATURE_TRANSMISSION + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_TRANSMISSION; + #endif + + #ifdef _MATERIAL_FEATURE_ANISOTROPY + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_ANISOTROPY; + + // Initialize the normal to something non-zero to avoid a div-zero warning for anisotropy. + surfaceData.normalWS = float3(0, 1, 0); + #endif + + #ifdef _MATERIAL_FEATURE_IRIDESCENCE + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_IRIDESCENCE; + #endif + + #ifdef _MATERIAL_FEATURE_SPECULAR_COLOR + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR; + #endif + + #ifdef _MATERIAL_FEATURE_CLEAR_COAT + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_CLEAR_COAT; + #endif + + #if defined (_MATERIAL_FEATURE_SPECULAR_COLOR) && defined (_ENERGY_CONSERVING_SPECULAR) + // Require to have setup baseColor + // Reproduce the energy conservation done in legacy Unity. Not ideal but better for compatibility and users can unchek it + surfaceData.baseColor *= (1.0 - Max3(surfaceData.specularColor.r, surfaceData.specularColor.g, surfaceData.specularColor.b)); + #endif + + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + ApplyDecalAndGetNormal(fragInputs, posInput, surfaceDescription, surfaceData); + + surfaceData.geomNormalWS = fragInputs.tangentToWorld[2]; + + surfaceData.tangentWS = normalize(fragInputs.tangentToWorld[0].xyz); // The tangent is not normalize in tangentToWorld for mikkt. TODO: Check if it expected that we normalize with Morten. Tag: SURFACE_GRADIENT + + + bentNormalWS = surfaceData.normalWS; + + surfaceData.tangentWS = Orthonormalize(surfaceData.tangentWS, surfaceData.normalWS); + + #ifdef DEBUG_DISPLAY + if (_DebugMipMapMode != DEBUGMIPMAPMODE_NONE) + { + // TODO: need to update mip info + surfaceData.metallic = 0; + } + + // We need to call ApplyDebugToSurfaceData after filling the surfarcedata and before filling builtinData + // as it can modify attribute use for static lighting + ApplyDebugToSurfaceData(fragInputs.tangentToWorld, surfaceData); + #endif + + // By default we use the ambient occlusion with Tri-ace trick (apply outside) for specular occlusion. + // If user provide bent normal then we process a better term + #if defined(_SPECULAR_OCCLUSION_CUSTOM) + // Just use the value passed through via the slot (not active otherwise) + #elif defined(_SPECULAR_OCCLUSION_FROM_AO_BENT_NORMAL) + // If we have bent normal and ambient occlusion, process a specular occlusion + surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData.normalWS, surfaceData.ambientOcclusion, PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness)); + #elif defined(_AMBIENT_OCCLUSION) && defined(_SPECULAR_OCCLUSION_FROM_AO) + surfaceData.specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(ClampNdotV(dot(surfaceData.normalWS, V)), surfaceData.ambientOcclusion, PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness)); + #endif + + #if defined(_ENABLE_GEOMETRIC_SPECULAR_AA) && !defined(SHADER_STAGE_RAY_TRACING) + surfaceData.perceptualSmoothness = GeometricNormalFiltering(surfaceData.perceptualSmoothness, fragInputs.tangentToWorld[2], surfaceDescription.SpecularAAScreenSpaceVariance, surfaceDescription.SpecularAAThreshold); + #endif + } + + // -------------------------------------------------- + // Get Surface And BuiltinData + + void GetSurfaceAndBuiltinData(FragInputs fragInputs, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData RAY_TRACING_OPTIONAL_PARAMETERS) + { + // 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 + LODDitheringTransition(ComputeFadeMaskSeed(V, posInput.positionSS), unity_LODFade.x); + #endif + #endif + + #ifndef SHADER_UNLIT + #ifdef _DOUBLESIDED_ON + float3 doubleSidedConstants = _DoubleSidedConstants.xyz; + #else + float3 doubleSidedConstants = float3(1.0, 1.0, 1.0); + #endif + + ApplyDoubleSidedFlipOrMirror(fragInputs, doubleSidedConstants); // Apply double sided flip on the vertex normal + #endif // SHADER_UNLIT + + SurfaceDescriptionInputs surfaceDescriptionInputs = FragInputsToSurfaceDescriptionInputs(fragInputs, V); + + #if defined(HAVE_VFX_MODIFICATION) + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + GetElementPixelProperties(fragInputs, properties); + + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs, properties); + #else + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs); + #endif + + // Perform alpha test very early to save performance (a killed pixel will not sample textures) + // TODO: split graph evaluation to grab just alpha dependencies first? tricky.. + #ifdef _ALPHATEST_ON + float alphaCutoff = surfaceDescription.AlphaClipThreshold; + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + // The TransparentDepthPrepass is also used with SSR transparent. + // If an artists enable transaprent SSR but not the TransparentDepthPrepass itself, then we use AlphaClipThreshold + // otherwise if TransparentDepthPrepass is enabled we use AlphaClipThresholdDepthPrepass + #elif SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_POSTPASS + // DepthPostpass always use its own alpha threshold + alphaCutoff = surfaceDescription.AlphaClipThresholdDepthPostpass; + #elif (SHADERPASS == SHADERPASS_SHADOWS) || (SHADERPASS == SHADERPASS_RAYTRACING_VISIBILITY) + // If use shadow threshold isn't enable we don't allow any test + #endif + + GENERIC_ALPHA_TEST(surfaceDescription.Alpha, alphaCutoff); + #endif + + #if !defined(SHADER_STAGE_RAY_TRACING) && _DEPTHOFFSET_ON + ApplyDepthOffsetPositionInput(V, surfaceDescription.DepthOffset, GetViewForwardDir(), GetWorldToHClipMatrix(), posInput); + #endif + + #ifndef SHADER_UNLIT + float3 bentNormalWS; + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData, bentNormalWS); + + #ifdef FRAG_INPUTS_USE_TEXCOORD1 + float4 lightmapTexCoord1 = fragInputs.texCoord1; + #else + float4 lightmapTexCoord1 = float4(0,0,0,0); + #endif + + #ifdef FRAG_INPUTS_USE_TEXCOORD2 + float4 lightmapTexCoord2 = fragInputs.texCoord2; + #else + float4 lightmapTexCoord2 = float4(0,0,0,0); + #endif + + // Builtin Data + // For back lighting we use the oposite vertex normal + InitBuiltinData(posInput, surfaceDescription.Alpha, bentNormalWS, -fragInputs.tangentToWorld[2], lightmapTexCoord1, lightmapTexCoord2, builtinData); + + #else + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData); + + ZERO_BUILTIN_INITIALIZE(builtinData); // No call to InitBuiltinData as we don't have any lighting + builtinData.opacity = surfaceDescription.Alpha; + + #if defined(DEBUG_DISPLAY) + // Light Layers are currently not used for the Unlit shader (because it is not lit) + // But Unlit objects do cast shadows according to their rendering layer mask, which is what we want to + // display in the light layers visualization mode, therefore we need the renderingLayers + builtinData.renderingLayers = GetMeshRenderingLightLayer(); + #endif + + #endif // SHADER_UNLIT + + #ifdef _ALPHATEST_ON + // Used for sharpening by alpha to mask - Alpha to covertage is only used with depth only and forward pass (no shadow pass, no transparent pass) + builtinData.alphaClipTreshold = alphaCutoff; + #endif + + // override sampleBakedGI - not used by Unlit + + builtinData.emissiveColor = surfaceDescription.Emission; + + // Note this will not fully work on transparent surfaces (can check with _SURFACE_TYPE_TRANSPARENT define) + // We will always overwrite vt feeback with the nearest. So behind transparent surfaces vt will not be resolved + // This is a limitation of the current MRT approach. + #ifdef UNITY_VIRTUAL_TEXTURING + #endif + + #if _DEPTHOFFSET_ON + builtinData.depthOffset = surfaceDescription.DepthOffset; + #endif + + // TODO: We should generate distortion / distortionBlur for non distortion pass + #if (SHADERPASS == SHADERPASS_DISTORTION) + builtinData.distortion = surfaceDescription.Distortion; + builtinData.distortionBlur = surfaceDescription.DistortionBlur; + #endif + + #ifndef SHADER_UNLIT + // PostInitBuiltinData call ApplyDebugToBuiltinData + PostInitBuiltinData(V, posInput, surfaceData, builtinData); + #else + ApplyDebugToBuiltinData(builtinData); + #endif + + RAY_TRACING_OPTIONAL_ALPHA_TEST_PASS + } + + // -------------------------------------------------- + // Main + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassRaytracingGBuffer.hlsl" + + // -------------------------------------------------- + // Visual Effect Vertex Invocations + + #ifdef HAVE_VFX_MODIFICATION + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/VisualEffectVertex.hlsl" + #endif + + ENDHLSL + } + Pass + { + Name "DebugDXR" + Tags + { + "LightMode" = "DebugDXR" + } + + // Debug + // + + // -------------------------------------------------- + // Pass + + HLSLPROGRAM + + // Pragmas + #pragma target 5.0 + #pragma raytracing surface_shader + #pragma only_renderers d3d11 xboxseries ps5 + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" + + // Includes + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingMacros.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/ShaderVariablesRaytracing.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingIntersection.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RayTracingCommon.hlsl" + // GraphIncludes: + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassRayTracingDebug.hlsl" + + ENDHLSL + } + Pass + { + Name "PathTracingDXR" + Tags + { + "LightMode" = "PathTracingDXR" + } + + // Render State + // RenderState: + + // Debug + // + + // -------------------------------------------------- + // Pass + + HLSLPROGRAM + + // Pragmas + #pragma target 5.0 + #pragma raytracing surface_shader + #pragma only_renderers d3d11 xboxseries ps5 + + // Keywords + #pragma shader_feature _ _SURFACE_TYPE_TRANSPARENT + #pragma shader_feature_local _ _DOUBLESIDED_ON + #pragma shader_feature_local _ _ADD_PRECOMPUTED_VELOCITY + #pragma shader_feature_local _ _TRANSPARENT_WRITES_MOTION_VEC + #pragma shader_feature_local_fragment _ _ENABLE_FOG_ON_TRANSPARENT + #pragma shader_feature_local_fragment _ _DISABLE_DECALS + #pragma shader_feature_local_raytracing _ _DISABLE_DECALS + #pragma shader_feature_local_fragment _ _DISABLE_SSR + #pragma shader_feature_local_raytracing _ _DISABLE_SSR + #pragma shader_feature_local_fragment _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local_raytracing _ _DISABLE_SSR_TRANSPARENT + #pragma shader_feature_local _ _REFRACTION_PLANE _REFRACTION_SPHERE _REFRACTION_THIN + // GraphKeywords: + + // For custom interpolators to inject a substruct definition before FragInputs definition, + // allowing for FragInputs to capture CI's intended for ShaderGraph's SDI. + /* WARNING: $splice Could not find named fragment 'CustomInterpolatorPreInclude' */ + + + // TODO: Merge FragInputsVFX substruct with CustomInterpolators. + #ifdef HAVE_VFX_MODIFICATION + struct FragInputsVFX + { + /* WARNING: $splice Could not find named fragment 'FragInputsVFX' */ + }; + #endif + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl" // Required by Tessellation.hlsl + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Tessellation.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Texture.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl" // Required to be include before we include properties as it define DECLARE_STACK_CB + // Always include Shader Graph version + // Always include last to avoid double macros + #include "Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl" // Need to be here for Gradient struct definition + + // -------------------------------------------------- + // Defines + + // Attribute + #define ATTRIBUTES_NEED_NORMAL + #define ATTRIBUTES_NEED_TANGENT + #define ATTRIBUTES_NEED_TEXCOORD1 + #define ATTRIBUTES_NEED_TEXCOORD2 + #define VARYINGS_NEED_POSITION_WS + #define VARYINGS_NEED_TANGENT_TO_WORLD + #define VARYINGS_NEED_TEXCOORD1 + #define VARYINGS_NEED_TEXCOORD2 + + + //Strip down the FragInputs.hlsl (on graphics), so we can only optimize the interpolators we use. + //if by accident something requests contents of FragInputs.hlsl, it will be caught as a compiler error + //Frag inputs stripping is only enabled when FRAG_INPUTS_ENABLE_STRIPPING is set + #if !defined(SHADER_STAGE_RAY_TRACING) && SHADERPASS != SHADERPASS_RAYTRACING_GBUFFER && SHADERPASS != SHADERPASS_FULL_SCREEN_DEBUG + #define FRAG_INPUTS_ENABLE_STRIPPING + #endif + #define FRAG_INPUTS_USE_TEXCOORD1 + #define FRAG_INPUTS_USE_TEXCOORD2 + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl" + + + + #define SHADERPASS SHADERPASS_PATH_TRACING + #define SHADOW_LOW + #define RAYTRACING_SHADER_GRAPH_DEFAULT + #define HAS_LIGHTLOOP 1 + + + // Following two define are a workaround introduce in 10.1.x for RaytracingQualityNode + // The ShaderGraph don't support correctly migration of this node as it serialize all the node data + // in the json file making it impossible to uprgrade. Until we get a fix, we do a workaround here + // to still allow us to rename the field and keyword of this node without breaking existing code. + #ifdef RAYTRACING_SHADER_GRAPH_DEFAULT + #define RAYTRACING_SHADER_GRAPH_HIGH + #endif + + #ifdef RAYTRACING_SHADER_GRAPH_RAYTRACED + #define RAYTRACING_SHADER_GRAPH_LOW + #endif + // end + + #ifndef SHADER_UNLIT + // We need isFrontFace when using double sided - it is not required for unlit as in case of unlit double sided only drive the cullmode + // VARYINGS_NEED_CULLFACE can be define by VaryingsMeshToPS.FaceSign input if a IsFrontFace Node is included in the shader graph. + #if defined(_DOUBLESIDED_ON) && !defined(VARYINGS_NEED_CULLFACE) + #define VARYINGS_NEED_CULLFACE + #endif + #endif + + // Specific Material Define + #define _SPECULAR_OCCLUSION_FROM_AO 1 + #define _ENERGY_CONSERVING_SPECULAR 1 + + // If we use subsurface scattering, enable output split lighting (for forward pass) + #if defined(_MATERIAL_FEATURE_SUBSURFACE_SCATTERING) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define OUTPUT_SPLIT_LIGHTING + #endif + + // This shader support recursive rendering for raytracing + #define HAVE_RECURSIVE_RENDERING + + // In Path Tracing, For all single-sided, refractive materials, we want to force a thin refraction model + #if (SHADERPASS == SHADERPASS_PATH_TRACING) && !defined(_DOUBLESIDED_ON) && (defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE)) + #undef _REFRACTION_PLANE + #undef _REFRACTION_SPHERE + #define _REFRACTION_THIN + #endif + // Caution: we can use the define SHADER_UNLIT onlit after the above Material include as it is the Unlit template who define it + + // To handle SSR on transparent correctly with a possibility to enable/disable it per framesettings + // we should have a code like this: + // if !defined(_DISABLE_SSR_TRANSPARENT) + // pragma multi_compile _ WRITE_NORMAL_BUFFER + // endif + // i.e we enable the multicompile only if we can receive SSR or not, and then C# code drive + // it based on if SSR transparent in frame settings and not (and stripper can strip it). + // this is currently not possible with our current preprocessor as _DISABLE_SSR_TRANSPARENT is a keyword not a define + // so instead we used this and chose to pay the extra cost of normal write even if SSR transaprent is disabled. + // Ideally the shader graph generator should handle it but condition below can't be handle correctly for now. + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + #if !defined(_DISABLE_SSR_TRANSPARENT) && !defined(SHADER_UNLIT) + #define WRITE_NORMAL_BUFFER + #endif + #endif + + #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) + // Don't do it with debug display mode as it is possible there is no depth prepass in this case + #if !defined(_SURFACE_TYPE_TRANSPARENT) + #if SHADERPASS == SHADERPASS_FORWARD + #define SHADERPASS_FORWARD_BYPASS_ALPHA_TEST + #elif SHADERPASS == SHADERPASS_GBUFFER + #define SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST + #endif + #endif + #endif + + // Define _DEFERRED_CAPABLE_MATERIAL for shader capable to run in deferred pass + #if defined(SHADER_LIT) && !defined(_SURFACE_TYPE_TRANSPARENT) + #define _DEFERRED_CAPABLE_MATERIAL + #endif + + // Translate transparent motion vector define + #if defined(_TRANSPARENT_WRITES_MOTION_VEC) && defined(_SURFACE_TYPE_TRANSPARENT) + #define _WRITE_TRANSPARENT_MOTION_VECTOR + #endif + + // -- Graph Properties + CBUFFER_START(UnityPerMaterial) + float4 _Color; + float4 _EmissionColor; + float _UseShadowThreshold; + float4 _DoubleSidedConstants; + float _BlendMode; + float _EnableBlendModePreserveSpecularLighting; + float _RayTracing; + float _RefractionModel; + CBUFFER_END + + + // Object and Global properties + + // -- Property used by ScenePickingPass + #ifdef SCENEPICKINGPASS + float4 _SelectionID; + #endif + + // -- Properties used by SceneSelectionPass + #ifdef SCENESELECTIONPASS + int _ObjectId; + int _PassValue; + #endif + + // Includes + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingMacros.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/ShaderVariablesRaytracing.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/ShaderVariablesRaytracingLightLoop.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingIntersection.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/Lighting.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoopDef.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/Lit.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitPathTracing.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/BuiltinUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/MaterialUtilities.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RayTracingCommon.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderGraphFunctions.hlsl" + // GraphIncludes: + + // -------------------------------------------------- + // Structs and Packing + + struct SurfaceDescriptionInputs + { + float3 TangentSpaceNormal; + }; + + //Interpolator Packs: + + // -------------------------------------------------- + // Graph + + + // Graph Functions + // GraphFunctions: + + // Graph Vertex + // GraphVertex: + + // Graph Pixel + struct SurfaceDescription + { + float3 BaseColor; + float3 Emission; + float Alpha; + float3 BentNormal; + float Smoothness; + float Occlusion; + float3 NormalTS; + float Metallic; + }; + + SurfaceDescription SurfaceDescriptionFunction(SurfaceDescriptionInputs IN) + { + SurfaceDescription surface = (SurfaceDescription)0; + float4 _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4 = _Color; + float _Split_cace9cff304a4c5d84b5305897d09aa9_R_1_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[0]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_G_2_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[1]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_B_3_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[2]; + float _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float = _Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4[3]; + surface.BaseColor = (_Property_1336b8bd5bb24e9bba34bb3d2c1b4313_Out_0_Vector4.xyz); + surface.Emission = float3(0, 0, 0); + surface.Alpha = _Split_cace9cff304a4c5d84b5305897d09aa9_A_4_Float; + surface.BentNormal = IN.TangentSpaceNormal; + surface.Smoothness = 0.5; + surface.Occlusion = 1; + surface.NormalTS = IN.TangentSpaceNormal; + surface.Metallic = 0; + return surface; + } + + // -------------------------------------------------- + // Build Graph Inputs + #ifdef HAVE_VFX_MODIFICATION + #define VFX_SRP_ATTRIBUTES AttributesMesh + #define VaryingsMeshType VaryingsMeshToPS + #define VFX_SRP_VARYINGS VaryingsMeshType + #define VFX_SRP_SURFACE_INPUTS FragInputs + #endif + SurfaceDescriptionInputs FragInputsToSurfaceDescriptionInputs(FragInputs input, float3 viewWS) + { + SurfaceDescriptionInputs output; + ZERO_INITIALIZE(SurfaceDescriptionInputs, output); + + #if defined(SHADER_STAGE_RAY_TRACING) + #else + #endif + output.TangentSpaceNormal = float3(0.0f, 0.0f, 1.0f); + + #if UNITY_UV_STARTS_AT_TOP + #else + #endif + + + + // splice point to copy frag inputs custom interpolator pack into the SDI + /* WARNING: $splice Could not find named fragment 'CustomInterpolatorCopyToSDI' */ + + return output; + } + + // -------------------------------------------------- + // Build Surface Data (Specific Material) + + void ApplyDecalToSurfaceDataNoNormal(DecalSurfaceData decalSurfaceData, inout SurfaceData surfaceData); + + void ApplyDecalAndGetNormal(FragInputs fragInputs, PositionInputs posInput, SurfaceDescription surfaceDescription, + inout SurfaceData surfaceData) + { + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + #ifdef DECAL_NORMAL_BLENDING + // SG nodes don't ouptut surface gradients, so if decals require surf grad blending, we have to convert + // the normal to gradient before applying the decal. We then have to resolve the gradient back to world space + float3 normalTS; + + normalTS = SurfaceGradientFromTangentSpaceNormalAndFromTBN(surfaceDescription.NormalTS, + fragInputs.tangentToWorld[0], fragInputs.tangentToWorld[1]); + + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, fragInputs.tangentToWorld[2], normalTS); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + + GetNormalWS_SG(fragInputs, normalTS, surfaceData.normalWS, doubleSidedConstants); + #else + // normal delivered to master node + GetNormalWS(fragInputs, surfaceDescription.NormalTS, surfaceData.normalWS, doubleSidedConstants); + + #if HAVE_DECALS + if (_EnableDecals) + { + float alpha = 1.0; + alpha = surfaceDescription.Alpha; + + // Both uses and modifies 'surfaceData.normalWS'. + DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, fragInputs, alpha); + ApplyDecalToSurfaceNormal(decalSurfaceData, surfaceData.normalWS.xyz); + ApplyDecalToSurfaceDataNoNormal(decalSurfaceData, surfaceData); + } + #endif + #endif + } + void BuildSurfaceData(FragInputs fragInputs, inout SurfaceDescription surfaceDescription, float3 V, PositionInputs posInput, out SurfaceData surfaceData, out float3 bentNormalWS) + { + ZERO_INITIALIZE(SurfaceData, surfaceData); + + // specularOcclusion need to be init ahead of decal to quiet the compiler that modify the SurfaceData struct + // however specularOcclusion can come from the graph, so need to be init here so it can be override. + surfaceData.specularOcclusion = 1.0; + + surfaceData.baseColor = surfaceDescription.BaseColor; + surfaceData.perceptualSmoothness = surfaceDescription.Smoothness; + surfaceData.ambientOcclusion = surfaceDescription.Occlusion; + surfaceData.metallic = surfaceDescription.Metallic; + + #if defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE) || defined(_REFRACTION_THIN) + if (_EnableSSRefraction) + { + + surfaceData.transmittanceMask = (1.0 - surfaceDescription.Alpha); + surfaceDescription.Alpha = 1.0; + } + else + { + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + surfaceDescription.Alpha = 1.0; + } + #else + surfaceData.ior = 1.0; + surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0); + surfaceData.atDistance = 1.0; + surfaceData.transmittanceMask = 0.0; + #endif + + // These static material feature allow compile time optimization + surfaceData.materialFeatures = MATERIALFEATUREFLAGS_LIT_STANDARD; + #ifdef _MATERIAL_FEATURE_SUBSURFACE_SCATTERING + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SUBSURFACE_SCATTERING; + #endif + + #ifdef _MATERIAL_FEATURE_TRANSMISSION + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_TRANSMISSION; + #endif + + #ifdef _MATERIAL_FEATURE_ANISOTROPY + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_ANISOTROPY; + + // Initialize the normal to something non-zero to avoid a div-zero warning for anisotropy. + surfaceData.normalWS = float3(0, 1, 0); + #endif + + #ifdef _MATERIAL_FEATURE_IRIDESCENCE + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_IRIDESCENCE; + #endif + + #ifdef _MATERIAL_FEATURE_SPECULAR_COLOR + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR; + #endif + + #ifdef _MATERIAL_FEATURE_CLEAR_COAT + surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_LIT_CLEAR_COAT; + #endif + + #if defined (_MATERIAL_FEATURE_SPECULAR_COLOR) && defined (_ENERGY_CONSERVING_SPECULAR) + // Require to have setup baseColor + // Reproduce the energy conservation done in legacy Unity. Not ideal but better for compatibility and users can unchek it + surfaceData.baseColor *= (1.0 - Max3(surfaceData.specularColor.r, surfaceData.specularColor.g, surfaceData.specularColor.b)); + #endif + + float3 doubleSidedConstants = GetDoubleSidedConstants(); + + ApplyDecalAndGetNormal(fragInputs, posInput, surfaceDescription, surfaceData); + + surfaceData.geomNormalWS = fragInputs.tangentToWorld[2]; + + surfaceData.tangentWS = normalize(fragInputs.tangentToWorld[0].xyz); // The tangent is not normalize in tangentToWorld for mikkt. TODO: Check if it expected that we normalize with Morten. Tag: SURFACE_GRADIENT + + + bentNormalWS = surfaceData.normalWS; + + surfaceData.tangentWS = Orthonormalize(surfaceData.tangentWS, surfaceData.normalWS); + + #ifdef DEBUG_DISPLAY + if (_DebugMipMapMode != DEBUGMIPMAPMODE_NONE) + { + // TODO: need to update mip info + surfaceData.metallic = 0; + } + + // We need to call ApplyDebugToSurfaceData after filling the surfarcedata and before filling builtinData + // as it can modify attribute use for static lighting + ApplyDebugToSurfaceData(fragInputs.tangentToWorld, surfaceData); + #endif + + // By default we use the ambient occlusion with Tri-ace trick (apply outside) for specular occlusion. + // If user provide bent normal then we process a better term + #if defined(_SPECULAR_OCCLUSION_CUSTOM) + // Just use the value passed through via the slot (not active otherwise) + #elif defined(_SPECULAR_OCCLUSION_FROM_AO_BENT_NORMAL) + // If we have bent normal and ambient occlusion, process a specular occlusion + surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData.normalWS, surfaceData.ambientOcclusion, PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness)); + #elif defined(_AMBIENT_OCCLUSION) && defined(_SPECULAR_OCCLUSION_FROM_AO) + surfaceData.specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(ClampNdotV(dot(surfaceData.normalWS, V)), surfaceData.ambientOcclusion, PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness)); + #endif + + #if defined(_ENABLE_GEOMETRIC_SPECULAR_AA) && !defined(SHADER_STAGE_RAY_TRACING) + surfaceData.perceptualSmoothness = GeometricNormalFiltering(surfaceData.perceptualSmoothness, fragInputs.tangentToWorld[2], surfaceDescription.SpecularAAScreenSpaceVariance, surfaceDescription.SpecularAAThreshold); + #endif + } + + // -------------------------------------------------- + // Get Surface And BuiltinData + + void GetSurfaceAndBuiltinData(FragInputs fragInputs, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData RAY_TRACING_OPTIONAL_PARAMETERS) + { + // 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 + LODDitheringTransition(ComputeFadeMaskSeed(V, posInput.positionSS), unity_LODFade.x); + #endif + #endif + + #ifndef SHADER_UNLIT + #ifdef _DOUBLESIDED_ON + float3 doubleSidedConstants = _DoubleSidedConstants.xyz; + #else + float3 doubleSidedConstants = float3(1.0, 1.0, 1.0); + #endif + + ApplyDoubleSidedFlipOrMirror(fragInputs, doubleSidedConstants); // Apply double sided flip on the vertex normal + #endif // SHADER_UNLIT + + SurfaceDescriptionInputs surfaceDescriptionInputs = FragInputsToSurfaceDescriptionInputs(fragInputs, V); + + #if defined(HAVE_VFX_MODIFICATION) + GraphProperties properties; + ZERO_INITIALIZE(GraphProperties, properties); + + GetElementPixelProperties(fragInputs, properties); + + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs, properties); + #else + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs); + #endif + + // Perform alpha test very early to save performance (a killed pixel will not sample textures) + // TODO: split graph evaluation to grab just alpha dependencies first? tricky.. + #ifdef _ALPHATEST_ON + float alphaCutoff = surfaceDescription.AlphaClipThreshold; + #if SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_PREPASS + // The TransparentDepthPrepass is also used with SSR transparent. + // If an artists enable transaprent SSR but not the TransparentDepthPrepass itself, then we use AlphaClipThreshold + // otherwise if TransparentDepthPrepass is enabled we use AlphaClipThresholdDepthPrepass + #elif SHADERPASS == SHADERPASS_TRANSPARENT_DEPTH_POSTPASS + // DepthPostpass always use its own alpha threshold + alphaCutoff = surfaceDescription.AlphaClipThresholdDepthPostpass; + #elif (SHADERPASS == SHADERPASS_SHADOWS) || (SHADERPASS == SHADERPASS_RAYTRACING_VISIBILITY) + // If use shadow threshold isn't enable we don't allow any test + #endif + + GENERIC_ALPHA_TEST(surfaceDescription.Alpha, alphaCutoff); + #endif + + #if !defined(SHADER_STAGE_RAY_TRACING) && _DEPTHOFFSET_ON + ApplyDepthOffsetPositionInput(V, surfaceDescription.DepthOffset, GetViewForwardDir(), GetWorldToHClipMatrix(), posInput); + #endif + + #ifndef SHADER_UNLIT + float3 bentNormalWS; + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData, bentNormalWS); + + #ifdef FRAG_INPUTS_USE_TEXCOORD1 + float4 lightmapTexCoord1 = fragInputs.texCoord1; + #else + float4 lightmapTexCoord1 = float4(0,0,0,0); + #endif + + #ifdef FRAG_INPUTS_USE_TEXCOORD2 + float4 lightmapTexCoord2 = fragInputs.texCoord2; + #else + float4 lightmapTexCoord2 = float4(0,0,0,0); + #endif + + // Builtin Data + // For back lighting we use the oposite vertex normal + InitBuiltinData(posInput, surfaceDescription.Alpha, bentNormalWS, -fragInputs.tangentToWorld[2], lightmapTexCoord1, lightmapTexCoord2, builtinData); + + #else + BuildSurfaceData(fragInputs, surfaceDescription, V, posInput, surfaceData); + + ZERO_BUILTIN_INITIALIZE(builtinData); // No call to InitBuiltinData as we don't have any lighting + builtinData.opacity = surfaceDescription.Alpha; + + #if defined(DEBUG_DISPLAY) + // Light Layers are currently not used for the Unlit shader (because it is not lit) + // But Unlit objects do cast shadows according to their rendering layer mask, which is what we want to + // display in the light layers visualization mode, therefore we need the renderingLayers + builtinData.renderingLayers = GetMeshRenderingLightLayer(); + #endif + + #endif // SHADER_UNLIT + + #ifdef _ALPHATEST_ON + // Used for sharpening by alpha to mask - Alpha to covertage is only used with depth only and forward pass (no shadow pass, no transparent pass) + builtinData.alphaClipTreshold = alphaCutoff; + #endif + + // override sampleBakedGI - not used by Unlit + + builtinData.emissiveColor = surfaceDescription.Emission; + + // Note this will not fully work on transparent surfaces (can check with _SURFACE_TYPE_TRANSPARENT define) + // We will always overwrite vt feeback with the nearest. So behind transparent surfaces vt will not be resolved + // This is a limitation of the current MRT approach. + #ifdef UNITY_VIRTUAL_TEXTURING + #endif + + #if _DEPTHOFFSET_ON + builtinData.depthOffset = surfaceDescription.DepthOffset; + #endif + + // TODO: We should generate distortion / distortionBlur for non distortion pass + #if (SHADERPASS == SHADERPASS_DISTORTION) + builtinData.distortion = surfaceDescription.Distortion; + builtinData.distortionBlur = surfaceDescription.DistortionBlur; + #endif + + #ifndef SHADER_UNLIT + // PostInitBuiltinData call ApplyDebugToBuiltinData + PostInitBuiltinData(V, posInput, surfaceData, builtinData); + #else + ApplyDebugToBuiltinData(builtinData); + #endif + + RAY_TRACING_OPTIONAL_ALPHA_TEST_PASS + } + + // -------------------------------------------------- + // Main + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassPathTracing.hlsl" + + // -------------------------------------------------- + // Visual Effect Vertex Invocations + + #ifdef HAVE_VFX_MODIFICATION + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/VisualEffectVertex.hlsl" + #endif + + ENDHLSL + } + } + CustomEditor "UnityEditor.ShaderGraph.GenericShaderGraphMaterialGUI" + CustomEditorForRenderPipeline "Rendering.HighDefinition.LitShaderGraphGUI" "UnityEngine.Rendering.HighDefinition.HDRenderPipelineAsset" + FallBack "OrderIndependentTransparency/Unlit" +} diff --git a/Shaders/Resources/OitRenderURP.shader.meta b/HDRP/Shaders/OitLitHDRP.shader.meta similarity index 80% rename from Shaders/Resources/OitRenderURP.shader.meta rename to HDRP/Shaders/OitLitHDRP.shader.meta index 0c43bb2..74cfc13 100644 --- a/Shaders/Resources/OitRenderURP.shader.meta +++ b/HDRP/Shaders/OitLitHDRP.shader.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 6d23e2ef444cae444b9ddd1167cd8553 +guid: 93e3ad154fba08c47a8c182c5d3ac7e5 ShaderImporter: externalObjects: {} defaultTextures: [] diff --git a/HDRP/Shaders/OitShaderPassForwardHDRP.hlsl b/HDRP/Shaders/OitShaderPassForwardHDRP.hlsl new file mode 100644 index 0000000..06a7348 --- /dev/null +++ b/HDRP/Shaders/OitShaderPassForwardHDRP.hlsl @@ -0,0 +1,267 @@ +#if SHADERPASS != SHADERPASS_FORWARD +#error SHADERPASS_is_not_correctly_define +#endif + +#include "Packages/org.happy-turtle.order-independent-transparency/Shaders/LinkedListCreation.hlsl" + +#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; +#ifdef HAVE_VFX_MODIFICATION + AttributesElement inputElement; + varyingsType.vmesh = VertMesh(inputMesh, inputElement); + return MotionVectorVS(varyingsType, inputMesh, inputPass, inputElement); +#else + varyingsType.vmesh = VertMesh(inputMesh); + return MotionVectorVS(varyingsType, inputMesh, inputPass); +#endif +} + +#ifdef TESSELLATION_ON + +PackedVaryingsToPS VertTesselation(VaryingsToDS input) +{ + VaryingsToPS output; + output.vmesh = VertMeshTesselation(input.vmesh); + return MotionVectorTessellation(output, input); +} + +#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) +{ + VaryingsType varyingsType; + +#if defined(HAVE_RECURSIVE_RENDERING) + // If we have a recursive raytrace object, we will not render it. + // As we don't want to rely on renderqueue to exclude the object from the list, + // we cull it by settings position to NaN value. + // TODO: provide a solution to filter dyanmically recursive raytrace object in the DrawRenderer + if (_EnableRecursiveRayTracing && _RayTracing > 0.0) + { + ZERO_INITIALIZE(VaryingsType, varyingsType); // Divide by 0 should produce a NaN and thus cull the primitive. + } + else +#endif + { + varyingsType.vmesh = VertMesh(inputMesh); + } + + return PackVaryingsType(varyingsType); +} + +#ifdef TESSELLATION_ON + +PackedVaryingsToPS VertTesselation(VaryingsToDS input) +{ + VaryingsToPS output; + output.vmesh = VertMeshTesselation(input.vmesh); + + return PackVaryingsToPS(output); +} + +#endif // TESSELLATION_ON + +#endif // _WRITE_TRANSPARENT_MOTION_VECTOR + + +#ifdef TESSELLATION_ON +#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/TessellationShare.hlsl" +#endif + +#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugDisplayMaterial.hlsl" + +//NOTE: some shaders set target1 to be +// Blend 1 SrcAlpha OneMinusSrcAlpha +//The reason for this blend mode is to let virtual texturing alpha dither work. +//Anything using Target1 should write 1.0 or 0.0 in alpha to write / not write into the target. + +#ifdef UNITY_VIRTUAL_TEXTURING + #ifdef OUTPUT_SPLIT_LIGHTING + #define DIFFUSE_LIGHTING_TARGET SV_Target2 + #define SSS_BUFFER_TARGET SV_Target3 + #elif defined(_WRITE_TRANSPARENT_MOTION_VECTOR) + #define MOTION_VECTOR_TARGET SV_Target2 + #endif + #if defined(SHADER_API_PSSL) + //For exact packing on pssl, we want to write exact 16 bit unorm (respect exact bit packing). + //In some sony platforms, the default is FMT_16_ABGR, which would incur in loss of precision. + //Thus, when VT is enabled, we force FMT_32_ABGR + #pragma PSSL_target_output_format(target 1 FMT_32_ABGR) + #endif +#else + #ifdef OUTPUT_SPLIT_LIGHTING + #define DIFFUSE_LIGHTING_TARGET SV_Target1 + #define SSS_BUFFER_TARGET SV_Target2 + #elif defined(_WRITE_TRANSPARENT_MOTION_VECTOR) + #define MOTION_VECTOR_TARGET SV_Target1 + #endif +#endif + +[earlydepthstencil] +void Frag(PackedVaryingsToPS packedInput + , out float4 outColor : SV_Target0 // outSpecularLighting when outputting split lighting + #ifdef UNITY_VIRTUAL_TEXTURING + , out float4 outVTFeedback : SV_Target1 + #endif + #ifdef OUTPUT_SPLIT_LIGHTING + , out float4 outDiffuseLighting : DIFFUSE_LIGHTING_TARGET + , OUTPUT_SSSBUFFER(outSSSBuffer) : SSS_BUFFER_TARGET + #elif defined(_WRITE_TRANSPARENT_MOTION_VECTOR) + , out float4 outMotionVec : MOTION_VECTOR_TARGET + #endif + #ifdef _DEPTHOFFSET_ON + , out float outputDepth : DEPTH_OFFSET_SEMANTIC + #endif + , uint uSampleIdx : SV_SampleIndex +) +{ +#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) + // Always write 1.0 in alpha since blend mode could be active on this target as a side effect of VT feedback buffer + // motion vector expected output format is RG16 + outMotionVec = float4(2.0, 0.0, 0.0, 1.0); +#endif + + UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(packedInput); + FragInputs input = UnpackVaryingsToFragInputs(packedInput); + + AdjustFragInputsToOffScreenRendering(input, _OffScreenRendering > 0, _OffScreenDownsampleFactor); + + uint2 tileIndex = uint2(input.positionSS.xy) / GetTileSize(); + + // input.positionSS is SV_Position + PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw, input.positionSS.z, input.positionSS.w, input.positionRWS.xyz, tileIndex); + +#ifdef VARYINGS_NEED_POSITION_WS + float3 V = GetWorldSpaceNormalizeViewDir(input.positionRWS); +#else + // Unused + float3 V = float3(1.0, 1.0, 1.0); // Avoid the division by 0 +#endif + + SurfaceData surfaceData; + BuiltinData builtinData; + GetSurfaceAndBuiltinData(input, V, posInput, surfaceData, builtinData); + + BSDFData bsdfData = ConvertSurfaceDataToBSDFData(input.positionSS.xy, surfaceData); + + PreLightData preLightData = GetPreLightData(V, posInput, bsdfData); + + outColor = float4(0.0, 0.0, 0.0, 0.0); + + // We need to skip lighting when doing debug pass because the debug pass is done before lighting so some buffers may not be properly initialized potentially causing crashes on PS4. + +#ifdef DEBUG_DISPLAY + // Init in debug display mode to quiet warning +#ifdef OUTPUT_SPLIT_LIGHTING + // Always write 1.0 in alpha since blend mode could be active on this target as a side effect of VT feedback buffer + // Diffuse output is expected to be RGB10, so alpha must always be 1 to ensure it is written. + outDiffuseLighting = float4(0, 0, 0, 1); + ENCODE_INTO_SSSBUFFER(surfaceData, posInput.positionSS, outSSSBuffer); +#endif + + bool viewMaterial = GetMaterialDebugColor(outColor, input, builtinData, posInput, surfaceData, bsdfData); + + if (!viewMaterial) + { + if (_DebugFullScreenMode == FULLSCREENDEBUGMODE_VALIDATE_DIFFUSE_COLOR || _DebugFullScreenMode == FULLSCREENDEBUGMODE_VALIDATE_SPECULAR_COLOR) + { + float3 result = float3(0.0, 0.0, 0.0); + + GetPBRValidatorDebug(surfaceData, result); + + outColor = float4(result, 1.0f); + } + else if (_DebugFullScreenMode == FULLSCREENDEBUGMODE_TRANSPARENCY_OVERDRAW) + { + float4 result = _DebugTransparencyOverdrawWeight * float4(TRANSPARENCY_OVERDRAW_COST, TRANSPARENCY_OVERDRAW_COST, TRANSPARENCY_OVERDRAW_COST, TRANSPARENCY_OVERDRAW_A); + outColor = result; + } + else +#endif + { +#ifdef _SURFACE_TYPE_TRANSPARENT + uint featureFlags = LIGHT_FEATURE_MASK_FLAGS_TRANSPARENT; +#else + uint featureFlags = LIGHT_FEATURE_MASK_FLAGS_OPAQUE; +#endif + LightLoopOutput lightLoopOutput; + LightLoop(V, posInput, preLightData, bsdfData, builtinData, featureFlags, lightLoopOutput); + + // Alias + float3 diffuseLighting = lightLoopOutput.diffuseLighting; + float3 specularLighting = lightLoopOutput.specularLighting; + + diffuseLighting *= GetCurrentExposureMultiplier(); + specularLighting *= GetCurrentExposureMultiplier(); + +#ifdef OUTPUT_SPLIT_LIGHTING + if (_EnableSubsurfaceScattering != 0 && ShouldOutputSplitLighting(bsdfData)) + { + outColor = float4(specularLighting, 1.0); + // Always write 1.0 in alpha since blend mode could be active on this target as a side effect of VT feedback buffer + // Diffuse output is expected to be RGB10, so alpha must always be 1 to ensure it is written. + outDiffuseLighting = float4(TagLightingForSSS(diffuseLighting), 1.0); + } + else + { + outColor = float4(diffuseLighting + specularLighting, 1.0); + // Always write 1.0 in alpha since blend mode could be active on this target as a side effect of VT feedback buffer + // Diffuse output is expected to be RGB10, so alpha must always be 1 to ensure it is written. + outDiffuseLighting = float4(0, 0, 0, 1); + } + ENCODE_INTO_SSSBUFFER(surfaceData, posInput.positionSS, outSSSBuffer); +#else + outColor = ApplyBlendMode(diffuseLighting, specularLighting, builtinData.opacity); + outColor = EvaluateAtmosphericScattering(posInput, V, outColor); +#endif + +#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) + + //Motion vector is enabled in SG but not active in VFX +#if defined(HAVE_VFX_MODIFICATION) && !VFX_FEATURE_MOTION_VECTORS + forceNoMotion = true; +#endif + + if (!forceNoMotion) + { + float2 motionVec = CalculateMotionVector(inputPass.positionCS, inputPass.previousPositionCS); + EncodeMotionVector(motionVec * 0.5, outMotionVec); + + // Always write 1.0 in alpha since blend mode could be active on this target as a side effect of VT feedback buffer + // motion vector expected output format is RG16 + outMotionVec.zw = 1.0; + } +#endif + } + +#ifdef DEBUG_DISPLAY + } +#endif + +#ifdef _DEPTHOFFSET_ON + outputDepth = posInput.deviceDepth; +#endif + +#ifdef UNITY_VIRTUAL_TEXTURING + float vtAlphaValue = builtinData.opacity; + #if defined(HAS_REFRACTION) && HAS_REFRACTION + vtAlphaValue = 1.0f - bsdfData.transmittanceMask; + #endif + outVTFeedback = PackVTFeedbackWithAlpha(builtinData.vtPackedFeedback, input.positionSS.xy, vtAlphaValue); +#endif + + createFragmentEntry(float4(outColor.rgb, builtinData.opacity), packedInput.vmesh.positionCS.xyz, uSampleIdx); +} diff --git a/HDRP/Shaders/OitShaderPassForwardHDRP.hlsl.meta b/HDRP/Shaders/OitShaderPassForwardHDRP.hlsl.meta new file mode 100644 index 0000000..30cd266 --- /dev/null +++ b/HDRP/Shaders/OitShaderPassForwardHDRP.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 43dfc7268426406468e999c1b6376709 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PostProcessingStackV2/Runtime/OitPostProcess.cs b/PostProcessingStackV2/Runtime/OitPostProcess.cs index c29238a..f52c3ad 100644 --- a/PostProcessingStackV2/Runtime/OitPostProcess.cs +++ b/PostProcessingStackV2/Runtime/OitPostProcess.cs @@ -19,7 +19,7 @@ internal class OitPostProcessRenderer : PostProcessEffectRenderer FLBuffer : register(u1); RWByteAddressBuffer StartOffsetBuffer : register(u2); +// PackRGBA takes a float4 value and packs it into a UINT (8 bits / float) +uint PackRGBA(float4 unpackedInput) +{ + uint4 u = (uint4)(saturate(unpackedInput) * 255 + 0.5); + uint packedOutput = (u.w << 24UL) | (u.z << 16UL) | (u.y << 8UL) | u.x; + return packedOutput; +} + +uint PackDepthSampleIdx(float depth, uint uSampleIdx) { + uint d = (uint)(saturate(depth) * (pow(2, 24) - 1)); + return d << 8UL | uSampleIdx; +} + +// Z buffer to linear 0..1 depth +inline float OitLinear01Depth( float z ) +{ + return 1.0 / (_ZBufferParams.x * z + _ZBufferParams.y); +} + void createFragmentEntry(float4 col, float3 pos, uint uSampleIdx) { //Retrieve current Pixel count and increase counter uint uPixelCount = FLBuffer.IncrementCounter(); diff --git a/Shaders/LinkedListRendering.hlsl b/Shaders/LinkedListRendering.hlsl index d29acd6..a3b1217 100644 --- a/Shaders/LinkedListRendering.hlsl +++ b/Shaders/LinkedListRendering.hlsl @@ -1,18 +1,36 @@ #ifndef OIT_LINKED_LIST_INCLUDED #define OIT_LINKED_LIST_INCLUDED -#include "OitUtils.hlsl" - -struct FragmentAndLinkBuffer_STRUCT -{ - uint pixelColor; - uint uDepthSampleIdx; - uint next; -}; +#include "LinkedListStruct.hlsl" StructuredBuffer FLBuffer : register(t0); ByteAddressBuffer StartOffsetBuffer : register(t1); +// Unity's HLSL seems not to support dynamic array size, so we can only set this before compilation +#define MAX_SORTED_PIXELS 8 + +//https://github.com/GameTechDev/AOIT-Update/blob/master/OIT_DX11/AOIT%20Technique/AOIT.hlsl +// UnpackRGBA takes a uint value and converts it to a float4 +float4 UnpackRGBA(uint packedInput) +{ + float4 unpackedOutput; + uint4 p = uint4((packedInput & 0xFFUL), + (packedInput >> 8UL) & 0xFFUL, + (packedInput >> 16UL) & 0xFFUL, + (packedInput >> 24UL)); + + unpackedOutput = ((float4)p) / 255; + return unpackedOutput; +} + +float UnpackDepth(uint uDepthSampleIdx) { + return (float)(uDepthSampleIdx >> 8UL) / (pow(2, 24) - 1); +} + +uint UnpackSampleIdx(uint uDepthSampleIdx) { + return uDepthSampleIdx & 0xFFUL; +} + float4 renderLinkedList(float4 col, float2 pos, uint uSampleIndex) { // Fetch offset of first fragment for current pixel diff --git a/Shaders/LinkedListStruct.hlsl b/Shaders/LinkedListStruct.hlsl new file mode 100644 index 0000000..f0c289d --- /dev/null +++ b/Shaders/LinkedListStruct.hlsl @@ -0,0 +1,11 @@ +#ifndef LINKED_LIST_STRUCT_INCLUDED +#define LINKED_LIST_STRUCT_INCLUDED + +struct FragmentAndLinkBuffer_STRUCT +{ + uint pixelColor; + uint uDepthSampleIdx; + uint next; +}; + +#endif // LINKED_LIST_STRUCT_INCLUDED \ No newline at end of file diff --git a/Shaders/OitUtils.hlsl.meta b/Shaders/LinkedListStruct.hlsl.meta similarity index 100% rename from Shaders/OitUtils.hlsl.meta rename to Shaders/LinkedListStruct.hlsl.meta diff --git a/Shaders/OitUnlit.shader b/Shaders/OitUnlit.shader index 518fc0e..3ebfbc2 100644 --- a/Shaders/OitUnlit.shader +++ b/Shaders/OitUnlit.shader @@ -6,6 +6,10 @@ Shader "OrderIndependentTransparency/Unlit" } SubShader { + PackageRequirements { + "org.happy-turtle.order-independent-transparency" + } + Tags{ "Queue" = "Geometry" } Pass { @@ -17,12 +21,11 @@ Shader "OrderIndependentTransparency/Unlit" HLSLPROGRAM #pragma vertex vert #pragma fragment frag - #pragma target 5.0 - #pragma require randomwrite + #pragma target 4.5 // #pragma enable_d3d11_debug_symbols #include "UnityCG.cginc" - #include "LinkedListCreation.hlsl" + #include "Packages/org.happy-turtle.order-independent-transparency/Shaders/LinkedListCreation.hlsl" sampler2D _MainTex; float4 _MainTex_ST; diff --git a/Shaders/OitUtils.hlsl b/Shaders/OitUtils.hlsl deleted file mode 100644 index f30855b..0000000 --- a/Shaders/OitUtils.hlsl +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef OIT_UTILS_INCLUDED -#define OIT_UTILS_INCLUDED - -// Unity's HLSL seems not to support dynamic array size, so we can only set this before compilation -#define MAX_SORTED_PIXELS 8 - -//https://github.com/GameTechDev/AOIT-Update/blob/master/OIT_DX11/AOIT%20Technique/AOIT.hlsl -// UnpackRGBA takes a uint value and converts it to a float4 -float4 UnpackRGBA(uint packedInput) -{ - float4 unpackedOutput; - uint4 p = uint4((packedInput & 0xFFUL), - (packedInput >> 8UL) & 0xFFUL, - (packedInput >> 16UL) & 0xFFUL, - (packedInput >> 24UL)); - - unpackedOutput = ((float4)p) / 255; - return unpackedOutput; -} - -// PackRGBA takes a float4 value and packs it into a UINT (8 bits / float) -uint PackRGBA(float4 unpackedInput) -{ - uint4 u = (uint4)(saturate(unpackedInput) * 255 + 0.5); - uint packedOutput = (u.w << 24UL) | (u.z << 16UL) | (u.y << 8UL) | u.x; - return packedOutput; -} - -float UnpackDepth(uint uDepthSampleIdx) { - return (float)(uDepthSampleIdx >> 8UL) / (pow(2, 24) - 1); -} - -uint UnpackSampleIdx(uint uDepthSampleIdx) { - return uDepthSampleIdx & 0xFFUL; -} - -uint PackDepthSampleIdx(float depth, uint uSampleIdx) { - uint d = (uint)(saturate(depth) * (pow(2, 24) - 1)); - return d << 8UL | uSampleIdx; -} - -// Z buffer to linear 0..1 depth -inline float OitLinear01Depth( float z ) -{ - return 1.0 / (_ZBufferParams.x * z + _ZBufferParams.y); -} - -#endif // OIT_UTILS_INCLUDED \ No newline at end of file diff --git a/Shaders/Resources/OitRender.shader b/Shaders/Resources/OitRender.shader new file mode 100644 index 0000000..4705351 --- /dev/null +++ b/Shaders/Resources/OitRender.shader @@ -0,0 +1,136 @@ +Shader "Hidden/OitRender" +{ + Properties{ + _MainTex("Main Texture", 2DArray) = "white" {} + } + SubShader + { + PackageRequirements { + "org.happy-turtle.order-independent-transparency" + "com.unity.render-pipelines.high-definition" + } + Tags { "RenderPipeline" = "HDRenderPipeline" } + Pass { + Name "HDRP Order-Independent Transparency Pass" + ZTest Always + ZWrite Off + Blend Off + Cull Off + + HLSLPROGRAM + #pragma fragment frag + #pragma vertex Vert + #pragma target 4.5 + #pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch + // #pragma enable_d3d11_debug_symbols + + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/CustomPass/CustomPassCommon.hlsl" + #include "Packages/org.happy-turtle.order-independent-transparency/Shaders/LinkedListRendering.hlsl" + + float4 frag(Varyings input, uint uSampleIndex : SV_SampleIndex) : SV_Target + { + UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); + + float4 col = float4 (0, 1, 0, 1); + float depth = LoadCameraDepth(input.positionCS.xy); + PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V); + // Load the camera color buffer at the mip 0 if we're not at the before rendering injection point + if (_CustomPassInjectionPoint != CUSTOMPASSINJECTIONPOINT_BEFORE_RENDERING) + col = float4(CustomPassSampleCameraColor(posInput.positionNDC.xy, 0), 1); + + return renderLinkedList(col, input.positionCS.xy, uSampleIndex); + } + ENDHLSL + } + } + SubShader + { + PackageRequirements { + "org.happy-turtle.order-independent-transparency" + "com.unity.render-pipelines.universal" + } + Tags { "RenderPipeline" = "UniversalPipeline" } + Pass { + Name "URP Order-Independent Transparency Pass" + ZTest Always + ZWrite Off + Cull Off + Blend Off + + HLSLPROGRAM + #pragma vertex Vert + #pragma fragment frag + #pragma target 4.5 + // #pragma enable_d3d11_debug_symbols + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + #include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl" + #include "Packages/org.happy-turtle.order-independent-transparency/Shaders/LinkedListRendering.hlsl" + + TEXTURE2D_X(_CameraOpaqueTexture); + SAMPLER(sampler_CameraOpaqueTexture); + + //Pixel function returns a solid color for each point. + half4 frag(Varyings input, uint uSampleIndex: SV_SampleIndex) : SV_Target + { + UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); + // Retrieve current color from background texture + float4 col = SAMPLE_TEXTURE2D_X(_CameraOpaqueTexture, sampler_CameraOpaqueTexture, input.texcoord); + + return renderLinkedList(col, input.positionCS.xy, uSampleIndex); + } + ENDHLSL + } + } + SubShader + { + PackageRequirements { + "org.happy-turtle.order-independent-transparency" + } + Pass { + ZTest Always + ZWrite Off + Cull Off + Blend Off + + HLSLPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma target 4.5 + // #pragma enable_d3d11_debug_symbols + + #include "UnityCG.cginc" + #include "Packages/org.happy-turtle.order-independent-transparency/Shaders/LinkedListRendering.hlsl" + + struct appdata { + float4 vertex : POSITION; + float2 texcoord : TEXCOORD0; + }; + struct v2f { + float2 uv : TEXCOORD0; + float4 vertex : SV_POSITION; + }; + + sampler2D _MainTex; + float4 _MainTex_ST; + + v2f vert(appdata v) + { + v2f o; + o.vertex = UnityObjectToClipPos(v.vertex); + o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); + return o; + } + + //Pixel function returns a solid color for each point. + fixed4 frag(v2f i, uint uSampleIndex : SV_SampleIndex) : SV_Target + { + // Retrieve current color from background texture + float4 col = tex2D(_MainTex, i.uv); + + return renderLinkedList(col, i.vertex.xy, uSampleIndex); + } + ENDHLSL + } + } +} \ No newline at end of file diff --git a/Shaders/Resources/OitRenderHDRP.shader.meta b/Shaders/Resources/OitRender.shader.meta similarity index 100% rename from Shaders/Resources/OitRenderHDRP.shader.meta rename to Shaders/Resources/OitRender.shader.meta diff --git a/Shaders/Resources/OitRenderHDRP.shader b/Shaders/Resources/OitRenderHDRP.shader deleted file mode 100644 index c87e93f..0000000 --- a/Shaders/Resources/OitRenderHDRP.shader +++ /dev/null @@ -1,46 +0,0 @@ -Shader "Hidden/OitRenderHDRP" -{ - Properties{ - _MainTex("Main Texture", 2DArray) = "white" {} - } - SubShader - { - PackageRequirements { - "com.unity.render-pipelines.high-definition" - } - Tags { "RenderPipeline" = "HDRenderPipeline" } - Pass { - Name "HDRP Order-Independent Transparency Pass" - ZTest Always - ZWrite Off - Blend Off - Cull Off - - HLSLPROGRAM - #pragma fragment frag - #pragma vertex Vert - #pragma target 5.0 - #pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch - #pragma require randomwrite - // #pragma enable_d3d11_debug_symbols - - #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/CustomPass/CustomPassCommon.hlsl" - #include "../LinkedListRendering.hlsl" - - float4 frag(Varyings input, uint uSampleIndex : SV_SampleIndex) : SV_Target - { - UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); - - float4 col = float4 (0, 1, 0, 1); - float depth = LoadCameraDepth(input.positionCS.xy); - PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V); - // Load the camera color buffer at the mip 0 if we're not at the before rendering injection point - if (_CustomPassInjectionPoint != CUSTOMPASSINJECTIONPOINT_BEFORE_RENDERING) - col = float4(CustomPassSampleCameraColor(posInput.positionNDC.xy, 0), 1); - - return renderLinkedList(col, input.positionCS.xy, uSampleIndex); - } - ENDHLSL - } - } -} \ No newline at end of file diff --git a/Shaders/Resources/OitRenderPPv2.shader b/Shaders/Resources/OitRenderPPv2.shader deleted file mode 100644 index 99e6e1a..0000000 --- a/Shaders/Resources/OitRenderPPv2.shader +++ /dev/null @@ -1,55 +0,0 @@ -Shader "Hidden/OitRenderPPv2" -{ - Properties{ - _MainTex("Main Texture", 2DArray) = "white" {} - } - SubShader - { - Pass { - ZTest Always - ZWrite Off - Cull Off - Blend Off - - HLSLPROGRAM - #pragma vertex vert - #pragma fragment frag - #pragma target 5.0 - #pragma require randomwrite - // #pragma enable_d3d11_debug_symbols - - #include "UnityCG.cginc" - #include "../LinkedListRendering.hlsl" - - struct appdata { - float4 vertex : POSITION; - float2 texcoord : TEXCOORD0; - }; - struct v2f { - float2 uv : TEXCOORD0; - float4 vertex : SV_POSITION; - }; - - sampler2D _MainTex; - float4 _MainTex_ST; - - v2f vert(appdata v) - { - v2f o; - o.vertex = UnityObjectToClipPos(v.vertex); - o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); - return o; - } - - //Pixel function returns a solid color for each point. - fixed4 frag(v2f i, uint uSampleIndex : SV_SampleIndex) : SV_Target - { - // Retrieve current color from background texture - float4 col = tex2D(_MainTex, i.uv); - - return renderLinkedList(col, i.vertex.xy, uSampleIndex); - } - ENDHLSL - } - } -} \ No newline at end of file diff --git a/Shaders/Resources/OitRenderPPv2.shader.meta b/Shaders/Resources/OitRenderPPv2.shader.meta deleted file mode 100644 index bf575c7..0000000 --- a/Shaders/Resources/OitRenderPPv2.shader.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: f2e2448455bf4f6ba2ec561a0aa09479 -timeCreated: 1669232651 \ No newline at end of file diff --git a/Shaders/Resources/OitRenderURP.shader b/Shaders/Resources/OitRenderURP.shader deleted file mode 100644 index fd4a72a..0000000 --- a/Shaders/Resources/OitRenderURP.shader +++ /dev/null @@ -1,42 +0,0 @@ -Shader "Hidden/OitRenderURP" -{ - SubShader - { - PackageRequirements { - "com.unity.render-pipelines.universal" - } - Tags { "RenderPipeline" = "UniversalPipeline" } - Pass { - Name "URP Order-Independent Transparency Pass" - ZTest Always - ZWrite Off - Cull Off - Blend Off - - HLSLPROGRAM - #pragma vertex Vert - #pragma fragment frag - #pragma target 5.0 - #pragma require randomwrite - // #pragma enable_d3d11_debug_symbols - - #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" - #include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl" - #include "../LinkedListRendering.hlsl" - - TEXTURE2D_X(_CameraOpaqueTexture); - SAMPLER(sampler_CameraOpaqueTexture); - - //Pixel function returns a solid color for each point. - half4 frag(Varyings input, uint uSampleIndex: SV_SampleIndex) : SV_Target - { - UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); - // Retrieve current color from background texture - float4 col = SAMPLE_TEXTURE2D_X(_CameraOpaqueTexture, sampler_CameraOpaqueTexture, input.texcoord); - - return renderLinkedList(col, input.positionCS.xy, uSampleIndex); - } - ENDHLSL - } - } -} \ No newline at end of file diff --git a/Shared/OitLinkedList.cs b/Shared/OitLinkedList.cs index 86a4db8..d04ec08 100644 --- a/Shared/OitLinkedList.cs +++ b/Shared/OitLinkedList.cs @@ -25,7 +25,11 @@ public OitLinkedList(string shaderName) oitComputeUtils = Resources.Load("OitComputeUtils"); clearStartOffsetBufferKernel = oitComputeUtils.FindKernel("ClearStartOffsetBuffer"); - SetupGraphicsBuffers(); + + if (screenWidth != 0 && screenHeight != 0) + { + SetupGraphicsBuffers(); + } } public void PreRender(CommandBuffer command) diff --git a/URP/Runtime/OitPass.cs b/URP/Runtime/OitPass.cs index 66a7c91..77b051e 100644 --- a/URP/Runtime/OitPass.cs +++ b/URP/Runtime/OitPass.cs @@ -12,7 +12,7 @@ internal class OitPass : ScriptableRenderPass public OitPass() { renderPassEvent = RenderPassEvent.BeforeRenderingTransparents; - orderIndependentTransparency = new OitLinkedList("OitRenderURP"); + orderIndependentTransparency = new OitLinkedList("OitRender"); RenderPipelineManager.beginContextRendering += PreRender; } diff --git a/URP/Shaders/OitLitURP.shader b/URP/Shaders/OitLitURP.shader index 8752882..a52148f 100644 --- a/URP/Shaders/OitLitURP.shader +++ b/URP/Shaders/OitLitURP.shader @@ -66,6 +66,11 @@ Shader "OrderIndependentTransparency/URP/Lit" SubShader { + PackageRequirements { + "org.happy-turtle.order-independent-transparency" + "com.unity.render-pipelines.universal" + } + // Universal Pipeline tag is required. If Universal render pipeline is not set in the graphics settings // this Subshader will fail. One can add a subshader below or fallback to Standard built-in to make this // material work with both Universal Render Pipeline and Builtin Unity Pipeline @@ -98,8 +103,7 @@ Shader "OrderIndependentTransparency/URP/Lit" Cull Off HLSLPROGRAM - #pragma target 5.0 - #pragma require randomwrite + #pragma target 4.5 // ------------------------------------- // Shader Stages @@ -177,7 +181,7 @@ Shader "OrderIndependentTransparency/URP/Lit" Cull[_Cull] HLSLPROGRAM - #pragma target 5.0 + #pragma target 4.5 // ------------------------------------- // Shader Stages @@ -306,7 +310,7 @@ Shader "OrderIndependentTransparency/URP/Lit" Cull[_Cull] HLSLPROGRAM - #pragma target 5.0 + #pragma target 4.5 // ------------------------------------- // Shader Stages @@ -355,7 +359,7 @@ Shader "OrderIndependentTransparency/URP/Lit" Cull Off HLSLPROGRAM - #pragma target 5.0 + #pragma target 4.5 // ------------------------------------- // Shader Stages @@ -397,7 +401,7 @@ Shader "OrderIndependentTransparency/URP/Lit" Cull Off HLSLPROGRAM - #pragma target 5.0 + #pragma target 4.5 // ------------------------------------- // Shader Stages @@ -419,6 +423,6 @@ Shader "OrderIndependentTransparency/URP/Lit" } } - FallBack "Hidden/Universal Render Pipeline/FallbackError" + FallBack "OrderIndependentTransparency/Unlit" CustomEditor "UnityEditor.Rendering.Universal.ShaderGUI.LitShader" }