Search Unity

Question How do I make the shader ignore some layers?

Discussion in 'Shader Graph' started by MrKsi, Oct 1, 2022.

  1. MrKsi

    MrKsi

    Joined:
    Aug 30, 2020
    Posts:
    139
    Hello everyone, I ran into such a problem, I have a shader that simulates texture in all directions, but I need it to simulate texture only on certain layers, like a projector, which is not available in my version of Unity URP. How do I add a layer constraint?

    Code (CSharp):
    1. Shader "KJPiGames/Multiply"
    2. {
    3.     Properties
    4.     {
    5.         [Header(Basic)]
    6.         [MainTexture]_MainTex("Texture", 2D) = "white" {}
    7.         [MainColor][HDR]_Color("_Color (default = 1,1,1,1)", Color) = (1,1,1,1)
    8.  
    9.         [Header(Blending)]
    10.         // https://docs.unity3d.com/ScriptReference/Rendering.BlendMode.html
    11.         [Enum(UnityEngine.Rendering.BlendMode)]_DecalSrcBlend("_DecalSrcBlend (default = SrcAlpha)", Int) = 5 // 5 = SrcAlpha
    12.         [Enum(UnityEngine.Rendering.BlendMode)]_DecalDstBlend("_DecalDstBlend (default = OneMinusSrcAlpha)", Int) = 10 // 10 = OneMinusSrcAlpha
    13.  
    14.         [Header(Alpha remap(extra alpha control))]
    15.         _AlphaRemap("_AlphaRemap (default = 1,0,0,0) _____alpha will first mul x, then add y    (zw unused)", vector) = (1,0,0,0)
    16.  
    17.         [Header(Prevent Side Stretching(Compare projection direction with scene normal and Discard if needed))]
    18.         [Toggle(_ProjectionAngleDiscardEnable)] _ProjectionAngleDiscardEnable("_ProjectionAngleDiscardEnable (default = off)", float) = 0
    19.         _ProjectionAngleDiscardThreshold("_ProjectionAngleDiscardThreshold (default = 0)", range(-1,1)) = 0
    20.  
    21.         [Header(Mul alpha to rgb)]
    22.         [Toggle]_MulAlphaToRGB("_MulAlphaToRGB (default = off)", Float) = 0
    23.  
    24.         [Header(Ignore texture wrap mode setting)]
    25.         [Toggle(_FracUVEnable)] _FracUVEnable("_FracUVEnable (default = off)", Float) = 0
    26.  
    27.         //====================================== below = usually can ignore in normal use case =====================================================================
    28.         [Header(Stencil Masking)]
    29.         // https://docs.unity3d.com/ScriptReference/Rendering.CompareFunction.html
    30.         _StencilRef("_StencilRef", Float) = 0
    31.         [Enum(UnityEngine.Rendering.CompareFunction)]_StencilComp("_StencilComp (default = Disable) _____Set to NotEqual if you want to mask by specific _StencilRef value, else set to Disable", Float) = 0 //0 = disable
    32.  
    33.         [Header(ZTest)]
    34.         // https://docs.unity3d.com/ScriptReference/Rendering.CompareFunction.html
    35.         // default need to be Disable, because we need to make sure decal render correctly even if camera goes into decal cube volume, although disable ZTest by default will prevent EarlyZ (bad for GPU performance)
    36.         [Enum(UnityEngine.Rendering.CompareFunction)]_ZTest("_ZTest (default = Disable) _____to improve GPU performance, Set to LessEqual if camera never goes into cube volume, else set to Disable", Float) = 0 //0 = disable
    37.  
    38.         [Header(Cull)]
    39.         // https://docs.unity3d.com/ScriptReference/Rendering.CullMode.html
    40.         // default need to be Front, because we need to make sure decal render correctly even if camera goes into decal cube
    41.         [Enum(UnityEngine.Rendering.CullMode)]_Cull("_Cull (default = Front) _____to improve GPU performance, Set to Back if camera never goes into cube volume, else set to Front", Float) = 1 //1 = Front
    42.  
    43.         [Header(Unity Fog)]
    44.         [Toggle(_UnityFogEnable)] _UnityFogEnable("_UnityFogEnable (default = on)", Float) = 1
    45.  
    46.         [Header(Support Orthographic camera)]
    47.         [Toggle(_SupportOrthographicCamera)] _SupportOrthographicCamera("_SupportOrthographicCamera (default = off)", Float) = 0
    48.     }
    49.  
    50.     SubShader
    51.     {
    52.         // To avoid render order problems, Queue must >= 2501, which enters the transparent queue,
    53.         // in transparent queue Unity will always draw from back to front
    54.         // https://github.com/ColinLeung-NiloCat/UnityURPUnlitScreenSpaceDecalShader/issues/6#issuecomment-615940985
    55.  
    56.         // https://docs.unity3d.com/Manual/SL-SubShaderTags.html
    57.         // Queues up to 2500 (“Geometry+500”) are consided “opaque” and optimize the drawing order of the objects for best performance.
    58.         // Higher rendering queues are considered for “transparent objects” and sort objects by distance,
    59.         // starting rendering from the furthest ones and ending with the closest ones.
    60.         // Skyboxes are drawn in between all opaque and all transparent objects.
    61.         // "Queue" = "Transparent-499" means "Queue" = "2501", which is almost equals "draw right before any transparent objects"
    62.  
    63.         // "DisableBatching" means disable "dynamic batching", not "srp batching"
    64.         Tags { "RenderType" = "Overlay" "Queue" = "Transparent-499" "DisableBatching" = "True" }
    65.  
    66.         Pass
    67.         {
    68.             Stencil
    69.             {
    70.                 Ref[_StencilRef]
    71.                 Comp[_StencilComp]
    72.             }
    73.  
    74.             Cull[_Cull]
    75.             ZTest[_ZTest]
    76.  
    77.             ZWrite off
    78.             Blend[_DecalSrcBlend][_DecalDstBlend]
    79.  
    80.             HLSLPROGRAM
    81.  
    82.             #pragma vertex vert
    83.             #pragma fragment frag
    84.  
    85.             // make fog work
    86.             #pragma multi_compile_fog
    87.  
    88.             // due to using ddx() & ddy()
    89.             #pragma target 3.0
    90.  
    91.             #pragma shader_feature_local_fragment _ProjectionAngleDiscardEnable
    92.             #pragma shader_feature_local _UnityFogEnable
    93.             #pragma shader_feature_local_fragment _FracUVEnable
    94.             #pragma shader_feature_local_fragment _SupportOrthographicCamera
    95.  
    96.             // Required by all Universal Render Pipeline shaders.
    97.             // It will include Unity built-in shader variables (except the lighting variables)
    98.             // (https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html
    99.             // It will also include many utilitary functions.
    100.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    101.  
    102.             struct appdata
    103.             {
    104.                 float3 positionOS : POSITION;
    105.             };
    106.  
    107.             struct v2f
    108.             {
    109.                 float4 positionCS : SV_POSITION;
    110.                 float4 screenPos : TEXCOORD0;
    111.                 float4 viewRayOS : TEXCOORD1; // xyz: viewRayOS, w: extra copy of positionVS.z
    112.                 float4 cameraPosOSAndFogFactor : TEXCOORD2;
    113.             };
    114.  
    115.             sampler2D _MainTex;
    116.             sampler2D _CameraDepthTexture;
    117.  
    118.             CBUFFER_START(UnityPerMaterial)              
    119.                 float4 _MainTex_ST;
    120.                 float _ProjectionAngleDiscardThreshold;
    121.                 half4 _Color;
    122.                 half2 _AlphaRemap;
    123.                 half _MulAlphaToRGB;
    124.             CBUFFER_END
    125.  
    126.             v2f vert(appdata input)
    127.             {
    128.                 v2f o;
    129.  
    130.                 // VertexPositionInputs contains position in multiple spaces (world, view, homogeneous clip space, ndc)
    131.                 // Unity compiler will strip all unused references (say you don't use view space).
    132.                 // Therefore there is more flexibility at no additional cost with this struct.
    133.                 VertexPositionInputs vertexPositionInput = GetVertexPositionInputs(input.positionOS);
    134.  
    135.                 o.positionCS = vertexPositionInput.positionCS;
    136.  
    137.                 // regular unity fog
    138. #if _UnityFogEnable
    139.                 o.cameraPosOSAndFogFactor.a = ComputeFogFactor(o.positionCS.z);
    140. #else
    141.                 o.cameraPosOSAndFogFactor.a = 0;
    142. #endif
    143.  
    144.                 // prepare depth texture's screen space UV
    145.                 o.screenPos = ComputeScreenPos(o.positionCS);
    146.  
    147.                 // get "camera to vertex" ray in View space
    148.                 float3 viewRay = vertexPositionInput.positionVS;
    149.  
    150.                 // [important note]
    151.                 //=========================================================
    152.                 // "viewRay z division" must do in the fragment shader, not vertex shader! (due to rasteriazation varying interpolation's perspective correction)
    153.                 // We skip the "viewRay z division" in vertex shader for now, and store the division value into varying o.viewRayOS.w first,
    154.                 // we will do the division later when we enter fragment shader
    155.                 // viewRay /= viewRay.z; //skip the "viewRay z division" in vertex shader for now
    156.                 o.viewRayOS.w = viewRay.z;//store the division value to varying o.viewRayOS.w
    157.                 //=========================================================
    158.  
    159.                 // unity's camera space is right hand coord(negativeZ pointing into screen), we want positive z ray in fragment shader, so negate it
    160.                 viewRay *= -1;
    161.  
    162.                 // it is ok to write very expensive code in decal's vertex shader,
    163.                 // it is just a unity cube(4*6 vertices) per decal only, won't affect GPU performance at all.
    164.                 float4x4 ViewToObjectMatrix = mul(UNITY_MATRIX_I_M, UNITY_MATRIX_I_V);
    165.  
    166.                 // transform everything to object space(decal space) in vertex shader first, so we can skip all matrix mul() in fragment shader
    167.                 o.viewRayOS.xyz = mul((float3x3)ViewToObjectMatrix, viewRay);
    168.                 o.cameraPosOSAndFogFactor.xyz = mul(ViewToObjectMatrix, float4(0,0,0,1)).xyz; // hard code 0 or 1 can enable many compiler optimization
    169.  
    170.                 return o;
    171.             }
    172.  
    173.             // copied from URP12.1.2's ShaderVariablesFunctions.hlsl
    174.             float LinearDepthToEyeDepth(float rawDepth)
    175.             {
    176.                 #if UNITY_REVERSED_Z
    177.                     return _ProjectionParams.z - (_ProjectionParams.z - _ProjectionParams.y) * rawDepth;
    178.                 #else
    179.                     return _ProjectionParams.y + (_ProjectionParams.z - _ProjectionParams.y) * rawDepth;
    180.                 #endif
    181.             }
    182.  
    183.             half4 frag(v2f i) : SV_Target
    184.             {
    185.                 // [important note]
    186.                 //========================================================================
    187.                 // now do "viewRay z division" that we skipped in vertex shader earlier.
    188.                 i.viewRayOS.xyz /= i.viewRayOS.w;
    189.                 //========================================================================
    190.  
    191.                 float2 screenSpaceUV = i.screenPos.xy / i.screenPos.w;
    192.                 float sceneRawDepth = tex2D(_CameraDepthTexture, screenSpaceUV).r;
    193.  
    194.                 float3 decalSpaceScenePos;
    195.  
    196. #if _SupportOrthographicCamera
    197.                 // we have to support both orthographic and perspective camera projection
    198.                 // static uniform branch depends on unity_OrthoParams.w
    199.                 // (should we use UNITY_BRANCH here?) decided NO because https://forum.unity.com/threads/correct-use-of-unity_branch.476804/
    200.                 if(unity_OrthoParams.w)
    201.                 {
    202.                     float sceneDepthVS = LinearDepthToEyeDepth(sceneRawDepth);
    203.  
    204.                     //***Used a few lines from Asset: Lux URP Essentials by forst***
    205.                     // Edit: The copied Lux URP stopped working at some point, and no one even knew why it worked in the first place
    206.                     //----------------------------------------------------------------------------
    207.                     float2 viewRayEndPosVS_xy = float2(unity_OrthoParams.xy * (i.screenPos.xy - 0.5) * 2 /* to clip space */);  // Ortho near/far plane xy pos
    208.                     float4 vposOrtho = float4(viewRayEndPosVS_xy, -sceneDepthVS, 1);                                            // Constructing a view space pos
    209.                     float3 wposOrtho = mul(UNITY_MATRIX_I_V, vposOrtho).xyz;                                                 // Trans. view space to world space
    210.                     //----------------------------------------------------------------------------
    211.  
    212.                     // transform world to object space(decal space)
    213.                     decalSpaceScenePos = mul(GetWorldToObjectMatrix(), float4(wposOrtho, 1)).xyz;
    214.                 }
    215.                 else
    216.                 {
    217. #endif
    218.                     // if perspective camera, LinearEyeDepth will handle everything for user
    219.                     // remember we can't use LinearEyeDepth for orthographic camera!
    220.                     float sceneDepthVS = LinearEyeDepth(sceneRawDepth,_ZBufferParams);
    221.  
    222.                     // scene depth in any space = rayStartPos + rayDir * rayLength
    223.                     // here all data in ObjectSpace(OS) or DecalSpace
    224.                     // be careful, viewRayOS is not a unit vector, so don't normalize it, it is a direction vector which view space z's length is 1
    225.                     decalSpaceScenePos = i.cameraPosOSAndFogFactor.xyz + i.viewRayOS.xyz * sceneDepthVS;
    226.                    
    227. #if _SupportOrthographicCamera
    228.                 }
    229. #endif
    230.  
    231.                 // convert unity cube's [-0.5,0.5] vertex pos range to [0,1] uv. Only works if you use a unity cube in mesh filter!
    232.                 float2 decalSpaceUV = decalSpaceScenePos.xy + 0.5;
    233.  
    234.                 // discard logic
    235.                 //===================================================
    236.                 // discard "out of cube volume" pixels
    237.                 float shouldClip = 0;
    238. #if _ProjectionAngleDiscardEnable
    239.                 // also discard "scene normal not facing decal projector direction" pixels
    240.                 float3 decalSpaceHardNormal = normalize(cross(ddx(decalSpaceScenePos), ddy(decalSpaceScenePos)));//reconstruct scene hard normal using scene pos ddx&ddy
    241.  
    242.                 // compare scene hard normal with decal projector's dir, decalSpaceHardNormal.z equals dot(decalForwardDir,sceneHardNormalDir)
    243.                 shouldClip = decalSpaceHardNormal.z > _ProjectionAngleDiscardThreshold ? 0 : 1;
    244. #endif
    245.                 // call discard
    246.                 // if ZWrite is Off, clip() is fast enough on mobile, because it won't write the DepthBuffer, so no GPU pipeline stall(confirmed by ARM staff).
    247.                 clip(0.5 - abs(decalSpaceScenePos) - shouldClip);
    248.                 //===================================================
    249.  
    250.                 // sample the decal texture
    251.                 float2 uv = decalSpaceUV.xy * _MainTex_ST.xy + _MainTex_ST.zw;//Texture tiling & offset
    252. #if _FracUVEnable
    253.                 uv = frac(uv);// add frac to ignore texture wrap setting
    254. #endif
    255.                 half4 col = tex2D(_MainTex, uv);
    256.                 col *= _Color;// tint color
    257.                 col.a = saturate(col.a * _AlphaRemap.x + _AlphaRemap.y);// alpha remap MAD
    258.                 col.rgb *= lerp(1, col.a, _MulAlphaToRGB);// extra multiply alpha to RGB
    259.  
    260. #if _UnityFogEnable
    261.                 // Mix the pixel color with fogColor. You can optionaly use MixFogColor to override the fogColor
    262.                 // with a custom one.
    263.                 col.rgb = MixFog(col.rgb, i.cameraPosOSAndFogFactor.a);
    264. #endif
    265.                 return col;
    266.             }
    267.             ENDHLSL
    268.         }
    269.     }
    270. }
    271.  
     
  2. MrKsi

    MrKsi

    Joined:
    Aug 30, 2020
    Posts:
    139
    Here's what it looks like:
     

    Attached Files:

    • 13.gif
      13.gif
      File size:
      2.4 MB
      Views:
      193
  3. MrKsi

    MrKsi

    Joined:
    Aug 30, 2020
    Posts:
    139