Guest User

PBR Lit Shader Example for Universal RP

a guest
Jul 27th, 2020
1,197
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Example Shader for Universal RP
  2. // Written by @Cyanilux
  3. // https://cyangamedev.wordpress.com/urp-shader-code/
  4. Shader "Custom/LitShaderExample" {
  5. Properties {
  6. _BaseMap ("Base Texture", 2D) = "white" {}
  7. _BaseColor ("Example Colour", Color) = (0, 0.66, 0.73, 1)
  8. _Smoothness ("Smoothness", Float) = 0.5
  9.  
  10. [Toggle(_ALPHATEST_ON)] _EnableAlphaTest("Enable Alpha Cutoff", Float) = 0.0
  11. _Cutoff ("Alpha Cutoff", Float) = 0.5
  12.  
  13. [Toggle(_NORMALMAP)] _EnableBumpMap("Enable Normal/Bump Map", Float) = 0.0
  14. _BumpMap ("Normal/Bump Texture", 2D) = "bump" {}
  15. _BumpScale ("Bump Scale", Float) = 1
  16.  
  17. [Toggle(_EMISSION)] _EnableEmission("Enable Emission", Float) = 0.0
  18. _EmissionMap ("Emission Texture", 2D) = "white" {}
  19. _EmissionColor ("Emission Colour", Color) = (0, 0, 0, 0)
  20. }
  21. SubShader {
  22. Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalPipeline" }
  23.  
  24. HLSLINCLUDE
  25. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
  26.  
  27. CBUFFER_START(UnityPerMaterial)
  28. float4 _BaseMap_ST;
  29. float4 _BaseColor;
  30. float _BumpScale;
  31. float4 _EmissionColor;
  32. float _Smoothness;
  33. float _Cutoff;
  34. CBUFFER_END
  35. ENDHLSL
  36.  
  37. Pass {
  38. Name "Example"
  39. Tags { "LightMode"="UniversalForward" }
  40.  
  41. HLSLPROGRAM
  42.  
  43. // Required to compile gles 2.0 with standard SRP library
  44. // All shaders must be compiled with HLSLcc and currently only gles is not using HLSLcc by default
  45. #pragma prefer_hlslcc gles
  46. #pragma exclude_renderers d3d11_9x gles
  47.  
  48. //#pragma target 4.5 // https://docs.unity3d.com/Manual/SL-ShaderCompileTargets.html
  49.  
  50. #pragma vertex vert
  51. #pragma fragment frag
  52.  
  53. // Material Keywords
  54. #pragma shader_feature _NORMALMAP
  55. #pragma shader_feature _ALPHATEST_ON
  56. #pragma shader_feature _ALPHAPREMULTIPLY_ON
  57. #pragma shader_feature _EMISSION
  58. //#pragma shader_feature _METALLICSPECGLOSSMAP
  59. //#pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
  60. //#pragma shader_feature _OCCLUSIONMAP
  61. //#pragma shader_feature _ _CLEARCOAT _CLEARCOATMAP // URP v10+
  62.  
  63. //#pragma shader_feature _SPECULARHIGHLIGHTS_OFF
  64. //#pragma shader_feature _ENVIRONMENTREFLECTIONS_OFF
  65. //#pragma shader_feature _SPECULAR_SETUP
  66. #pragma shader_feature _RECEIVE_SHADOWS_OFF
  67.  
  68. // URP Keywords
  69. #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
  70. #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
  71. #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
  72. #pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
  73. #pragma multi_compile _ _SHADOWS_SOFT
  74. #pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE
  75.  
  76. // Unity defined keywords
  77. #pragma multi_compile _ DIRLIGHTMAP_COMBINED
  78. #pragma multi_compile _ LIGHTMAP_ON
  79. #pragma multi_compile_fog
  80.  
  81. // Includes
  82. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
  83. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"
  84.  
  85. struct Attributes {
  86. float4 positionOS : POSITION;
  87. float3 normalOS : NORMAL;
  88. float4 tangentOS : TANGENT;
  89. float4 color : COLOR;
  90. float2 uv : TEXCOORD0;
  91. float2 lightmapUV : TEXCOORD1;
  92. };
  93.  
  94. struct Varyings {
  95. float4 positionCS : SV_POSITION;
  96. float4 color : COLOR;
  97. float2 uv : TEXCOORD0;
  98. DECLARE_LIGHTMAP_OR_SH(lightmapUV, vertexSH, 1);
  99.  
  100. #ifdef REQUIRES_WORLD_SPACE_POS_INTERPOLATOR
  101. float3 positionWS : TEXCOORD2;
  102. #endif
  103.  
  104. float3 normalWS : TEXCOORD3;
  105. #ifdef _NORMALMAP
  106. float4 tangentWS : TEXCOORD4;
  107. #endif
  108.  
  109. float3 viewDirWS : TEXCOORD5;
  110. half4 fogFactorAndVertexLight : TEXCOORD6; // x: fogFactor, yzw: vertex light
  111.  
  112. #ifdef REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR
  113. float4 shadowCoord : TEXCOORD7;
  114. #endif
  115. };
  116.  
  117. // Automatically defined with SurfaceInput.hlsl
  118. //TEXTURE2D(_BaseMap);
  119. //SAMPLER(sampler_BaseMap);
  120.  
  121. #if SHADER_LIBRARY_VERSION_MAJOR < 9
  122. // This function was added in URP v9.x.x versions, if we want to support URP versions before, we need to handle it instead.
  123. // Computes the world space view direction (pointing towards the viewer).
  124. float3 GetWorldSpaceViewDir(float3 positionWS) {
  125. if (unity_OrthoParams.w == 0) {
  126. // Perspective
  127. return _WorldSpaceCameraPos - positionWS;
  128. } else {
  129. // Orthographic
  130. float4x4 viewMat = GetWorldToViewMatrix();
  131. return viewMat[2].xyz;
  132. }
  133. }
  134. #endif
  135.  
  136. Varyings vert(Attributes IN) {
  137. Varyings OUT;
  138.  
  139. VertexPositionInputs positionInputs = GetVertexPositionInputs(IN.positionOS.xyz);
  140. OUT.positionCS = positionInputs.positionCS;
  141. OUT.uv = TRANSFORM_TEX(IN.uv, _BaseMap);
  142. OUT.color = IN.color;
  143.  
  144. #ifdef REQUIRES_WORLD_SPACE_POS_INTERPOLATOR
  145. OUT.positionWS = positionInputs.positionWS;
  146. #endif
  147.  
  148. OUT.viewDirWS = GetWorldSpaceViewDir(positionInputs.positionWS);
  149.  
  150. VertexNormalInputs normalInputs = GetVertexNormalInputs(IN.normalOS, IN.tangentOS);
  151. OUT.normalWS = normalInputs.normalWS;
  152. #ifdef _NORMALMAP
  153. real sign = IN.tangentOS.w * GetOddNegativeScale();
  154. OUT.tangentWS = half4(normalInputs.tangentWS.xyz, sign);
  155. #endif
  156.  
  157. half3 vertexLight = VertexLighting(positionInputs.positionWS, normalInputs.normalWS);
  158. half fogFactor = ComputeFogFactor(positionInputs.positionCS.z);
  159.  
  160. OUT.fogFactorAndVertexLight = half4(fogFactor, vertexLight);
  161.  
  162. OUTPUT_LIGHTMAP_UV(IN.lightmapUV, unity_LightmapST, OUT.lightmapUV);
  163. OUTPUT_SH(OUT.normalWS.xyz, OUT.vertexSH);
  164.  
  165. #ifdef REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR
  166. OUT.shadowCoord = GetShadowCoord(positionInputs);
  167. #endif
  168.  
  169. return OUT;
  170. }
  171.  
  172. InputData InitializeInputData(Varyings IN, half3 normalTS){
  173. InputData inputData = (InputData)0;
  174.  
  175. #if defined(REQUIRES_WORLD_SPACE_POS_INTERPOLATOR)
  176. inputData.positionWS = IN.positionWS;
  177. #endif
  178.  
  179. half3 viewDirWS = SafeNormalize(IN.viewDirWS);
  180. #ifdef _NORMALMAP
  181. float sgn = IN.tangentWS.w; // should be either +1 or -1
  182. float3 bitangent = sgn * cross(IN.normalWS.xyz, IN.tangentWS.xyz);
  183. inputData.normalWS = TransformTangentToWorld(normalTS, half3x3(IN.tangentWS.xyz, bitangent.xyz, IN.normalWS.xyz));
  184. #else
  185. inputData.normalWS = IN.normalWS;
  186. #endif
  187.  
  188. inputData.normalWS = NormalizeNormalPerPixel(inputData.normalWS);
  189. inputData.viewDirectionWS = viewDirWS;
  190.  
  191. #if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
  192. inputData.shadowCoord = IN.shadowCoord;
  193. #elif defined(MAIN_LIGHT_CALCULATE_SHADOWS)
  194. inputData.shadowCoord = TransformWorldToShadowCoord(inputData.positionWS);
  195. #else
  196. inputData.shadowCoord = float4(0, 0, 0, 0);
  197. #endif
  198.  
  199. inputData.fogCoord = IN.fogFactorAndVertexLight.x;
  200. inputData.vertexLighting = IN.fogFactorAndVertexLight.yzw;
  201. inputData.bakedGI = SAMPLE_GI(IN.lightmapUV, IN.vertexSH, inputData.normalWS);
  202. return inputData;
  203. }
  204.  
  205. SurfaceData InitializeSurfaceData(Varyings IN){
  206. SurfaceData surfaceData = (SurfaceData)0;
  207. // Note, we can just use SurfaceData surfaceData; here and not set it.
  208. // However we then need to ensure all values in the struct are set before returning.
  209. // By casting 0 to SurfaceData, we automatically set all the contents to 0.
  210.  
  211. half4 albedoAlpha = SampleAlbedoAlpha(IN.uv, TEXTURE2D_ARGS(_BaseMap, sampler_BaseMap));
  212. surfaceData.alpha = Alpha(albedoAlpha.a, _BaseColor, _Cutoff);
  213. surfaceData.albedo = albedoAlpha.rgb * _BaseColor.rgb * IN.color.rgb;
  214.  
  215. // For the sake of simplicity I'm not supporting the metallic/specular map or occlusion map
  216. // for an example of that see : https://github.com/Unity-Technologies/Graphics/blob/master/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl
  217.  
  218. surfaceData.smoothness = 0.5;
  219. surfaceData.normalTS = SampleNormal(IN.uv, TEXTURE2D_ARGS(_BumpMap, sampler_BumpMap), _BumpScale);
  220. surfaceData.emission = SampleEmission(IN.uv, _EmissionColor.rgb, TEXTURE2D_ARGS(_EmissionMap, sampler_EmissionMap));
  221.  
  222. surfaceData.occlusion = 1;
  223.  
  224. return surfaceData;
  225. }
  226.  
  227. half4 frag(Varyings IN) : SV_Target {
  228. SurfaceData surfaceData = InitializeSurfaceData(IN);
  229. InputData inputData = InitializeInputData(IN, surfaceData.normalTS);
  230.  
  231. // In URP v10+ versions we could use this :
  232. // half4 color = UniversalFragmentPBR(inputData, surfaceData);
  233.  
  234. // But for other versions, we need to use this instead.
  235. // We could also avoid using the SurfaceData struct completely, but it helps to organise things.
  236. half4 color = UniversalFragmentPBR(inputData, surfaceData.albedo, surfaceData.metallic,
  237. surfaceData.specular, surfaceData.smoothness, surfaceData.occlusion,
  238. surfaceData.emission, surfaceData.alpha);
  239.  
  240. color.rgb = MixFog(color.rgb, inputData.fogCoord);
  241.  
  242. // color.a = OutputAlpha(color.a);
  243. // Not sure if this is important really. It's implemented as :
  244. // saturate(outputAlpha + _DrawObjectPassData.a);
  245. // Where _DrawObjectPassData.a is 1 for opaque objects and 0 for alpha blended.
  246. // But it was added in URP v8, and versions before just didn't have it.
  247. // We could still saturate the alpha to ensure it doesn't go outside the 0-1 range though :
  248. color.a = saturate(color.a);
  249.  
  250. return color; // float4(inputData.bakedGI,1);
  251. }
  252. ENDHLSL
  253. }
  254.  
  255. // UsePass "Universal Render Pipeline/Lit/ShadowCaster"
  256. // Note, you can do this, but it will break batching with the SRP Batcher currently due to the CBUFFERs not being the same.
  257. // So instead, we'll define the pass manually :
  258. Pass {
  259. Name "ShadowCaster"
  260. Tags { "LightMode"="ShadowCaster" }
  261.  
  262. ZWrite On
  263. ZTest LEqual
  264.  
  265. HLSLPROGRAM
  266. // Required to compile gles 2.0 with standard srp library
  267. #pragma prefer_hlslcc gles
  268. #pragma exclude_renderers d3d11_9x gles
  269. //#pragma target 4.5
  270.  
  271. // Material Keywords
  272. #pragma shader_feature _ALPHATEST_ON
  273. #pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
  274.  
  275. // GPU Instancing
  276. #pragma multi_compile_instancing
  277. #pragma multi_compile _ DOTS_INSTANCING_ON
  278.  
  279. #pragma vertex ShadowPassVertex
  280. #pragma fragment ShadowPassFragment
  281.  
  282. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
  283. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"
  284. #include "Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl"
  285.  
  286. // Note if we want to do any vertex displacment, we'll need to change the vertex function :
  287. /*
  288. // e.g.
  289. #pragma vertex vert
  290.  
  291. Varyings vert(Attributes input) {
  292. Varyings output;
  293. UNITY_SETUP_INSTANCE_ID(input);
  294.  
  295. // Example Displacement
  296. input.positionOS += float4(0, _SinTime.y, 0, 0);
  297.  
  298. output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap);
  299. output.positionCS = GetShadowPositionHClip(input);
  300. return output;
  301. }*/
  302.  
  303. // Using the ShadowCasterPass means we also need _BaseMap, _BaseColor and _Cutoff shader properties.
  304. // Also including them in cbuffer, with the exception of _BaseMap as it's a texture.
  305.  
  306. ENDHLSL
  307. }
  308.  
  309. // Similarly, we should have a DepthOnly pass.
  310. // UsePass "Universal Render Pipeline/Lit/DepthOnly"
  311. // Again, since the cbuffer is different it'll break batching with the SRP Batcher.
  312.  
  313. // The DepthOnly pass is very similar to the ShadowCaster but doesn't include the shadow bias offsets.
  314. // I believe Unity uses this pass when rendering the depth of objects in the Scene View.
  315. // But for the Game View / actual camera Depth Texture it renders fine without it.
  316. // It's possible that it could be used in Forward Renderer features though, so we should probably still include it.
  317. Pass {
  318. Name "DepthOnly"
  319. Tags { "LightMode"="DepthOnly" }
  320.  
  321. ZWrite On
  322. ColorMask 0
  323.  
  324. HLSLPROGRAM
  325. // Required to compile gles 2.0 with standard srp library
  326. #pragma prefer_hlslcc gles
  327. #pragma exclude_renderers d3d11_9x gles
  328. //#pragma target 4.5
  329.  
  330. // Material Keywords
  331. #pragma shader_feature _ALPHATEST_ON
  332. #pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
  333.  
  334. // GPU Instancing
  335. #pragma multi_compile_instancing
  336. #pragma multi_compile _ DOTS_INSTANCING_ON
  337.  
  338. #pragma vertex DepthOnlyVertex
  339. #pragma fragment DepthOnlyFragment
  340.  
  341. //#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
  342. // Note, the Lit shader that URP provides uses this, but it also handles the cbuffer which we already have.
  343. // We could change the shader to use their cbuffer, but we can also just do this :
  344. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
  345. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"
  346. #include "Packages/com.unity.render-pipelines.universal/Shaders/DepthOnlyPass.hlsl"
  347.  
  348. // Again, using the DepthOnlyPass means we also need _BaseMap, _BaseColor and _Cutoff shader properties.
  349. // Also including them in cbuffer, with the exception of _BaseMap as it's a texture.
  350.  
  351. ENDHLSL
  352. }
  353.  
  354. // URP also has a "Meta" pass, used when baking lightmaps.
  355. // UsePass "Universal Render Pipeline/Lit/Meta"
  356. // While this still breaks the SRP Batcher, I'm curious as to whether it matters.
  357. // The Meta pass is only used for lightmap baking, so surely is only used in editor?
  358. // Anyway, if you want to write your own meta pass look at the shaders URP provides for examples
  359. // https://github.com/Unity-Technologies/Graphics/tree/master/com.unity.render-pipelines.universal/Shaders
  360. }
  361. }
RAW Paste Data