TerrainLitPasses.hlsl 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844
  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. #if defined(UNITY_INSTANCING_ENABLED) && defined(_TERRAIN_INSTANCED_PERPIXEL_NORMAL)
  5. #define ENABLE_TERRAIN_PERPIXEL_NORMAL
  6. #endif
  7. #ifdef UNITY_INSTANCING_ENABLED
  8. TEXTURE2D(_TerrainHeightmapTexture);
  9. TEXTURE2D(_TerrainNormalmapTexture);
  10. SAMPLER(sampler_TerrainNormalmapTexture);
  11. float4 _TerrainHeightmapRecipSize; // float4(1.0f/width, 1.0f/height, 1.0f/(width-1), 1.0f/(height-1))
  12. float4 _TerrainHeightmapScale; // float4(hmScale.x, hmScale.y / (float)(kMaxHeight), hmScale.z, 0.0f)
  13. #endif
  14. UNITY_INSTANCING_BUFFER_START(Terrain)
  15. UNITY_DEFINE_INSTANCED_PROP(float4, _TerrainPatchInstanceData) // float4(xBase, yBase, skipScale, ~)
  16. UNITY_INSTANCING_BUFFER_END(Terrain)
  17. #ifdef _ALPHATEST_ON
  18. // Already defined in TerrainLitinput.hlsl
  19. // TEXTURE2D(_TerrainHolesTexture);
  20. // SAMPLER(sampler_TerrainHolesTexture);
  21. void ClipHoles(float2 uv)
  22. {
  23. float hole = SAMPLE_TEXTURE2D(_TerrainHolesTexture, sampler_TerrainHolesTexture, uv).r;
  24. clip(hole == 0.0f ? -1 : 1);
  25. }
  26. #endif
  27. struct Attributes
  28. {
  29. float4 positionOS : POSITION;
  30. float3 normalOS : NORMAL;
  31. float2 texcoord : TEXCOORD0;
  32. UNITY_VERTEX_INPUT_INSTANCE_ID
  33. };
  34. struct Varyings
  35. {
  36. float4 uvMainAndLM : TEXCOORD0; // xy: control, zw: lightmap
  37. #ifndef TERRAIN_SPLAT_BASEPASS
  38. float4 uvSplat01 : TEXCOORD1; // xy: splat0, zw: splat1
  39. float4 uvSplat23 : TEXCOORD2; // xy: splat2, zw: splat3
  40. #endif
  41. #if ( defined(_NORMALMAP) || defined(_PARALLAX) ) && !defined(ENABLE_TERRAIN_PERPIXEL_NORMAL)
  42. float3 normal : TEXCOORD3; // xyz: normal, w: viewDir.x
  43. float4 tangent : TEXCOORD4; // xyz: tangent, w: viewDir.y
  44. float3 viewDir : TEXCOORD5;
  45. #else
  46. float3 normal : TEXCOORD3;
  47. float3 viewDir : TEXCOORD4;
  48. half3 vertexSH : TEXCOORD5; // SH
  49. #endif
  50. half4 fogFactorAndVertexLight : TEXCOORD6; // x: fogFactor, yzw: vertex light
  51. float3 positionWS : TEXCOORD7;
  52. #if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
  53. float4 shadowCoord : TEXCOORD8;
  54. #endif
  55. float4 clipPos : SV_POSITION;
  56. UNITY_VERTEX_INPUT_INSTANCE_ID
  57. UNITY_VERTEX_OUTPUT_STEREO
  58. };
  59. // -----------------------------------------------------------------------------------------------
  60. // Procedural Mapping
  61. real Lux_Luminance(real3 linearRgb) {
  62. return dot(linearRgb, real3(0.2126729, 0.7151522, 0.0721750));
  63. }
  64. void GetProceduralBaseSample(
  65. Texture2D sampleTex, SamplerState samplerTex, float2 uv,
  66. #ifdef _TERRAIN_BLEND_HEIGHT
  67. inout half result,
  68. #else
  69. inout half4 result,
  70. #endif
  71. inout float2 uv1, inout float2 uv2, inout float2 uv3,
  72. inout half w1, inout half w2, inout half w3, inout float2 duvdx, inout float2 duvdy)
  73. {
  74. float2 uvScaled = uv * 3.464 * _ProceduralScale;
  75. const float2x2 gridToSkewedGrid = float2x2(1.0, 0.0, -0.57735027, 1.15470054);
  76. float2 skewedCoord = mul(gridToSkewedGrid, uvScaled);
  77. int2 baseId = int2(floor(skewedCoord));
  78. float3 temp = float3(frac(skewedCoord), 0);
  79. temp.z = 1.0 - temp.x - temp.y;
  80. int2 vertex1, vertex2, vertex3;
  81. if (temp.z > 0.0) {
  82. w1 = temp.z;
  83. w2 = temp.y;
  84. w3 = temp.x;
  85. vertex1 = baseId;
  86. vertex2 = baseId + int2(0, 1);
  87. vertex3 = baseId + int2(1, 0);
  88. }
  89. else {
  90. w1 = -temp.z;
  91. w2 = 1.0 - temp.y;
  92. w3 = 1.0 - temp.x;
  93. vertex1 = baseId + int2(1, 1);
  94. vertex2 = baseId + int2(1, 0);
  95. vertex3 = baseId + int2(0, 1);
  96. }
  97. const float2x2 hashMatrix = float2x2(127.1, 311.7, 269.5, 183.3);
  98. const float hashFactor = 3758.5453;
  99. uv1 = uv + frac(sin(mul(hashMatrix, (float2)vertex1)) * hashFactor);
  100. uv2 = uv + frac(sin(mul(hashMatrix, (float2)vertex2)) * hashFactor);
  101. uv3 = uv + frac(sin(mul(hashMatrix, (float2)vertex3)) * hashFactor);
  102. // Use a hash function which does not include sin
  103. // Adds a little bit visible tiling...
  104. // float2 uv1 = uv + hash22( (float2)vertex1 );
  105. // float2 uv2 = uv + hash22( (float2)vertex2 );
  106. // float2 uv3 = uv + hash22( (float2)vertex3 );
  107. duvdx = ddx(uv);
  108. duvdy = ddy(uv);
  109. // Here we have to sample first as we want to calculate the wights based on luminance
  110. // Albedo – Sample Gaussion values from transformed input
  111. #ifdef _TERRAIN_BLEND_HEIGHT
  112. half G1 = SAMPLE_TEXTURE2D_GRAD(sampleTex, samplerTex, uv1, duvdx, duvdy).r;
  113. half G2 = SAMPLE_TEXTURE2D_GRAD(sampleTex, samplerTex, uv2, duvdx, duvdy).r;
  114. half G3 = SAMPLE_TEXTURE2D_GRAD(sampleTex, samplerTex, uv3, duvdx, duvdy).r;
  115. // Weight by Height - somehow
  116. w1 *= G1;
  117. w2 *= G2;
  118. w3 *= G3;
  119. #else
  120. half4 G1 = SAMPLE_TEXTURE2D_GRAD(sampleTex, samplerTex, uv1, duvdx, duvdy);
  121. half4 G2 = SAMPLE_TEXTURE2D_GRAD(sampleTex, samplerTex, uv2, duvdx, duvdy);
  122. half4 G3 = SAMPLE_TEXTURE2D_GRAD(sampleTex, samplerTex, uv3, duvdx, duvdy);
  123. // Weight by Luminance
  124. w1 *= Lux_Luminance(G1.rgb);
  125. w2 *= Lux_Luminance(G2.rgb);
  126. w3 *= Lux_Luminance(G3.rgb);
  127. #endif
  128. // Get weights
  129. half exponent = 1.0h + _ProceduralBlend * 15.0h;
  130. w1 = pow(w1, exponent);
  131. w2 = pow(w2, exponent);
  132. w3 = pow(w3, exponent);
  133. // Lets help the compiler here:
  134. half sum = 1.0h / (w1 + w2 + w3);
  135. w1 = w1 * sum;
  136. w2 = w2 * sum;
  137. w3 = w3 * sum;
  138. // Result
  139. result = w1 * G1 + w2 * G2 + w3 * G3;
  140. }
  141. half4 sampleProcedural(Texture2D sampleTex, SamplerState samplerTex, float2 uv, float2 uv1, float2 uv2, float2 uv3, half w1, half w2, half w3, float2 duvdx, float2 duvdy) {
  142. half4 G1 = SAMPLE_TEXTURE2D_GRAD(sampleTex, samplerTex, uv1, duvdx, duvdy);
  143. half4 G2 = SAMPLE_TEXTURE2D_GRAD(sampleTex, samplerTex, uv2, duvdx, duvdy);
  144. half4 G3 = SAMPLE_TEXTURE2D_GRAD(sampleTex, samplerTex, uv3, duvdx, duvdy);
  145. return w1 * G1 + w2 * G2 + w3 * G3;
  146. }
  147. half1 sampleProceduralHalf(Texture2D sampleTex, SamplerState samplerTex, float2 uv, float2 uv1, float2 uv2, float2 uv3, half w1, half w2, half w3, float2 duvdx, float2 duvdy) {
  148. half G1 = SAMPLE_TEXTURE2D_GRAD(sampleTex, samplerTex, uv1, duvdx, duvdy).r;
  149. half G2 = SAMPLE_TEXTURE2D_GRAD(sampleTex, samplerTex, uv2, duvdx, duvdy).r;
  150. half G3 = SAMPLE_TEXTURE2D_GRAD(sampleTex, samplerTex, uv3, duvdx, duvdy).r;
  151. return w1 * G1 + w2 * G2 + w3 * G3;
  152. }
  153. // -----------------------------------------------------------------------------------------------
  154. // ---------------------------
  155. void InitializeInputData(Varyings IN, half3 normalTS, half3x3 tangentSpaceRotation, half3 viewDirWS, out InputData input)
  156. {
  157. input = (InputData)0;
  158. input.positionWS = IN.positionWS;
  159. half3 SH = half3(0, 0, 0);
  160. // Most of this is passed in
  161. /*
  162. #if ( defined(_NORMALMAP) || defined (_PARALLAX) ) && !defined(ENABLE_TERRAIN_PERPIXEL_NORMAL)
  163. //half3 viewDirWS = half3(IN.normal.w, IN.tangent.w, IN.bitangent.w);
  164. half3 viewDirWS = IN.viewDir;
  165. float sgn = input.tangentWS.w; // should be either +1 or -1
  166. float3 bitangent = sgn * cross(IN.normalWS.xyz, IN.tangentWS.xyz);
  167. input.normalWS = TransformTangentToWorld(normalTS, half3x3(IN.tangent.xyz, bitangent, IN.normal.xyz));
  168. SH = SampleSH(input.normalWS.xyz);
  169. #elif defined(ENABLE_TERRAIN_PERPIXEL_NORMAL)
  170. half3 viewDirWS = IN.viewDir;
  171. float2 sampleCoords = (IN.uvMainAndLM.xy / _TerrainHeightmapRecipSize.zw + 0.5f) * _TerrainHeightmapRecipSize.xy;
  172. half3 normalWS = TransformObjectToWorldNormal(normalize(SAMPLE_TEXTURE2D(_TerrainNormalmapTexture, sampler_TerrainNormalmapTexture, sampleCoords).rgb * 2 - 1));
  173. // fix orientation
  174. half3 tangentWS = cross(GetObjectToWorldMatrix()._13_23_33, normalWS) * -1;
  175. input.normalWS = TransformTangentToWorld(normalTS, half3x3(tangentWS, -cross(normalWS, tangentWS), normalWS));
  176. SH = SampleSH(input.normalWS.xyz);
  177. #else
  178. half3 viewDirWS = IN.viewDir;
  179. input.normalWS = IN.normal;
  180. SH = IN.vertexSH;
  181. #endif
  182. #if SHADER_HINT_NICE_QUALITY
  183. viewDirWS = SafeNormalize(viewDirWS);
  184. #endif
  185. */
  186. // So this is all that has to be done
  187. #if defined(_NORMALMAP) || defined (_PARALLAX) || defined(ENABLE_TERRAIN_PERPIXEL_NORMAL)
  188. input.normalWS = TransformTangentToWorld(normalTS, tangentSpaceRotation);
  189. SH = SampleSH(input.normalWS.xyz);
  190. #else
  191. input.normalWS = IN.normal;
  192. SH = IN.vertexSH;
  193. #endif
  194. input.normalWS = NormalizeNormalPerPixel(input.normalWS);
  195. input.viewDirectionWS = viewDirWS;
  196. #if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
  197. input.shadowCoord = IN.shadowCoord;
  198. #elif defined(MAIN_LIGHT_CALCULATE_SHADOWS)
  199. input.shadowCoord = TransformWorldToShadowCoord(input.positionWS);
  200. #else
  201. input.shadowCoord = float4(0, 0, 0, 0);
  202. #endif
  203. input.fogCoord = IN.fogFactorAndVertexLight.x;
  204. input.vertexLighting = IN.fogFactorAndVertexLight.yzw;
  205. input.bakedGI = SAMPLE_GI(IN.uvMainAndLM.zw, SH, input.normalWS);
  206. //input.normalizedScreenSpaceUV = IN.clipPos.xy;
  207. input.normalizedScreenSpaceUV = GetNormalizedScreenSpaceUV(IN.clipPos.xy);
  208. input.shadowMask = SAMPLE_SHADOWMASK(IN.uvMainAndLM.zw);
  209. }
  210. #ifdef _TERRAIN_BLEND_HEIGHT
  211. void HeightBasedSplatModifyCombined(inout half4 splatControl, in half4 heights, inout half height) {
  212. #ifndef TERRAIN_SPLAT_ADDPASS // disable for multi-pass
  213. half4 defaultHeight = heights;
  214. half4 mweights = splatControl * max(defaultHeight, 1e-5);
  215. // Go parallel
  216. half maxWeight = max( max(mweights.x, mweights.y), max(mweights.z, mweights.w) );
  217. half mtransition = max(_HeightTransition * maxWeight, 1e-5);
  218. half mthreshold = maxWeight - mtransition;
  219. half mscale = 1.0h / mtransition;
  220. mweights = saturate((mweights - mthreshold ) / mtransition); // * mscale );
  221. half sumHeight = mweights.x + mweights.y + mweights.z + mweights.w;
  222. half sumSplat = splatControl.x+splatControl.y+splatControl.z+splatControl.w;
  223. splatControl = mweights / sumHeight;
  224. // Must not get more than before...
  225. splatControl *= sumSplat;
  226. height = maxWeight;
  227. #endif
  228. }
  229. #endif
  230. // Splatting ----------------------------------------------
  231. #ifndef TERRAIN_SPLAT_BASEPASS
  232. void SplatmapMix(float4 uvMainAndLM, float4 uvSplat01, float4 uvSplat23, inout half4 splatControl, out half weight, out half4 mixedDiffuse, out half4 defaultSmoothness, inout half3 mixedNormal)
  233. {
  234. // Sample albedo and smoothness
  235. half4 diffAlbedo[4];
  236. // We may use procedural texturing but do not use height based blending
  237. #if defined(_PROCEDURALTEXTURING) && !defined(_TERRAIN_BLEND_HEIGHT)
  238. half4 diffAlbedoNull;
  239. float2 uv1, uv2, uv3;
  240. half w1, w2, w3;
  241. float2 duvdx, duvdy;
  242. GetProceduralBaseSample(_Splat0, sampler_Splat0, uvSplat01.xy, diffAlbedoNull, uv1, uv2, uv3, w1, w2, w3, duvdx, duvdy);
  243. diffAlbedo[0] = diffAlbedoNull;
  244. #else
  245. diffAlbedo[0] = SAMPLE_TEXTURE2D(_Splat0, sampler_Splat0, uvSplat01.xy);
  246. #endif
  247. diffAlbedo[1] = SAMPLE_TEXTURE2D(_Splat1, sampler_Splat0, uvSplat01.zw);
  248. diffAlbedo[2] = SAMPLE_TEXTURE2D(_Splat2, sampler_Splat0, uvSplat23.xy);
  249. diffAlbedo[3] = SAMPLE_TEXTURE2D(_Splat3, sampler_Splat0, uvSplat23.zw);
  250. defaultSmoothness = half4(diffAlbedo[0].a, diffAlbedo[1].a, diffAlbedo[2].a, diffAlbedo[3].a);
  251. defaultSmoothness *= half4(_Smoothness0, _Smoothness1, _Smoothness2, _Smoothness3);
  252. // Now that splatControl has changed, we can compute the final weight and normalize
  253. weight = dot(splatControl, 1.0h);
  254. #ifdef TERRAIN_SPLAT_ADDPASS
  255. clip(weight <= 0.005h ? -1.0h : 1.0h);
  256. #endif
  257. #ifndef _TERRAIN_BASEMAP_GEN
  258. // Normalize weights before lighting and restore weights in final modifier functions so that the overal
  259. // lighting result can be correctly weighted.
  260. splatControl /= (weight + HALF_MIN);
  261. #endif
  262. mixedDiffuse = 0.0h;
  263. mixedDiffuse += diffAlbedo[0] * half4(_DiffuseRemapScale0.rgb * splatControl.rrr, 1.0h);
  264. mixedDiffuse += diffAlbedo[1] * half4(_DiffuseRemapScale1.rgb * splatControl.ggg, 1.0h);
  265. mixedDiffuse += diffAlbedo[2] * half4(_DiffuseRemapScale2.rgb * splatControl.bbb, 1.0h);
  266. mixedDiffuse += diffAlbedo[3] * half4(_DiffuseRemapScale3.rgb * splatControl.aaa, 1.0h);
  267. #ifdef _NORMALMAP
  268. half4 normalSamples[4];
  269. #if defined(_PROCEDURALTEXTURING) && !defined(_TERRAIN_BLEND_HEIGHT)
  270. normalSamples[0] = sampleProcedural(_Normal0, sampler_Normal0, uvSplat01.xy, uv1, uv2, uv3, w1, w2, w3, duvdx, duvdy);
  271. #else
  272. normalSamples[0] = SAMPLE_TEXTURE2D(_Normal0, sampler_Normal0, uvSplat01.xy);
  273. #endif
  274. normalSamples[1] = SAMPLE_TEXTURE2D(_Normal1, sampler_Normal0, uvSplat01.zw);
  275. normalSamples[2] = SAMPLE_TEXTURE2D(_Normal2, sampler_Normal0, uvSplat23.xy);
  276. normalSamples[3] = SAMPLE_TEXTURE2D(_Normal3, sampler_Normal0, uvSplat23.zw);
  277. half4 normalSample = 0;
  278. normalSample = splatControl.r * normalSamples[0];
  279. normalSample += splatControl.g * normalSamples[1];
  280. normalSample += splatControl.b * normalSamples[2];
  281. normalSample += splatControl.a * normalSamples[3];
  282. half3 nrm = 0.0f;
  283. #if BUMP_SCALE_NOT_SUPPORTED
  284. nrm = UnpackNormal(normalSample);
  285. #else
  286. half normalScale = dot(half4(_NormalScale0, _NormalScale1, _NormalScale2, _NormalScale3), splatControl);
  287. nrm = UnpackNormalScale(normalSample, normalScale);
  288. #endif
  289. // avoid risk of NaN when normalizing.
  290. #if HAS_HALF
  291. nrm.z += 0.01h;
  292. #else
  293. nrm.z += 1e-5f;
  294. #endif
  295. mixedNormal = normalize(nrm.xyz);
  296. #endif
  297. //mixedDiffuse = height.xxxx;
  298. }
  299. void SplatmapMixProcedural(float4 uvMainAndLM, float4 uvSplat01, float4 uvSplat23, inout half4 splatControl, out half weight, out half4 mixedDiffuse, out half4 defaultSmoothness, inout half3 mixedNormal,
  300. float2 uv1, float2 uv2, float2 uv3, half w1, half w2, half w3, float2 duvdx, float2 duvdy)
  301. {
  302. // Sample albedo and smoothness
  303. half4 diffAlbedo[4];
  304. diffAlbedo[0] = sampleProcedural(_Splat0, sampler_Splat0, uvSplat01.xy, uv1, uv2, uv3, w1, w2, w3, duvdx, duvdy);
  305. diffAlbedo[1] = SAMPLE_TEXTURE2D(_Splat1, sampler_Splat0, uvSplat01.zw);
  306. diffAlbedo[2] = SAMPLE_TEXTURE2D(_Splat2, sampler_Splat0, uvSplat23.xy);
  307. diffAlbedo[3] = SAMPLE_TEXTURE2D(_Splat3, sampler_Splat0, uvSplat23.zw);
  308. defaultSmoothness = half4(diffAlbedo[0].a, diffAlbedo[1].a, diffAlbedo[2].a, diffAlbedo[3].a);
  309. defaultSmoothness *= half4(_Smoothness0, _Smoothness1, _Smoothness2, _Smoothness3);
  310. // Now that splatControl has changed, we can compute the final weight and normalize
  311. weight = dot(splatControl, 1.0h);
  312. #ifdef TERRAIN_SPLAT_ADDPASS
  313. clip(weight <= 0.005h ? -1.0h : 1.0h);
  314. #endif
  315. #ifndef _TERRAIN_BASEMAP_GEN
  316. // Normalize weights before lighting and restore weights in final modifier functions so that the overal
  317. // lighting result can be correctly weighted.
  318. splatControl /= (weight + HALF_MIN);
  319. #endif
  320. mixedDiffuse = 0.0h;
  321. mixedDiffuse += diffAlbedo[0] * half4(_DiffuseRemapScale0.rgb * splatControl.rrr, 1.0h);
  322. mixedDiffuse += diffAlbedo[1] * half4(_DiffuseRemapScale1.rgb * splatControl.ggg, 1.0h);
  323. mixedDiffuse += diffAlbedo[2] * half4(_DiffuseRemapScale2.rgb * splatControl.bbb, 1.0h);
  324. mixedDiffuse += diffAlbedo[3] * half4(_DiffuseRemapScale3.rgb * splatControl.aaa, 1.0h);
  325. #ifdef _NORMALMAP
  326. half4 normalSamples[4];
  327. normalSamples[0] = sampleProcedural(_Normal0, sampler_Normal0, uvSplat01.xy, uv1, uv2, uv3, w1, w2, w3, duvdx, duvdy);
  328. normalSamples[1] = SAMPLE_TEXTURE2D(_Normal1, sampler_Normal0, uvSplat01.zw);
  329. normalSamples[2] = SAMPLE_TEXTURE2D(_Normal2, sampler_Normal0, uvSplat23.xy);
  330. normalSamples[3] = SAMPLE_TEXTURE2D(_Normal3, sampler_Normal0, uvSplat23.zw);
  331. half4 normalSample = 0;
  332. normalSample = splatControl.r * normalSamples[0];
  333. normalSample += splatControl.g * normalSamples[1];
  334. normalSample += splatControl.b * normalSamples[2];
  335. normalSample += splatControl.a * normalSamples[3];
  336. half3 nrm = 0.0f;
  337. #if BUMP_SCALE_NOT_SUPPORTED
  338. nrm = UnpackNormal(normalSample);
  339. #else
  340. half normalScale = dot(half4(_NormalScale0, _NormalScale1, _NormalScale2, _NormalScale3), splatControl);
  341. nrm = UnpackNormalScale(normalSample, normalScale);
  342. #endif
  343. // avoid risk of NaN when normalizing.
  344. #if HAS_HALF
  345. nrm.z += 0.01h;
  346. #else
  347. nrm.z += 1e-5f;
  348. #endif
  349. mixedNormal = normalize(nrm.xyz);
  350. #endif
  351. }
  352. #endif
  353. void SplatmapFinalColor(inout half4 color, half fogCoord)
  354. {
  355. color.rgb *= color.a;
  356. #ifdef TERRAIN_SPLAT_ADDPASS
  357. color.rgb = MixFogColor(color.rgb, half3(0,0,0), fogCoord);
  358. #else
  359. color.rgb = MixFog(color.rgb, fogCoord);
  360. #endif
  361. }
  362. void TerrainInstancing(inout float4 positionOS, inout float3 normal, inout float2 uv)
  363. {
  364. #ifdef UNITY_INSTANCING_ENABLED
  365. float2 patchVertex = positionOS.xy;
  366. float4 instanceData = UNITY_ACCESS_INSTANCED_PROP(Terrain, _TerrainPatchInstanceData);
  367. float2 sampleCoords = (patchVertex.xy + instanceData.xy) * instanceData.z;
  368. float height = UnpackHeightmap(_TerrainHeightmapTexture.Load(int3(sampleCoords, 0)));
  369. positionOS.xz = sampleCoords * _TerrainHeightmapScale.xz;
  370. positionOS.y = height * _TerrainHeightmapScale.y;
  371. #ifdef ENABLE_TERRAIN_PERPIXEL_NORMAL
  372. normal = float3(0, 1, 0);
  373. #else
  374. normal = _TerrainNormalmapTexture.Load(int3(sampleCoords, 0)).rgb * 2 - 1;
  375. #endif
  376. uv = sampleCoords * _TerrainHeightmapRecipSize.zw;
  377. #endif
  378. }
  379. void TerrainInstancing(inout float4 positionOS, inout float3 normal)
  380. {
  381. float2 uv = { 0, 0 };
  382. TerrainInstancing(positionOS, normal, uv);
  383. }
  384. ///////////////////////////////////////////////////////////////////////////////
  385. // Vertex and Fragment functions //
  386. ///////////////////////////////////////////////////////////////////////////////
  387. // Used in Standard Terrain shader
  388. Varyings SplatmapVert(Attributes v)
  389. {
  390. Varyings o = (Varyings)0;
  391. UNITY_SETUP_INSTANCE_ID(v);
  392. //UNITY_TRANSFER_INSTANCE_ID(v, o);
  393. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
  394. TerrainInstancing(v.positionOS, v.normalOS, v.texcoord);
  395. VertexPositionInputs Attributes = GetVertexPositionInputs(v.positionOS.xyz);
  396. o.uvMainAndLM.xy = v.texcoord;
  397. o.uvMainAndLM.zw = v.texcoord * unity_LightmapST.xy + unity_LightmapST.zw;
  398. #ifndef TERRAIN_SPLAT_BASEPASS
  399. #if defined(_PROCEDURALTEXTURING)
  400. o.uvSplat01.xy = Attributes.positionWS.xz / _ProceduralTiling;
  401. #else
  402. o.uvSplat01.xy = TRANSFORM_TEX(v.texcoord, _Splat0);
  403. #endif
  404. o.uvSplat01.zw = TRANSFORM_TEX(v.texcoord, _Splat1);
  405. o.uvSplat23.xy = TRANSFORM_TEX(v.texcoord, _Splat2);
  406. o.uvSplat23.zw = TRANSFORM_TEX(v.texcoord, _Splat3);
  407. #endif
  408. float3 viewDirWS = GetCameraPositionWS() - Attributes.positionWS;
  409. #if !SHADER_HINT_NICE_QUALITY
  410. viewDirWS = SafeNormalize(viewDirWS);
  411. #endif
  412. #if ( defined(_NORMALMAP) || defined(_PARALLAX) ) && !defined(ENABLE_TERRAIN_PERPIXEL_NORMAL)
  413. float4 vertexTangent = float4(cross(float3(0, 0, 1), v.normalOS), 1.0);
  414. VertexNormalInputs normalInput = GetVertexNormalInputs(v.normalOS, vertexTangent);
  415. // fix orientation
  416. normalInput.tangentWS *= -1;
  417. o.normal = normalInput.normalWS;
  418. float sign = vertexTangent.w * GetOddNegativeScale();
  419. o.tangent = float4(normalInput.tangentWS, sign);
  420. #else
  421. o.normal = TransformObjectToWorldNormal(v.normalOS);
  422. o.vertexSH = SampleSH(o.normal);
  423. #endif
  424. o.viewDir = viewDirWS;
  425. o.fogFactorAndVertexLight.x = ComputeFogFactor(Attributes.positionCS.z);
  426. o.fogFactorAndVertexLight.yzw = VertexLighting(Attributes.positionWS, o.normal.xyz);
  427. o.positionWS = Attributes.positionWS;
  428. o.clipPos = Attributes.positionCS;
  429. #if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
  430. o.shadowCoord = GetShadowCoord(Attributes);
  431. #endif
  432. return o;
  433. }
  434. // Used in Standard Terrain shader
  435. half4 SplatmapFragment(Varyings IN) : SV_TARGET {
  436. //UNITY_SETUP_INSTANCE_ID(IN);
  437. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(IN);
  438. #ifdef _ALPHATEST_ON
  439. half hole = SAMPLE_TEXTURE2D(_TerrainHolesTexture, sampler_TerrainHolesTexture, IN.uvMainAndLM.xy).r;
  440. clip(hole == 0.0h ? -1 : 1);
  441. #endif
  442. half3 normalTS = half3(0.0h, 0.0h, 1.0h);
  443. half3x3 tangentSpaceRotation = 0;
  444. half3 viewDirectionWS = SafeNormalize(IN.viewDir);
  445. #if defined(_NORMALMAP) || defined(_PARALLAX) || defined(TERRAIN_SPLAT_BASEPASS)
  446. #if !defined(ENABLE_TERRAIN_PERPIXEL_NORMAL) && ( defined(_NORMALMAP) || defined(_PARALLAX) )
  447. // Same matrix we need to transfer the normalTS
  448. half3 bitangentWS = cross(IN.normal, IN.tangent.xyz) * -1;
  449. tangentSpaceRotation = half3x3(IN.tangent.xyz, bitangentWS, IN.normal.xyz);
  450. half3 tangentWS = IN.tangent.xyz;
  451. half3 viewDirTS = normalize( mul(tangentSpaceRotation, viewDirectionWS ) );
  452. #elif defined(ENABLE_TERRAIN_PERPIXEL_NORMAL)
  453. float2 sampleCoords = (IN.uvMainAndLM.xy / _TerrainHeightmapRecipSize.zw + 0.5f) * _TerrainHeightmapRecipSize.xy;
  454. half3 normalWS = TransformObjectToWorldNormal(normalize(SAMPLE_TEXTURE2D(_TerrainNormalmapTexture, sampler_TerrainNormalmapTexture, sampleCoords).rgb * 2 - 1));
  455. // fix orientation
  456. half3 tangentWS = cross( /*GetObjectToWorldMatrix()._13_23_33*/ half3(0, 0, 1), normalWS) * -1;
  457. // Ups: * -1?
  458. half3 bitangentWS = cross(normalWS, tangentWS) * -1;
  459. tangentSpaceRotation = half3x3(tangentWS, bitangentWS, normalWS);
  460. half3 viewDirTS = normalize( mul(tangentSpaceRotation, viewDirectionWS) );
  461. #endif
  462. #endif
  463. #ifdef TERRAIN_SPLAT_BASEPASS
  464. half3 albedo = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, IN.uvMainAndLM.xy).rgb;
  465. half smoothness = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, IN.uvMainAndLM.xy).a;
  466. // Unity 2019.1
  467. half metallic = 0; //SAMPLE_TEXTURE2D(_MetallicTex, sampler_MetallicTex, IN.uvMainAndLM.xy).r;
  468. half alpha = 1;
  469. half occlusion = 1;
  470. #else
  471. half4 splatControl;
  472. half weight;
  473. half4 mixedDiffuse;
  474. half4 defaultSmoothness;
  475. float2 splatUV = (IN.uvMainAndLM.xy * (_Control_TexelSize.zw - 1.0f) + 0.5f) * _Control_TexelSize.xy;
  476. splatControl = SAMPLE_TEXTURE2D(_Control, sampler_Control, splatUV);
  477. // Sample heights
  478. #ifdef _TERRAIN_BLEND_HEIGHT
  479. half4 heights;
  480. #if defined(_PROCEDURALTEXTURING)
  481. half proceduralHeight;
  482. float2 uv1, uv2, uv3;
  483. half w1, w2, w3;
  484. float2 duvdx, duvdy;
  485. GetProceduralBaseSample(_HeightMaps, sampler_Splat0, IN.uvSplat01.xy, proceduralHeight, uv1, uv2, uv3, w1, w2, w3, duvdx, duvdy);
  486. heights.x = proceduralHeight;
  487. #else
  488. heights.x = SAMPLE_TEXTURE2D(_HeightMaps, sampler_Splat0, IN.uvSplat01.xy).r;
  489. #endif
  490. heights.y = SAMPLE_TEXTURE2D(_HeightMaps, sampler_Splat0, IN.uvSplat01.zw).g;
  491. heights.z = SAMPLE_TEXTURE2D(_HeightMaps, sampler_Splat0, IN.uvSplat23.xy).b;
  492. heights.w = SAMPLE_TEXTURE2D(_HeightMaps, sampler_Splat0, IN.uvSplat23.zw).a;
  493. half height;
  494. // Adjust spaltControl and calculate 1st height
  495. HeightBasedSplatModifyCombined(splatControl, heights, height);
  496. // Parallax Extrusion
  497. #if defined(_PARALLAX)
  498. float3 v = viewDirTS;
  499. v.z += 0.42;
  500. v.xy /= v.z;
  501. half halfParallax = _Parallax * 0.5h;
  502. half parallax = height * _Parallax - halfParallax;
  503. float2 offset1 = parallax * v.xy;
  504. float4 splatUV1 = IN.uvSplat01 + offset1.xyxy;
  505. float4 splatUV2 = IN.uvSplat23 + offset1.xyxy;
  506. #if defined(_PROCEDURALTEXTURING)
  507. uv1 += offset1.xy;
  508. uv2 += offset1.xy;
  509. uv2 += offset1.xy;
  510. heights.x = sampleProceduralHalf(_HeightMaps, sampler_Splat0, splatUV1.xy, uv1, uv2, uv3, w1, w2, w3, duvdx, duvdy);
  511. #else
  512. heights.x = SAMPLE_TEXTURE2D(_HeightMaps, sampler_Splat0, splatUV1.xy).r;
  513. #endif
  514. heights.y = SAMPLE_TEXTURE2D(_HeightMaps, sampler_Splat0, splatUV1.zw).g;
  515. heights.z = SAMPLE_TEXTURE2D(_HeightMaps, sampler_Splat0, splatUV2.xy).b;
  516. heights.w = SAMPLE_TEXTURE2D(_HeightMaps, sampler_Splat0, splatUV2.zw).a;
  517. // Calculate 2nd height
  518. half height1 = max( max(heights.x, heights.y), max(heights.z, heights.w) );
  519. parallax = height1 * _Parallax - halfParallax;
  520. float2 offset2 = parallax * v.xy;
  521. offset1 = (offset1 + offset2) * 0.5;
  522. IN.uvSplat01 = IN.uvSplat01 + offset1.xyxy * float4(1,1,1,1);
  523. IN.uvSplat23 = IN.uvSplat23 + offset1.xyxy * float4(1,1,1,1);
  524. #endif
  525. #endif
  526. #if defined(_PROCEDURALTEXTURING)
  527. #ifdef _TERRAIN_BLEND_HEIGHT
  528. SplatmapMixProcedural(IN.uvMainAndLM, IN.uvSplat01, IN.uvSplat23, splatControl, weight, mixedDiffuse, defaultSmoothness, normalTS,
  529. uv1, uv2, uv3, w1, w2, w3, duvdx, duvdy);
  530. #else
  531. SplatmapMix(IN.uvMainAndLM, IN.uvSplat01, IN.uvSplat23, splatControl, weight, mixedDiffuse, defaultSmoothness, normalTS);
  532. #endif
  533. #else
  534. SplatmapMix(IN.uvMainAndLM, IN.uvSplat01, IN.uvSplat23, splatControl, weight, mixedDiffuse, defaultSmoothness, normalTS);
  535. #endif
  536. half3 albedo = mixedDiffuse.rgb;
  537. // Looks broken...
  538. defaultSmoothness *= dot(half4(_Smoothness0, _Smoothness1, _Smoothness2, _Smoothness3), splatControl);
  539. half smoothness = dot(defaultSmoothness, splatControl);
  540. half metallic = dot(half4(_Metallic0, _Metallic1, _Metallic2, _Metallic3), splatControl);
  541. half occlusion = 1;
  542. half alpha = weight;
  543. #endif
  544. InputData inputData;
  545. InitializeInputData(IN, normalTS, tangentSpaceRotation, viewDirectionWS, inputData);
  546. half4 color = UniversalFragmentPBR(inputData, albedo, metallic, /* specular */ half3(0.0h, 0.0h, 0.0h), smoothness, occlusion, /* emission */ half3(0, 0, 0), alpha);
  547. SplatmapFinalColor(color, inputData.fogCoord);
  548. return half4(color.rgb, 1.0h);
  549. }
  550. // -----------------------------------------------------------------------------
  551. // Shadow pass
  552. // x: global clip space bias, y: normal world space bias
  553. float3 _LightDirection;
  554. struct AttributesLean {
  555. float4 positionOS : POSITION;
  556. float3 normalOS : NORMAL;
  557. UNITY_VERTEX_INPUT_INSTANCE_ID
  558. UNITY_VERTEX_OUTPUT_STEREO
  559. };
  560. #ifdef _ALPHATEST_ON
  561. Varyings ShadowPassVertex (Attributes v)
  562. {
  563. Varyings o = (Varyings)0;
  564. UNITY_SETUP_INSTANCE_ID(v);
  565. TerrainInstancing(v.positionOS, v.normalOS, v.texcoord);
  566. o.uvMainAndLM.xy = v.texcoord;
  567. float3 positionWS = TransformObjectToWorld(v.positionOS.xyz);
  568. float3 normalWS = TransformObjectToWorldNormal(v.normalOS);
  569. float4 clipPos = TransformWorldToHClip(ApplyShadowBias(positionWS, normalWS, _LightDirection));
  570. #if UNITY_REVERSED_Z
  571. clipPos.z = min(clipPos.z, clipPos.w * UNITY_NEAR_CLIP_VALUE);
  572. #else
  573. clipPos.z = max(clipPos.z, clipPos.w * UNITY_NEAR_CLIP_VALUE);
  574. #endif
  575. o.clipPos = clipPos;
  576. return o;
  577. }
  578. half4 ShadowPassFragment(Varyings input) : SV_TARGET {
  579. //ClipHoles(input.tc.xy);
  580. half hole = SAMPLE_TEXTURE2D(_TerrainHolesTexture, sampler_TerrainHolesTexture, input.uvMainAndLM.xy).r;
  581. clip(hole == 0.0h ? -1 : 1);
  582. return 0;
  583. }
  584. #else
  585. float4 ShadowPassVertex(AttributesLean v) : SV_POSITION {
  586. Varyings o;
  587. UNITY_SETUP_INSTANCE_ID(v);
  588. TerrainInstancing(v.positionOS, v.normalOS);
  589. float3 positionWS = TransformObjectToWorld(v.positionOS.xyz);
  590. float3 normalWS = TransformObjectToWorldNormal(v.normalOS);
  591. float4 clipPos = TransformWorldToHClip(ApplyShadowBias(positionWS, normalWS, _LightDirection));
  592. #if UNITY_REVERSED_Z
  593. clipPos.z = min(clipPos.z, clipPos.w * UNITY_NEAR_CLIP_VALUE);
  594. #else
  595. clipPos.z = max(clipPos.z, clipPos.w * UNITY_NEAR_CLIP_VALUE);
  596. #endif
  597. return clipPos;
  598. }
  599. half4 ShadowPassFragment(Varyings input) : SV_TARGET {
  600. return 0;
  601. }
  602. #endif
  603. // -----------------------------------------------------------------------------
  604. // Depth pass
  605. //
  606. #ifdef _ALPHATEST_ON
  607. Varyings DepthOnlyVertex(Attributes v) {
  608. Varyings o = (Varyings)0;
  609. UNITY_SETUP_INSTANCE_ID(v);
  610. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
  611. TerrainInstancing(v.positionOS, v.normalOS, v.texcoord);
  612. o.uvMainAndLM.xy = v.texcoord;
  613. o.clipPos = TransformObjectToHClip(v.positionOS.xyz);
  614. return o;
  615. }
  616. half4 DepthOnlyFragment(Varyings input) : SV_TARGET {
  617. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
  618. ClipHoles(input.uvMainAndLM.xy);
  619. return 0;
  620. }
  621. #else
  622. //float4 DepthOnlyVertex(AttributesLean v) : SV_POSITION {
  623. Varyings DepthOnlyVertex(AttributesLean v) {
  624. Varyings o = (Varyings)0;
  625. UNITY_SETUP_INSTANCE_ID(v);
  626. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
  627. TerrainInstancing(v.positionOS, v.normalOS);
  628. //return TransformObjectToHClip(v.positionOS.xyz);
  629. o.clipPos = TransformObjectToHClip(v.positionOS.xyz);
  630. return o;
  631. }
  632. half4 DepthOnlyFragment(Varyings input) : SV_TARGET {
  633. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
  634. return 0;
  635. }
  636. #endif
  637. // -----------------------------------------------------------------------------
  638. // DepthNormal pass
  639. struct AttributesDepthNormal
  640. {
  641. float4 positionOS : POSITION;
  642. float3 normalOS : NORMAL;
  643. float2 texcoord : TEXCOORD0;
  644. UNITY_VERTEX_INPUT_INSTANCE_ID
  645. };
  646. struct VaryingsDepthNormal
  647. {
  648. float4 uvMainAndLM : TEXCOORD0; // xy: control, zw: lightmap
  649. #ifndef TERRAIN_SPLAT_BASEPASS
  650. float4 uvSplat01 : TEXCOORD1; // xy: splat0, zw: splat1
  651. float4 uvSplat23 : TEXCOORD2; // xy: splat2, zw: splat3
  652. #endif
  653. #if defined(_NORMALMAP) && !defined(ENABLE_TERRAIN_PERPIXEL_NORMAL)
  654. float4 normal : TEXCOORD3; // xyz: normal, w: viewDir.x
  655. float4 tangent : TEXCOORD4; // xyz: tangent, w: viewDir.y
  656. float4 bitangent : TEXCOORD5; // xyz: bitangent, w: viewDir.z
  657. #else
  658. float3 normal : TEXCOORD3;
  659. #endif
  660. float4 clipPos : SV_POSITION;
  661. UNITY_VERTEX_OUTPUT_STEREO
  662. };
  663. VaryingsDepthNormal DepthNormalOnlyVertex(AttributesDepthNormal v)
  664. {
  665. VaryingsDepthNormal o = (VaryingsDepthNormal)0;
  666. UNITY_SETUP_INSTANCE_ID(v);
  667. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
  668. TerrainInstancing(v.positionOS, v.normalOS, v.texcoord);
  669. VertexPositionInputs Attributes = GetVertexPositionInputs(v.positionOS.xyz);
  670. o.uvMainAndLM.xy = v.texcoord;
  671. o.uvMainAndLM.zw = v.texcoord * unity_LightmapST.xy + unity_LightmapST.zw;
  672. #ifndef TERRAIN_SPLAT_BASEPASS
  673. o.uvSplat01.xy = TRANSFORM_TEX(v.texcoord, _Splat0);
  674. o.uvSplat01.zw = TRANSFORM_TEX(v.texcoord, _Splat1);
  675. o.uvSplat23.xy = TRANSFORM_TEX(v.texcoord, _Splat2);
  676. o.uvSplat23.zw = TRANSFORM_TEX(v.texcoord, _Splat3);
  677. #endif
  678. #if defined(_NORMALMAP) && !defined(ENABLE_TERRAIN_PERPIXEL_NORMAL)
  679. half3 viewDirWS = GetWorldSpaceViewDir(Attributes.positionWS);
  680. #if !SHADER_HINT_NICE_QUALITY
  681. viewDirWS = SafeNormalize(viewDirWS);
  682. #endif
  683. float4 vertexTangent = float4(cross(float3(0, 0, 1), v.normalOS), 1.0);
  684. VertexNormalInputs normalInput = GetVertexNormalInputs(v.normalOS, vertexTangent);
  685. o.normal = half4(normalInput.normalWS, viewDirWS.x);
  686. o.tangent = half4(normalInput.tangentWS, viewDirWS.y);
  687. o.bitangent = half4(normalInput.bitangentWS, viewDirWS.z);
  688. #else
  689. o.normal = TransformObjectToWorldNormal(v.normalOS);
  690. #endif
  691. o.clipPos = Attributes.positionCS;
  692. return o;
  693. }
  694. half4 DepthNormalOnlyFragment(VaryingsDepthNormal input) : SV_TARGET
  695. {
  696. #ifdef _ALPHATEST_ON
  697. ClipHoles(input.uvMainAndLM.xy);
  698. #endif
  699. half3 normalWS = input.normal.xyz;
  700. return float4(PackNormalOctRectEncode(TransformWorldToViewDir(normalWS, true)), 0.0, 0.0);
  701. }
  702. #endif