ConverterSplitPreview_URP.shader 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. //Mesh Terain Editor's terrain split preview shader for URP
  2. //http://u3d.as/oWB
  3. //This is a modified shader from https://github.com/ColinLeung-NiloCat/UnityURPUnlitScreenSpaceDecalShader
  4. Shader "Hidden/MTE/ConverterSplitPreview/URP"
  5. {
  6. Properties
  7. {
  8. [Header(MTE Parameters)]
  9. _SplitNumber("Split Number", int) = 2
  10. _NormalizedLineWidth("Normalized Line Width", float) = 0.01
  11. [Header(Basic)]
  12. _MainTex("Texture", 2D) = "white" {}
  13. [HDR]_Color("_Color (default = 1,1,1,1)", color) = (1,1,1,1)
  14. [Header(Blending)]
  15. //https://docs.unity3d.com/ScriptReference/Rendering.BlendMode.html
  16. [Enum(UnityEngine.Rendering.BlendMode)]_SrcBlend("_SrcBlend (default = One)", Float) = 1 //1 = One
  17. [Enum(UnityEngine.Rendering.BlendMode)]_DstBlend("_DstBlend (default = One)", Float) = 1 //1 = One
  18. [Header(Alpha remap(extra alpha control))]
  19. _AlphaRemap("_AlphaRemap (default = 1,0,0,0) _____alpha will first mul x, then add y (zw unused)", vector) = (1,0,0,0)
  20. [Header(Prevent Side Stretching(Compare projection direction with scene normal and Discard if needed))]
  21. [Toggle(_ProjectionAngleDiscardEnable)] _ProjectionAngleDiscardEnable("_ProjectionAngleDiscardEnable (default = off)", float) = 0
  22. _ProjectionAngleDiscardThreshold("_ProjectionAngleDiscardThreshold (default = 0)", range(-1,1)) = 0
  23. [Header(Mul alpha to rgb)]
  24. [Toggle]_MulAlphaToRGB("_MulAlphaToRGB (default = off)", Float) = 0
  25. [Header(Ignore texture wrap mode setting)]
  26. [Toggle(_FracUVEnable)] _FracUVEnable("_FracUVEnable (default = off)", Float) = 0
  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. [Header(ZTest)]
  33. //https://docs.unity3d.com/ScriptReference/Rendering.CompareFunction.html
  34. //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)
  35. [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
  36. [Header(Cull)]
  37. //https://docs.unity3d.com/ScriptReference/Rendering.CullMode.html
  38. //default need to be Front, because we need to make sure decal render correctly even if camera goes into decal cube
  39. [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
  40. [Header(Unity Fog)]
  41. [Toggle(_UnityFogEnable)] _UnityFogEnable("_UnityFogEnable (default = on)", Float) = 1
  42. }
  43. SubShader
  44. {
  45. //To avoid render order problems, Queue must >= 2501, which enters the transparent queue, in transparent queue Unity will always draw from back to front
  46. //https://github.com/ColinLeung-NiloCat/UnityURPUnlitScreenSpaceDecalShader/issues/6#issuecomment-615940985
  47. /*
  48. //https://docs.unity3d.com/Manual/SL-SubShaderTags.html
  49. Queues up to 2500 (“Geometry+500”) are consided “opaque” and optimize the drawing order of the objects for best performance.
  50. Higher rendering queues are considered for “transparent objects” and sort objects by distance, starting rendering from the furthest ones and ending with the closest ones.
  51. Skyboxes are drawn in between all opaque and all transparent objects.
  52. */
  53. Tags { "RenderType" = "Overlay" "Queue" = "Transparent-499" }
  54. Pass
  55. {
  56. Stencil
  57. {
  58. Ref[_StencilRef]
  59. Comp[_StencilComp]
  60. }
  61. Cull[_Cull]
  62. ZTest[_ZTest]
  63. ZWrite off
  64. Blend[_SrcBlend][_DstBlend]
  65. HLSLPROGRAM
  66. #pragma vertex vert
  67. #pragma fragment frag
  68. // make fog work
  69. #pragma multi_compile_fog
  70. //due to using ddx() & ddy()
  71. #pragma target 3.0
  72. #pragma shader_feature_local _ProjectionAngleDiscardEnable
  73. #pragma shader_feature_local _UnityFogEnable
  74. #pragma shader_feature_local _FracUVEnable
  75. // Required by all Universal Render Pipeline shaders.
  76. // It will include Unity built-in shader variables (except the lighting variables)
  77. // (https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html
  78. // It will also include many utilitary functions.
  79. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
  80. // for calculating color against the main light and normal map
  81. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
  82. struct appdata
  83. {
  84. float4 vertex : POSITION;
  85. };
  86. struct v2f
  87. {
  88. float4 vertex : SV_POSITION;
  89. float4 screenUV : TEXCOORD0;
  90. float4 viewRayOS : TEXCOORD1;
  91. float4 cameraPosOSAndFogFactor : TEXCOORD2;
  92. };
  93. sampler2D _MainTex;
  94. CBUFFER_START(UnityPerMaterial)
  95. float4 _MainTex_ST;
  96. int _SplitNumber;
  97. float _NormalizedLineWidth;
  98. float _ProjectionAngleDiscardThreshold;
  99. half4 _Color;
  100. half2 _AlphaRemap;
  101. half _MulAlphaToRGB;
  102. CBUFFER_END
  103. sampler2D _CameraDepthTexture;
  104. v2f vert(appdata v)
  105. {
  106. v2f o;
  107. //regular MVP
  108. o.vertex = TransformObjectToHClip(v.vertex.xyz);
  109. //regular unity fog
  110. #if _UnityFogEnable
  111. o.cameraPosOSAndFogFactor.a = ComputeFogFactor(o.vertex.z);
  112. #else
  113. o.cameraPosOSAndFogFactor.a = 0;
  114. #endif
  115. //prepare depth texture's screen space UV
  116. o.screenUV = ComputeScreenPos(o.vertex);
  117. //get "camera to vertex" ray in View space
  118. float3 viewRay = TransformWorldToView(TransformObjectToWorld(v.vertex.xyz));
  119. //***WARNING***
  120. //=========================================================
  121. //"viewRay z division" must do in the fragment shader, not vertex shader! (due to rasteriazation varying interpolation's perspective correction)
  122. //We skip the "viewRay z division" in vertex shader for now, and pass the division value to varying o.viewRayOS.w first, we will do the division later when we enter fragment shader
  123. //viewRay /= viewRay.z; //skip the "viewRay z division" in vertex shader for now
  124. o.viewRayOS.w = viewRay.z;//pass the division value to varying o.viewRayOS.w
  125. //=========================================================
  126. viewRay *= -1; //unity's camera space is right hand coord(negativeZ pointing into screen), we want positive z ray in fragment shader, so negate it
  127. //it is ok to write very expensive code in decal's vertex shader, it is just a unity cube(4*6 vertices) per decal only, won't affect GPU performance at all.
  128. float4x4 ViewToObjectMatrix = mul(unity_WorldToObject, UNITY_MATRIX_I_V);
  129. //transform everything to object space(decal space) in vertex shader first, so we can skip all matrix mul() in fragment shader
  130. o.viewRayOS.xyz = mul((float3x3)ViewToObjectMatrix, viewRay);
  131. o.cameraPosOSAndFogFactor.xyz = mul(ViewToObjectMatrix, float4(0,0,0,1)).xyz;
  132. return o;
  133. }
  134. half4 frag(v2f i) : SV_Target
  135. {
  136. //***WARNING***
  137. //=========================================================
  138. //now do "viewRay z division" that we skipped in vertex shader earlier.
  139. i.viewRayOS /= i.viewRayOS.w;
  140. //=========================================================
  141. float sceneCameraSpaceDepth = LinearEyeDepth(tex2Dproj(_CameraDepthTexture, i.screenUV).r, _ZBufferParams);
  142. //scene depth in any space = rayStartPos + rayDir * rayLength
  143. //here all data in ObjectSpace(OS) or DecalSpace
  144. float3 decalSpaceScenePos = i.cameraPosOSAndFogFactor.xyz + i.viewRayOS.xyz * sceneCameraSpaceDepth;
  145. //convert unity cube's [-0.5,0.5] vertex pos range to [0,1] uv. Only works if you use unity cube in mesh filter!
  146. float2 decalSpaceUV = decalSpaceScenePos.xy + 0.5;
  147. //discard logic
  148. //===================================================
  149. // discard "out of cube volume" pixels
  150. //2020-4-17: tried fix clip() bug by removing all possible bool
  151. //https://github.com/ColinLeung-NiloCat/UnityURPUnlitScreenSpaceDecalShader/issues/6#issuecomment-614633460
  152. float mask = (abs(decalSpaceScenePos.x) < 0.5 ? 1.0 : 0.0) * (abs(decalSpaceScenePos.y) < 0.5 ? 1.0 : 0.0) * (abs(decalSpaceScenePos.z) < 0.5 ? 1.0 : 0.0);
  153. #if _ProjectionAngleDiscardEnable
  154. // also discard "scene normal not facing decal projector direction" pixels
  155. float3 decalSpaceHardNormal = normalize(cross(ddx(decalSpaceScenePos), ddy(decalSpaceScenePos)));//reconstruct scene hard normal using scene pos ddx&ddy
  156. mask *= decalSpaceHardNormal.z > _ProjectionAngleDiscardThreshold ? 1.0 : 0.0;//compare scene hard normal with decal projector's dir, decalSpaceHardNormal.z equals dot(decalForwardDir,sceneHardNormalDir)
  157. #endif
  158. //call discard
  159. clip(mask - 0.5);//if ZWrite is off, clip() is fast enough on mobile, because it won't write the DepthBuffer, so no pipeline stall(confirmed by ARM staff).
  160. //===================================================
  161. // sample the decal texture
  162. float2 uv = decalSpaceUV.xy * _MainTex_ST.xy + _MainTex_ST.zw;//Texture tiling & offset
  163. #if _FracUVEnable
  164. uv = frac(uv);//add frac to ignore texture wrap setting
  165. #endif
  166. half4 col = tex2D(_MainTex, uv);
  167. col *= _Color;//tint color
  168. col.a = saturate(col.a * _AlphaRemap.x + _AlphaRemap.y);//alpha remap MAD
  169. col.rgb *= lerp(1, col.a, _MulAlphaToRGB);//extra multiply alpha to RGB
  170. float2 st = uv;
  171. st *= _SplitNumber;
  172. st = frac(st);
  173. float min = 0;
  174. float max = _NormalizedLineWidth;
  175. float c = smoothstep(min, max, st.x)*smoothstep(min, max, st.y);
  176. col = half4(1-c,1-c,1-c,0.5);
  177. #if _UnityFogEnable
  178. // Mix the pixel color with fogColor. You can optionaly use MixFogColor to override the fogColor
  179. // with a custom one.
  180. col.rgb = MixFog(col.rgb, i.cameraPosOSAndFogFactor.a);
  181. #endif
  182. return col;
  183. }
  184. ENDHLSL
  185. }
  186. }
  187. }