Нема описа
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TerrainLitPasses.hlsl 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. #ifndef UNIVERSAL_TERRAIN_LIT_PASSES_INCLUDED
  2. #define UNIVERSAL_TERRAIN_LIT_PASSES_INCLUDED
  3. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
  4. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/UnityGBuffer.hlsl"
  5. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DBuffer.hlsl"
  6. struct Attributes
  7. {
  8. float4 positionOS : POSITION;
  9. float3 normalOS : NORMAL;
  10. float2 texcoord : TEXCOORD0;
  11. UNITY_VERTEX_INPUT_INSTANCE_ID
  12. };
  13. struct Varyings
  14. {
  15. float4 uvMainAndLM : TEXCOORD0; // xy: control, zw: lightmap
  16. #ifndef TERRAIN_SPLAT_BASEPASS
  17. float4 uvSplat01 : TEXCOORD1; // xy: splat0, zw: splat1
  18. float4 uvSplat23 : TEXCOORD2; // xy: splat2, zw: splat3
  19. #endif
  20. #if defined(_NORMALMAP) && !defined(ENABLE_TERRAIN_PERPIXEL_NORMAL)
  21. half4 normal : TEXCOORD3; // xyz: normal, w: viewDir.x
  22. half4 tangent : TEXCOORD4; // xyz: tangent, w: viewDir.y
  23. half4 bitangent : TEXCOORD5; // xyz: bitangent, w: viewDir.z
  24. #else
  25. half3 normal : TEXCOORD3;
  26. half3 vertexSH : TEXCOORD4; // SH
  27. #endif
  28. #ifdef _ADDITIONAL_LIGHTS_VERTEX
  29. half4 fogFactorAndVertexLight : TEXCOORD6; // x: fogFactor, yzw: vertex light
  30. #else
  31. half fogFactor : TEXCOORD6;
  32. #endif
  33. float3 positionWS : TEXCOORD7;
  34. #if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
  35. float4 shadowCoord : TEXCOORD8;
  36. #endif
  37. #if defined(DYNAMICLIGHTMAP_ON)
  38. float2 dynamicLightmapUV : TEXCOORD9;
  39. #endif
  40. #ifdef USE_APV_PROBE_OCCLUSION
  41. float4 probeOcclusion : TEXCOORD10;
  42. #endif
  43. float4 clipPos : SV_POSITION;
  44. UNITY_VERTEX_OUTPUT_STEREO
  45. };
  46. void InitializeInputData(Varyings IN, half3 normalTS, out InputData inputData)
  47. {
  48. inputData = (InputData)0;
  49. inputData.positionWS = IN.positionWS;
  50. inputData.positionCS = IN.clipPos;
  51. #if defined(_NORMALMAP) && !defined(ENABLE_TERRAIN_PERPIXEL_NORMAL)
  52. half3 viewDirWS = half3(IN.normal.w, IN.tangent.w, IN.bitangent.w);
  53. inputData.tangentToWorld = half3x3(-IN.tangent.xyz, IN.bitangent.xyz, IN.normal.xyz);
  54. inputData.normalWS = TransformTangentToWorld(normalTS, inputData.tangentToWorld);
  55. half3 SH = 0;
  56. #elif defined(ENABLE_TERRAIN_PERPIXEL_NORMAL)
  57. half3 viewDirWS = GetWorldSpaceNormalizeViewDir(IN.positionWS);
  58. float2 sampleCoords = (IN.uvMainAndLM.xy / _TerrainHeightmapRecipSize.zw + 0.5f) * _TerrainHeightmapRecipSize.xy;
  59. half3 normalWS = TransformObjectToWorldNormal(normalize(SAMPLE_TEXTURE2D(_TerrainNormalmapTexture, sampler_TerrainNormalmapTexture, sampleCoords).rgb * 2 - 1));
  60. half3 tangentWS = cross(GetObjectToWorldMatrix()._13_23_33, normalWS);
  61. inputData.normalWS = TransformTangentToWorld(normalTS, half3x3(-tangentWS, cross(normalWS, tangentWS), normalWS));
  62. half3 SH = IN.vertexSH;
  63. #else
  64. half3 viewDirWS = GetWorldSpaceNormalizeViewDir(IN.positionWS);
  65. inputData.normalWS = IN.normal;
  66. half3 SH = IN.vertexSH;
  67. #endif
  68. inputData.normalWS = NormalizeNormalPerPixel(inputData.normalWS);
  69. inputData.viewDirectionWS = viewDirWS;
  70. #if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
  71. inputData.shadowCoord = IN.shadowCoord;
  72. #elif defined(MAIN_LIGHT_CALCULATE_SHADOWS)
  73. inputData.shadowCoord = TransformWorldToShadowCoord(inputData.positionWS);
  74. #else
  75. inputData.shadowCoord = float4(0, 0, 0, 0);
  76. #endif
  77. #ifdef _ADDITIONAL_LIGHTS_VERTEX
  78. inputData.fogCoord = InitializeInputDataFog(float4(IN.positionWS, 1.0), IN.fogFactorAndVertexLight.x);
  79. inputData.vertexLighting = IN.fogFactorAndVertexLight.yzw;
  80. #else
  81. inputData.fogCoord = InitializeInputDataFog(float4(IN.positionWS, 1.0), IN.fogFactor);
  82. #endif
  83. #if defined(DYNAMICLIGHTMAP_ON)
  84. inputData.bakedGI = SAMPLE_GI(IN.uvMainAndLM.zw, IN.dynamicLightmapUV, SH, inputData.normalWS);
  85. inputData.shadowMask = SAMPLE_SHADOWMASK(IN.uvMainAndLM.zw);
  86. #elif !defined(LIGHTMAP_ON) && (defined(PROBE_VOLUMES_L1) || defined(PROBE_VOLUMES_L2))
  87. inputData.bakedGI = SAMPLE_GI(SH,
  88. GetAbsolutePositionWS(inputData.positionWS),
  89. inputData.normalWS,
  90. inputData.viewDirectionWS,
  91. inputData.positionCS.xy,
  92. IN.probeOcclusion,
  93. inputData.shadowMask);
  94. #else
  95. inputData.bakedGI = SAMPLE_GI(IN.uvMainAndLM.zw, SH, inputData.normalWS);
  96. inputData.shadowMask = SAMPLE_SHADOWMASK(IN.uvMainAndLM.zw);
  97. #endif
  98. inputData.normalizedScreenSpaceUV = GetNormalizedScreenSpaceUV(IN.clipPos);
  99. #if defined(DEBUG_DISPLAY)
  100. #if defined(DYNAMICLIGHTMAP_ON)
  101. inputData.dynamicLightmapUV = IN.dynamicLightmapUV;
  102. #endif
  103. #if defined(LIGHTMAP_ON)
  104. inputData.staticLightmapUV = IN.uvMainAndLM.zw;
  105. #else
  106. inputData.vertexSH = SH;
  107. #endif
  108. #endif
  109. }
  110. #ifndef TERRAIN_SPLAT_BASEPASS
  111. void NormalMapMix(float4 uvSplat01, float4 uvSplat23, inout half4 splatControl, inout half3 mixedNormal)
  112. {
  113. #if defined(_NORMALMAP)
  114. half3 nrm = half(0.0);
  115. nrm += splatControl.r * UnpackNormalScale(SAMPLE_TEXTURE2D(_Normal0, sampler_Normal0, uvSplat01.xy), _NormalScale0);
  116. nrm += splatControl.g * UnpackNormalScale(SAMPLE_TEXTURE2D(_Normal1, sampler_Normal0, uvSplat01.zw), _NormalScale1);
  117. nrm += splatControl.b * UnpackNormalScale(SAMPLE_TEXTURE2D(_Normal2, sampler_Normal0, uvSplat23.xy), _NormalScale2);
  118. nrm += splatControl.a * UnpackNormalScale(SAMPLE_TEXTURE2D(_Normal3, sampler_Normal0, uvSplat23.zw), _NormalScale3);
  119. // avoid risk of NaN when normalizing.
  120. #if !HALF_IS_FLOAT
  121. nrm.z += half(0.01);
  122. #else
  123. nrm.z += 1e-5f;
  124. #endif
  125. mixedNormal = normalize(nrm.xyz);
  126. #endif
  127. }
  128. void SplatmapMix(float4 uvMainAndLM, float4 uvSplat01, float4 uvSplat23, inout half4 splatControl, out half weight, out half4 mixedDiffuse, out half4 defaultSmoothness, inout half3 mixedNormal)
  129. {
  130. half4 diffAlbedo[4];
  131. diffAlbedo[0] = SAMPLE_TEXTURE2D(_Splat0, sampler_Splat0, uvSplat01.xy);
  132. diffAlbedo[1] = SAMPLE_TEXTURE2D(_Splat1, sampler_Splat0, uvSplat01.zw);
  133. diffAlbedo[2] = SAMPLE_TEXTURE2D(_Splat2, sampler_Splat0, uvSplat23.xy);
  134. diffAlbedo[3] = SAMPLE_TEXTURE2D(_Splat3, sampler_Splat0, uvSplat23.zw);
  135. // This might be a bit of a gamble -- the assumption here is that if the diffuseMap has no
  136. // alpha channel, then diffAlbedo[n].a = 1.0 (and _DiffuseHasAlphaN = 0.0)
  137. // Prior to coming in, _SmoothnessN is actually set to max(_DiffuseHasAlphaN, _SmoothnessN)
  138. // This means that if we have an alpha channel, _SmoothnessN is locked to 1.0 and
  139. // otherwise, the true slider value is passed down and diffAlbedo[n].a == 1.0.
  140. defaultSmoothness = half4(diffAlbedo[0].a, diffAlbedo[1].a, diffAlbedo[2].a, diffAlbedo[3].a);
  141. defaultSmoothness *= half4(_Smoothness0, _Smoothness1, _Smoothness2, _Smoothness3);
  142. #ifndef _TERRAIN_BLEND_HEIGHT // density blending
  143. if(_NumLayersCount <= 4)
  144. {
  145. // 20.0 is the number of steps in inputAlphaMask (Density mask. We decided 20 empirically)
  146. half4 opacityAsDensity = saturate((half4(diffAlbedo[0].a, diffAlbedo[1].a, diffAlbedo[2].a, diffAlbedo[3].a) - (1 - splatControl)) * 20.0);
  147. opacityAsDensity += 0.001h * splatControl; // if all weights are zero, default to what the blend mask says
  148. half4 useOpacityAsDensityParam = { _DiffuseRemapScale0.w, _DiffuseRemapScale1.w, _DiffuseRemapScale2.w, _DiffuseRemapScale3.w }; // 1 is off
  149. splatControl = lerp(opacityAsDensity, splatControl, useOpacityAsDensityParam);
  150. }
  151. #endif
  152. // Now that splatControl has changed, we can compute the final weight and normalize
  153. weight = dot(splatControl, 1.0h);
  154. #ifdef TERRAIN_SPLAT_ADDPASS
  155. clip(weight <= 0.005h ? -1.0h : 1.0h);
  156. #endif
  157. #ifndef _TERRAIN_BASEMAP_GEN
  158. // Normalize weights before lighting and restore weights in final modifier functions so that the overal
  159. // lighting result can be correctly weighted.
  160. splatControl /= (weight + HALF_MIN);
  161. #endif
  162. mixedDiffuse = 0.0h;
  163. mixedDiffuse += diffAlbedo[0] * half4(_DiffuseRemapScale0.rgb * splatControl.rrr, 1.0h);
  164. mixedDiffuse += diffAlbedo[1] * half4(_DiffuseRemapScale1.rgb * splatControl.ggg, 1.0h);
  165. mixedDiffuse += diffAlbedo[2] * half4(_DiffuseRemapScale2.rgb * splatControl.bbb, 1.0h);
  166. mixedDiffuse += diffAlbedo[3] * half4(_DiffuseRemapScale3.rgb * splatControl.aaa, 1.0h);
  167. NormalMapMix(uvSplat01, uvSplat23, splatControl, mixedNormal);
  168. }
  169. #endif
  170. #ifdef _TERRAIN_BLEND_HEIGHT
  171. void HeightBasedSplatModify(inout half4 splatControl, in half4 masks[4])
  172. {
  173. // heights are in mask blue channel, we multiply by the splat Control weights to get combined height
  174. half4 splatHeight = half4(masks[0].b, masks[1].b, masks[2].b, masks[3].b) * splatControl.rgba;
  175. half maxHeight = max(splatHeight.r, max(splatHeight.g, max(splatHeight.b, splatHeight.a)));
  176. // Ensure that the transition height is not zero.
  177. half transition = max(_HeightTransition, 1e-5);
  178. // This sets the highest splat to "transition", and everything else to a lower value relative to that, clamping to zero
  179. // Then we clamp this to zero and normalize everything
  180. half4 weightedHeights = splatHeight + transition - maxHeight.xxxx;
  181. weightedHeights = max(0, weightedHeights);
  182. // We need to add an epsilon here for active layers (hence the blendMask again)
  183. // so that at least a layer shows up if everything's too low.
  184. weightedHeights = (weightedHeights + 1e-6) * splatControl;
  185. // Normalize (and clamp to epsilon to keep from dividing by zero)
  186. half sumHeight = max(dot(weightedHeights, half4(1, 1, 1, 1)), 1e-6);
  187. splatControl = weightedHeights / sumHeight.xxxx;
  188. }
  189. #endif
  190. void SplatmapFinalColor(inout half4 color, half fogCoord)
  191. {
  192. color.rgb *= color.a;
  193. #ifndef TERRAIN_GBUFFER // Technically we don't need fogCoord, but it is still passed from the vertex shader.
  194. #ifdef TERRAIN_SPLAT_ADDPASS
  195. color.rgb = MixFogColor(color.rgb, half3(0,0,0), fogCoord);
  196. #else
  197. color.rgb = MixFog(color.rgb, fogCoord);
  198. #endif
  199. #endif
  200. }
  201. void SetupTerrainDebugTextureData(inout InputData inputData, float2 uv)
  202. {
  203. #if defined(DEBUG_DISPLAY)
  204. #if defined(TERRAIN_SPLAT_ADDPASS)
  205. if (_DebugMipInfoMode != DEBUGMIPINFOMODE_NONE)
  206. {
  207. discard; // Layer 4 & beyond are done additively, doesn't make sense for the mipmap streaming debug views -> stop.
  208. }
  209. #endif
  210. switch (_DebugMipMapTerrainTextureMode)
  211. {
  212. case DEBUGMIPMAPMODETERRAINTEXTURE_CONTROL:
  213. SETUP_DEBUG_TEXTURE_DATA_FOR_TEX(inputData, TRANSFORM_TEX(uv, _Control), _Control);
  214. break;
  215. case DEBUGMIPMAPMODETERRAINTEXTURE_LAYER0:
  216. SETUP_DEBUG_TEXTURE_DATA_FOR_TEX(inputData, TRANSFORM_TEX(uv, _Splat0), _Splat0);
  217. break;
  218. case DEBUGMIPMAPMODETERRAINTEXTURE_LAYER1:
  219. SETUP_DEBUG_TEXTURE_DATA_FOR_TEX(inputData, TRANSFORM_TEX(uv, _Splat1), _Splat1);
  220. break;
  221. case DEBUGMIPMAPMODETERRAINTEXTURE_LAYER2:
  222. SETUP_DEBUG_TEXTURE_DATA_FOR_TEX(inputData, TRANSFORM_TEX(uv, _Splat2), _Splat2);
  223. break;
  224. case DEBUGMIPMAPMODETERRAINTEXTURE_LAYER3:
  225. SETUP_DEBUG_TEXTURE_DATA_FOR_TEX(inputData, TRANSFORM_TEX(uv, _Splat3), _Splat3);
  226. break;
  227. default:
  228. break;
  229. }
  230. // TERRAIN_STREAM_INFO: no streamInfo will have been set (no MeshRenderer); set status to "6" to reflect in the debug status that this is a terrain
  231. // also, set the per-material status to "4" to indicate warnings
  232. inputData.streamInfo = TERRAIN_STREAM_INFO;
  233. #endif
  234. }
  235. ///////////////////////////////////////////////////////////////////////////////
  236. // Vertex and Fragment functions //
  237. ///////////////////////////////////////////////////////////////////////////////
  238. // Used in Standard Terrain shader
  239. Varyings SplatmapVert(Attributes v)
  240. {
  241. Varyings o = (Varyings)0;
  242. UNITY_SETUP_INSTANCE_ID(v);
  243. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
  244. TerrainInstancing(v.positionOS, v.normalOS, v.texcoord);
  245. VertexPositionInputs Attributes = GetVertexPositionInputs(v.positionOS.xyz);
  246. o.uvMainAndLM.xy = v.texcoord;
  247. o.uvMainAndLM.zw = v.texcoord * unity_LightmapST.xy + unity_LightmapST.zw;
  248. #ifndef TERRAIN_SPLAT_BASEPASS
  249. o.uvSplat01.xy = TRANSFORM_TEX(v.texcoord, _Splat0);
  250. o.uvSplat01.zw = TRANSFORM_TEX(v.texcoord, _Splat1);
  251. o.uvSplat23.xy = TRANSFORM_TEX(v.texcoord, _Splat2);
  252. o.uvSplat23.zw = TRANSFORM_TEX(v.texcoord, _Splat3);
  253. #endif
  254. #if defined(DYNAMICLIGHTMAP_ON)
  255. o.dynamicLightmapUV = v.texcoord * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;
  256. #endif
  257. #if defined(_NORMALMAP) && !defined(ENABLE_TERRAIN_PERPIXEL_NORMAL)
  258. half3 viewDirWS = GetWorldSpaceNormalizeViewDir(Attributes.positionWS);
  259. float4 vertexTangent = float4(cross(float3(0, 0, 1), v.normalOS), 1.0);
  260. VertexNormalInputs normalInput = GetVertexNormalInputs(v.normalOS, vertexTangent);
  261. o.normal = half4(normalInput.normalWS, viewDirWS.x);
  262. o.tangent = half4(normalInput.tangentWS, viewDirWS.y);
  263. o.bitangent = half4(normalInput.bitangentWS, viewDirWS.z);
  264. #else
  265. o.normal = TransformObjectToWorldNormal(v.normalOS);
  266. OUTPUT_SH4(Attributes.positionWS, o.normal.xyz, GetWorldSpaceNormalizeViewDir(Attributes.positionWS), o.vertexSH, o.probeOcclusion);
  267. #endif
  268. half fogFactor = 0;
  269. #if !defined(_FOG_FRAGMENT)
  270. fogFactor = ComputeFogFactor(Attributes.positionCS.z);
  271. #endif
  272. #ifdef _ADDITIONAL_LIGHTS_VERTEX
  273. o.fogFactorAndVertexLight.x = fogFactor;
  274. o.fogFactorAndVertexLight.yzw = VertexLighting(Attributes.positionWS, o.normal.xyz);
  275. #else
  276. o.fogFactor = fogFactor;
  277. #endif
  278. o.positionWS = Attributes.positionWS;
  279. o.clipPos = Attributes.positionCS;
  280. #if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
  281. o.shadowCoord = GetShadowCoord(Attributes);
  282. #endif
  283. return o;
  284. }
  285. void ComputeMasks(out half4 masks[4], half4 hasMask, Varyings IN)
  286. {
  287. masks[0] = 0.5h;
  288. masks[1] = 0.5h;
  289. masks[2] = 0.5h;
  290. masks[3] = 0.5h;
  291. #ifdef _MASKMAP
  292. masks[0] = lerp(masks[0], SAMPLE_TEXTURE2D(_Mask0, sampler_Mask0, IN.uvSplat01.xy), hasMask.x);
  293. masks[1] = lerp(masks[1], SAMPLE_TEXTURE2D(_Mask1, sampler_Mask0, IN.uvSplat01.zw), hasMask.y);
  294. masks[2] = lerp(masks[2], SAMPLE_TEXTURE2D(_Mask2, sampler_Mask0, IN.uvSplat23.xy), hasMask.z);
  295. masks[3] = lerp(masks[3], SAMPLE_TEXTURE2D(_Mask3, sampler_Mask0, IN.uvSplat23.zw), hasMask.w);
  296. #endif
  297. masks[0] *= _MaskMapRemapScale0.rgba;
  298. masks[0] += _MaskMapRemapOffset0.rgba;
  299. masks[1] *= _MaskMapRemapScale1.rgba;
  300. masks[1] += _MaskMapRemapOffset1.rgba;
  301. masks[2] *= _MaskMapRemapScale2.rgba;
  302. masks[2] += _MaskMapRemapOffset2.rgba;
  303. masks[3] *= _MaskMapRemapScale3.rgba;
  304. masks[3] += _MaskMapRemapOffset3.rgba;
  305. }
  306. // Used in Standard Terrain shader
  307. #ifdef TERRAIN_GBUFFER
  308. FragmentOutput SplatmapFragment(Varyings IN)
  309. #else
  310. void SplatmapFragment(
  311. Varyings IN
  312. , out half4 outColor : SV_Target0
  313. #ifdef _WRITE_RENDERING_LAYERS
  314. , out float4 outRenderingLayers : SV_Target1
  315. #endif
  316. )
  317. #endif
  318. {
  319. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(IN);
  320. #ifdef _ALPHATEST_ON
  321. ClipHoles(IN.uvMainAndLM.xy);
  322. #endif
  323. half3 normalTS = half3(0.0h, 0.0h, 1.0h);
  324. #ifdef TERRAIN_SPLAT_BASEPASS
  325. half3 albedo = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, IN.uvMainAndLM.xy).rgb;
  326. half smoothness = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, IN.uvMainAndLM.xy).a;
  327. half metallic = SAMPLE_TEXTURE2D(_MetallicTex, sampler_MetallicTex, IN.uvMainAndLM.xy).r;
  328. half alpha = 1;
  329. half occlusion = 1;
  330. #else
  331. half4 hasMask = half4(_LayerHasMask0, _LayerHasMask1, _LayerHasMask2, _LayerHasMask3);
  332. half4 masks[4];
  333. ComputeMasks(masks, hasMask, IN);
  334. float2 splatUV = (IN.uvMainAndLM.xy * (_Control_TexelSize.zw - 1.0f) + 0.5f) * _Control_TexelSize.xy;
  335. half4 splatControl = SAMPLE_TEXTURE2D(_Control, sampler_Control, splatUV);
  336. half alpha = dot(splatControl, 1.0h);
  337. #ifdef _TERRAIN_BLEND_HEIGHT
  338. // disable Height Based blend when there are more than 4 layers (multi-pass breaks the normalization)
  339. if (_NumLayersCount <= 4)
  340. HeightBasedSplatModify(splatControl, masks);
  341. #endif
  342. half weight;
  343. half4 mixedDiffuse;
  344. half4 defaultSmoothness;
  345. SplatmapMix(IN.uvMainAndLM, IN.uvSplat01, IN.uvSplat23, splatControl, weight, mixedDiffuse, defaultSmoothness, normalTS);
  346. half3 albedo = mixedDiffuse.rgb;
  347. half4 defaultMetallic = half4(_Metallic0, _Metallic1, _Metallic2, _Metallic3);
  348. half4 defaultOcclusion = half4(_MaskMapRemapScale0.g, _MaskMapRemapScale1.g, _MaskMapRemapScale2.g, _MaskMapRemapScale3.g) +
  349. half4(_MaskMapRemapOffset0.g, _MaskMapRemapOffset1.g, _MaskMapRemapOffset2.g, _MaskMapRemapOffset3.g);
  350. half4 maskSmoothness = half4(masks[0].a, masks[1].a, masks[2].a, masks[3].a);
  351. defaultSmoothness = lerp(defaultSmoothness, maskSmoothness, hasMask);
  352. half smoothness = dot(splatControl, defaultSmoothness);
  353. half4 maskMetallic = half4(masks[0].r, masks[1].r, masks[2].r, masks[3].r);
  354. defaultMetallic = lerp(defaultMetallic, maskMetallic, hasMask);
  355. half metallic = dot(splatControl, defaultMetallic);
  356. half4 maskOcclusion = half4(masks[0].g, masks[1].g, masks[2].g, masks[3].g);
  357. defaultOcclusion = lerp(defaultOcclusion, maskOcclusion, hasMask);
  358. half occlusion = dot(splatControl, defaultOcclusion);
  359. #endif
  360. InputData inputData;
  361. InitializeInputData(IN, normalTS, inputData);
  362. SetupTerrainDebugTextureData(inputData, IN.uvMainAndLM.xy);
  363. #if defined(_DBUFFER)
  364. half3 specular = half3(0.0h, 0.0h, 0.0h);
  365. ApplyDecal(IN.clipPos,
  366. albedo,
  367. specular,
  368. inputData.normalWS,
  369. metallic,
  370. occlusion,
  371. smoothness);
  372. #endif
  373. #ifdef TERRAIN_GBUFFER
  374. BRDFData brdfData;
  375. InitializeBRDFData(albedo, metallic, /* specular */ half3(0.0h, 0.0h, 0.0h), smoothness, alpha, brdfData);
  376. // Baked lighting.
  377. half4 color;
  378. Light mainLight = GetMainLight(inputData.shadowCoord, inputData.positionWS, inputData.shadowMask);
  379. MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI, inputData.shadowMask);
  380. color.rgb = GlobalIllumination(brdfData, inputData.bakedGI, occlusion, inputData.positionWS, inputData.normalWS, inputData.viewDirectionWS);
  381. color.a = alpha;
  382. SplatmapFinalColor(color, inputData.fogCoord);
  383. // Dynamic lighting: emulate SplatmapFinalColor() by scaling gbuffer material properties. This will not give the same results
  384. // as forward renderer because we apply blending pre-lighting instead of post-lighting.
  385. // Blending of smoothness and normals is also not correct but close enough?
  386. brdfData.albedo.rgb *= alpha;
  387. brdfData.diffuse.rgb *= alpha;
  388. brdfData.specular.rgb *= alpha;
  389. brdfData.reflectivity *= alpha;
  390. inputData.normalWS = inputData.normalWS * alpha;
  391. smoothness *= alpha;
  392. return BRDFDataToGbuffer(brdfData, inputData, smoothness, color.rgb, occlusion);
  393. #else
  394. half4 color = UniversalFragmentPBR(inputData, albedo, metallic, /* specular */ half3(0.0h, 0.0h, 0.0h), smoothness, occlusion, /* emission */ half3(0, 0, 0), alpha);
  395. SplatmapFinalColor(color, inputData.fogCoord);
  396. outColor = half4(color.rgb, 1.0h);
  397. #ifdef _WRITE_RENDERING_LAYERS
  398. uint renderingLayers = GetMeshRenderingLayer();
  399. outRenderingLayers = float4(EncodeMeshRenderingLayer(renderingLayers), 0, 0, 0);
  400. #endif
  401. #endif
  402. }
  403. // Shadow pass
  404. // Shadow Casting Light geometric parameters. These variables are used when applying the shadow Normal Bias and are set by UnityEngine.Rendering.Universal.ShadowUtils.SetupShadowCasterConstantBuffer in com.unity.render-pipelines.universal/Runtime/ShadowUtils.cs
  405. // For Directional lights, _LightDirection is used when applying shadow Normal Bias.
  406. // For Spot lights and Point lights, _LightPosition is used to compute the actual light direction because it is different at each shadow caster geometry vertex.
  407. float3 _LightDirection;
  408. float3 _LightPosition;
  409. struct AttributesLean
  410. {
  411. float4 position : POSITION;
  412. float3 normalOS : NORMAL;
  413. float2 texcoord : TEXCOORD0;
  414. UNITY_VERTEX_INPUT_INSTANCE_ID
  415. };
  416. struct VaryingsLean
  417. {
  418. float4 clipPos : SV_POSITION;
  419. float2 texcoord : TEXCOORD0;
  420. UNITY_VERTEX_OUTPUT_STEREO
  421. };
  422. VaryingsLean ShadowPassVertex(AttributesLean v)
  423. {
  424. VaryingsLean o = (VaryingsLean)0;
  425. UNITY_SETUP_INSTANCE_ID(v);
  426. TerrainInstancing(v.position, v.normalOS, v.texcoord);
  427. float3 positionWS = TransformObjectToWorld(v.position.xyz);
  428. float3 normalWS = TransformObjectToWorldNormal(v.normalOS);
  429. #if _CASTING_PUNCTUAL_LIGHT_SHADOW
  430. float3 lightDirectionWS = normalize(_LightPosition - positionWS);
  431. #else
  432. float3 lightDirectionWS = _LightDirection;
  433. #endif
  434. float4 clipPos = TransformWorldToHClip(ApplyShadowBias(positionWS, normalWS, lightDirectionWS));
  435. #if UNITY_REVERSED_Z
  436. clipPos.z = min(clipPos.z, UNITY_NEAR_CLIP_VALUE);
  437. #else
  438. clipPos.z = max(clipPos.z, UNITY_NEAR_CLIP_VALUE);
  439. #endif
  440. o.clipPos = clipPos;
  441. o.texcoord = v.texcoord;
  442. return o;
  443. }
  444. half4 ShadowPassFragment(VaryingsLean IN) : SV_TARGET
  445. {
  446. #ifdef _ALPHATEST_ON
  447. ClipHoles(IN.texcoord);
  448. #endif
  449. return 0;
  450. }
  451. // Depth pass
  452. VaryingsLean DepthOnlyVertex(AttributesLean v)
  453. {
  454. VaryingsLean o = (VaryingsLean)0;
  455. UNITY_SETUP_INSTANCE_ID(v);
  456. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
  457. TerrainInstancing(v.position, v.normalOS);
  458. o.clipPos = TransformObjectToHClip(v.position.xyz);
  459. o.texcoord = v.texcoord;
  460. return o;
  461. }
  462. half4 DepthOnlyFragment(VaryingsLean IN) : SV_TARGET
  463. {
  464. #ifdef _ALPHATEST_ON
  465. ClipHoles(IN.texcoord);
  466. #endif
  467. #ifdef SCENESELECTIONPASS
  468. // We use depth prepass for scene selection in the editor, this code allow to output the outline correctly
  469. return half4(_ObjectId, _PassValue, 1.0, 1.0);
  470. #endif
  471. return IN.clipPos.z;
  472. }
  473. #endif