InTerra_TerrainLitData.hlsl 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. // NOTE! Almost all code in this file and the file InTerra_TerrainLitTemplate is written by Unity and are used because there is no longer the possibility to use the Standard Shader (or contains code for Terrain Instancing etc.) and there would be need to write basically the same Template/LitData for InTerra Shader Functions.
  2. //-------------------------------------------------------------------------------------
  3. // Defines
  4. //-------------------------------------------------------------------------------------
  5. // Use surface gradient normal mapping as it handle correctly triplanar normal mapping and multiple UVSet
  6. #define SURFACE_GRADIENT
  7. // Use surface gradient normal mapping as it handle correctly triplanar normal mapping and multiple UVSet
  8. #ifndef UNITY_2022_2_OR_NEWER
  9. #define SURFACE_GRADIENT
  10. #else
  11. #ifndef SHADER_STAGE_RAY_TRACING
  12. #define SURFACE_GRADIENT
  13. #endif
  14. #endif
  15. //-------------------------------------------------------------------------------------
  16. // Fill SurfaceData/Builtin data function
  17. //-------------------------------------------------------------------------------------
  18. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Sampling/SampleUVMapping.hlsl"
  19. #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/MaterialUtilities.hlsl"
  20. #ifndef UNITY_TERRAIN_CB_VARS
  21. #define UNITY_TERRAIN_CB_VARS
  22. #endif
  23. #ifndef UNITY_TERRAIN_CB_DEBUG_VARS
  24. #define UNITY_TERRAIN_CB_DEBUG_VARS
  25. #endif
  26. CBUFFER_START(UnityTerrain)
  27. UNITY_TERRAIN_CB_VARS
  28. #ifdef UNITY_INSTANCING_ENABLED
  29. float4 _TerrainHeightmapRecipSize; // float4(1.0f/width, 1.0f/height, 1.0f/(width-1), 1.0f/(height-1))
  30. float4 _TerrainHeightmapScale; // float4(hmScale.x, hmScale.y / (float)(kMaxHeight), hmScale.z, 0.0f)
  31. #endif
  32. #ifdef DEBUG_DISPLAY
  33. UNITY_TERRAIN_CB_DEBUG_VARS
  34. #endif
  35. #ifdef SCENESELECTIONPASS
  36. int _ObjectId;
  37. int _PassValue;
  38. #endif
  39. CBUFFER_END
  40. #ifdef UNITY_INSTANCING_ENABLED
  41. TEXTURE2D(_TerrainHeightmapTexture);
  42. TEXTURE2D(_TerrainNormalmapTexture);
  43. #ifdef ENABLE_TERRAIN_PERPIXEL_NORMAL
  44. SAMPLER(sampler_TerrainNormalmapTexture);
  45. #endif
  46. #endif
  47. #ifdef _ALPHATEST_ON
  48. TEXTURE2D(_TerrainHolesTexture);
  49. SAMPLER(sampler_TerrainHolesTexture);
  50. #ifndef UNITY_2022_2_OR_NEWER
  51. void ClipHoles(float2 uv)
  52. {
  53. float hole = SAMPLE_TEXTURE2D(_TerrainHolesTexture, sampler_TerrainHolesTexture, uv).r;
  54. DoAlphaTest(hole, 0.5);
  55. }
  56. #endif
  57. #endif
  58. #if !defined(SHADER_STAGE_RAY_TRACING)
  59. // Vertex height displacement
  60. #ifdef HAVE_MESH_MODIFICATION
  61. UNITY_INSTANCING_BUFFER_START(Terrain)
  62. UNITY_DEFINE_INSTANCED_PROP(float4, _TerrainPatchInstanceData) // float4(xBase, yBase, skipScale, ~)
  63. UNITY_INSTANCING_BUFFER_END(Terrain)
  64. float4 ConstructTerrainTangent(float3 normal, float3 positiveZ)
  65. {
  66. // Consider a flat terrain. It should have tangent be (1, 0, 0) and bitangent be (0, 0, 1) as the UV of the terrain grid mesh is a scale of the world XZ position.
  67. // In CreateTangentToWorld function (in SpaceTransform.hlsl), it is cross(normal, tangent) * sgn for the bitangent vector.
  68. // It is not true in a left-handed coordinate system for the terrain bitangent, if we provide 1 as the tangent.w. It would produce (0, 0, -1) instead of (0, 0, 1).
  69. // Also terrain's tangent calculation was wrong in a left handed system because cross((0,0,1), terrainNormalOS) points to the wrong direction as negative X.
  70. // Therefore all the 4 xyzw components of the tangent needs to be flipped to correct the tangent frame.
  71. // (See TerrainLitData.hlsl - GetSurfaceAndBuiltinData)
  72. float3 tangent = cross(normal, positiveZ);
  73. return float4(tangent, -1);
  74. }
  75. AttributesMesh ApplyMeshModification(AttributesMesh input, float3 timeParameters)
  76. {
  77. #ifdef UNITY_INSTANCING_ENABLED
  78. float2 patchVertex = input.positionOS.xy;
  79. float4 instanceData = UNITY_ACCESS_INSTANCED_PROP(Terrain, _TerrainPatchInstanceData);
  80. float2 sampleCoords = (patchVertex.xy + instanceData.xy) * instanceData.z; // (xy + float2(xBase,yBase)) * skipScale
  81. float height = UnpackHeightmap(_TerrainHeightmapTexture.Load(int3(sampleCoords, 0)));
  82. input.positionOS.xz = sampleCoords * _TerrainHeightmapScale.xz;
  83. input.positionOS.y = height * _TerrainHeightmapScale.y;
  84. #ifdef ATTRIBUTES_NEED_NORMAL
  85. input.normalOS = _TerrainNormalmapTexture.Load(int3(sampleCoords, 0)).rgb * 2 - 1;
  86. #endif
  87. #if defined(VARYINGS_NEED_TEXCOORD0) || defined(VARYINGS_DS_NEED_TEXCOORD0)
  88. #ifdef ENABLE_TERRAIN_PERPIXEL_NORMAL
  89. input.uv0 = sampleCoords;
  90. #else
  91. input.uv0 = sampleCoords * _TerrainHeightmapRecipSize.zw;
  92. #endif
  93. #endif
  94. #endif
  95. #ifdef ATTRIBUTES_NEED_TANGENT
  96. input.tangentOS = ConstructTerrainTangent(input.normalOS, float3(0, 0, 1));
  97. #endif
  98. return input;
  99. }
  100. #endif // HAVE_MESH_MODIFICATION
  101. #endif // !defined(SHADER_STAGE_RAY_TRACING)
  102. // We don't use emission for terrain
  103. #define _EmissiveColor float3(0,0,0)
  104. #define _AlbedoAffectEmissive 0
  105. #define _EmissiveExposureWeight 0
  106. #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitBuiltinData.hlsl"
  107. #undef _EmissiveColor
  108. #undef _AlbedoAffectEmissive
  109. #undef _EmissiveExposureWeight
  110. #ifndef SHADER_STAGE_RAY_TRACING
  111. #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Decal/DecalUtilities.hlsl"
  112. #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitDecalData.hlsl"
  113. #endif
  114. #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/TerrainLit/TerrainLitSurfaceData.hlsl"
  115. void TerrainLitDebug(float2 uv, inout float3 baseColor);
  116. void InTerraTerrainLitShade(float2 uv, inout TerrainLitSurfaceData surfaceData, float3 positionWS, float3 normalWS, float3 tangentViewDir);
  117. float3 ConvertToNormalTS(float3 normalData, float3 tangentWS, float3 bitangentWS)
  118. {
  119. #ifdef _NORMALMAP
  120. #ifdef SURFACE_GRADIENT
  121. return SurfaceGradientFromTBN(normalData.xy, tangentWS, bitangentWS);
  122. #else
  123. return normalData;
  124. #endif
  125. #else
  126. #ifdef SURFACE_GRADIENT
  127. return float3(0.0, 0.0, 0.0); // No gradient
  128. #else
  129. return float3(0.0, 0.0, 1.0);
  130. #endif
  131. #endif
  132. }
  133. #ifndef UNITY_2022_2_OR_NEWER
  134. void GetSurfaceAndBuiltinData(inout FragInputs input, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData)
  135. {
  136. #else
  137. void GetSurfaceAndBuiltinData(inout FragInputs input, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData RAY_TRACING_OPTIONAL_PARAMETERS)
  138. {
  139. ZERO_INITIALIZE(SurfaceData, surfaceData);
  140. ZERO_INITIALIZE(BuiltinData, builtinData);
  141. #endif
  142. #ifdef ENABLE_TERRAIN_PERPIXEL_NORMAL
  143. float2 terrainNormalMapUV = (input.texCoord0.xy + 0.5f) * _TerrainHeightmapRecipSize.xy;
  144. input.texCoord0.xy *= _TerrainHeightmapRecipSize.zw;
  145. #endif
  146. #ifdef _ALPHATEST_ON
  147. #ifndef UNITY_2022_2_OR_NEWER
  148. ClipHoles(input.texCoord0.xy);
  149. #else
  150. float hole = SAMPLE_TEXTURE2D(_TerrainHolesTexture, sampler_TerrainHolesTexture, input.texCoord0.xy).r;
  151. GENERIC_ALPHA_TEST(hole, 0.5);
  152. #endif
  153. #endif
  154. float3 positionWS = GetAbsolutePositionWS(posInput.positionWS).xyz;
  155. // terrain lightmap uvs are always taken from uv0
  156. input.texCoord1 = input.texCoord2 = input.texCoord0;
  157. TerrainLitSurfaceData terrainLitSurfaceData;
  158. InitializeTerrainLitSurfaceData(terrainLitSurfaceData);
  159. #ifdef ENABLE_TERRAIN_PERPIXEL_NORMAL
  160. #ifdef TERRAIN_PERPIXEL_NORMAL_OVERRIDE
  161. float3 normalWS = terrainLitSurfaceData.normalData.xyz; // normalData directly contains normal in world space.
  162. #else
  163. float3 normalOS = SAMPLE_TEXTURE2D(_TerrainNormalmapTexture, sampler_TerrainNormalmapTexture, terrainNormalMapUV).rgb * 2 - 1;
  164. float3 normalWS = mul((float3x3)GetObjectToWorldMatrix(), normalOS);
  165. #endif
  166. float4 tangentWS = ConstructTerrainTangent(normalWS, GetObjectToWorldMatrix()._13_23_33);
  167. input.tangentToWorld = BuildTangentToWorld(tangentWS, normalWS);
  168. surfaceData.normalWS = normalWS;
  169. #else
  170. #ifndef UNITY_2022_2_OR_NEWER
  171. surfaceData.normalWS = float3(0.0, 1.0, 0.0);
  172. #else
  173. surfaceData.normalWS = float3(0.0, 0.0, 0.0);
  174. #endif
  175. #endif
  176. surfaceData.tangentWS = normalize(input.tangentToWorld[0].xyz); // The tangent is not normalize in tangentToWorld for mikkt. Tag: SURFACE_GRADIENT
  177. surfaceData.geomNormalWS = input.tangentToWorld[2];
  178. float3 tangentViewDir = float3(0.0, 1.0, 0.0);
  179. #ifdef _TERRAIN_PARALLAX
  180. float3x3 objectToTangent = float3x3(surfaceData.tangentWS.xyz, (cross(surfaceData.geomNormalWS.xyz, surfaceData.tangentWS.xyz)) * -1, surfaceData.geomNormalWS.xyz);
  181. tangentViewDir = normalize(mul(objectToTangent, GetWorldSpaceNormalizeViewDir(posInput.positionWS)));
  182. float3 wNormal = surfaceData.geomNormalWS;
  183. float3 axisSign = wNormal < 0 ? -1 : 1;
  184. half3 tangentY = normalize(cross(wNormal.xyz, half3(1e-5f, 1e-5f, axisSign.y)));
  185. half3 bitangentY = normalize(cross(tangentY.xyz, wNormal.xyz)) * axisSign.y;
  186. half3x3 tbnY = half3x3(tangentY, bitangentY, wNormal);
  187. #endif
  188. InTerraTerrainLitShade(input.texCoord0.xy, terrainLitSurfaceData, positionWS, input.tangentToWorld[2], tangentViewDir);
  189. surfaceData.baseColor = terrainLitSurfaceData.albedo;
  190. surfaceData.perceptualSmoothness = terrainLitSurfaceData.smoothness;
  191. surfaceData.metallic = terrainLitSurfaceData.metallic;
  192. surfaceData.ambientOcclusion = terrainLitSurfaceData.ao;
  193. surfaceData.subsurfaceMask = 0;
  194. surfaceData.thickness = 1;
  195. surfaceData.diffusionProfileHash = 0;
  196. #ifdef UNITY_2022_2_OR_NEWER
  197. surfaceData.transmissionMask = 0;
  198. #endif
  199. surfaceData.materialFeatures = MATERIALFEATUREFLAGS_LIT_STANDARD;
  200. // Init other parameters
  201. surfaceData.anisotropy = 0.0;
  202. surfaceData.specularColor = float3(0.0, 0.0, 0.0);
  203. surfaceData.coatMask = 0.0;
  204. surfaceData.iridescenceThickness = 0.0;
  205. surfaceData.iridescenceMask = 0.0;
  206. // Transparency parameters
  207. // Use thickness from SSS
  208. surfaceData.ior = 1.0;
  209. surfaceData.transmittanceColor = float3(1.0, 1.0, 1.0);
  210. surfaceData.atDistance = 1000000.0;
  211. surfaceData.transmittanceMask = 0.0;
  212. // This need to be init here to quiet the compiler in case of decal, but can be override later.
  213. surfaceData.specularOcclusion = 1.0;
  214. #if defined(DECAL_SURFACE_GRADIENT) && !defined(SHADER_STAGE_RAY_TRACING)
  215. #if !defined(ENABLE_TERRAIN_PERPIXEL_NORMAL) || !defined(TERRAIN_PERPIXEL_NORMAL_OVERRIDE)
  216. float3 normalTS = ConvertToNormalTS(terrainLitSurfaceData.normalData, input.tangentToWorld[0], input.tangentToWorld[1]);
  217. #if HAVE_DECALS
  218. if (_EnableDecals)
  219. {
  220. float alpha = 1.0; // unused
  221. DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, input, alpha);
  222. ApplyDecalToSurfaceData(decalSurfaceData, input.tangentToWorld[2], surfaceData, normalTS);
  223. }
  224. #endif
  225. GetNormalWS(input, normalTS, surfaceData.normalWS, float3(1.0, 1.0, 1.0));
  226. #elif HAVE_DECALS
  227. if (_EnableDecals)
  228. {
  229. float3 normalTS = SurfaceGradientFromPerturbedNormal(input.tangentToWorld[2], surfaceData.normalWS);
  230. float alpha = 1.0; // unused
  231. DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, input, alpha);
  232. ApplyDecalToSurfaceData(decalSurfaceData, input.tangentToWorld[2], surfaceData, normalTS);
  233. GetNormalWS(input, normalTS, surfaceData.normalWS, float3(1.0, 1.0, 1.0));
  234. }
  235. #endif
  236. #else // defined(DECAL_SURFACE_GRADIENT) && !defined(SHADER_STAGE_RAY_TRACING)
  237. #if !defined(ENABLE_TERRAIN_PERPIXEL_NORMAL) || !defined(TERRAIN_PERPIXEL_NORMAL_OVERRIDE)
  238. float3 normalTS = ConvertToNormalTS(terrainLitSurfaceData.normalData, input.tangentToWorld[0], input.tangentToWorld[1]);
  239. GetNormalWS(input, normalTS, surfaceData.normalWS, float3(1.0, 1.0, 1.0));
  240. #endif
  241. #if HAVE_DECALS && !defined(SHADER_STAGE_RAY_TRACING)
  242. if (_EnableDecals)
  243. {
  244. float alpha = 1.0; // unused
  245. // Both uses and modifies 'surfaceData.normalWS'.
  246. DecalSurfaceData decalSurfaceData = GetDecalSurfaceData(posInput, input, alpha);
  247. ApplyDecalToSurfaceData(decalSurfaceData, input.tangentToWorld[2], surfaceData);
  248. }
  249. #endif
  250. #endif // DECAL_SURFACE_GRADIENT
  251. float3 bentNormalWS = surfaceData.normalWS;
  252. #if defined(DEBUG_DISPLAY) && !defined(SHADER_STAGE_RAY_TRACING)
  253. if (_DebugMipMapMode != DEBUGMIPMAPMODE_NONE)
  254. {
  255. TerrainLitDebug(input.texCoord0.xy, surfaceData.baseColor);
  256. surfaceData.metallic = 0;
  257. }
  258. // We need to call ApplyDebugToSurfaceData after filling the surfarcedata and before filling builtinData
  259. // as it can modify attribute use for static lighting
  260. ApplyDebugToSurfaceData(input.tangentToWorld, surfaceData);
  261. #endif
  262. // By default we use the ambient occlusion with Tri-ace trick (apply outside) for specular occlusion.
  263. // Don't do spec occ from Ambient if there is no mask mask
  264. #if defined(_MASKMAP) && !defined(_SPECULAR_OCCLUSION_NONE)
  265. surfaceData.specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(ClampNdotV(dot(surfaceData.normalWS, V)), surfaceData.ambientOcclusion, PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness));
  266. #endif
  267. GetBuiltinData(input, V, posInput, surfaceData, 1, bentNormalWS, 0, builtinData);
  268. #ifdef UNITY_2022_2_OR_NEWER
  269. RAY_TRACING_OPTIONAL_ALPHA_TEST_PASS
  270. #endif
  271. }
  272. #ifdef TESSELLATION_ON
  273. float _TessellationFactor;
  274. float _TessellationFactorMinDistance;
  275. float _TessellationFactorMaxDistance;
  276. float _TessellationFactorTriangleSize;
  277. float _TessellationShapeFactor;
  278. float _TessellationBackFaceCullEpsilon;
  279. float _TessellationMaxDisplacement;
  280. float _EnableBlendModePreserveSpecularLighting;
  281. float _HeightCenter, _HeightAmplitude;
  282. float _Tessellation_HeightTransition;
  283. float _TessellationShadowQuality;
  284. struct LayerTexCoord
  285. {
  286. #ifndef LAYERED_LIT_SHADER
  287. UVMapping base;
  288. UVMapping details;
  289. #else
  290. // Regular texcoord
  291. UVMapping base0;
  292. UVMapping base1;
  293. UVMapping base2;
  294. UVMapping base3;
  295. UVMapping details0;
  296. UVMapping details1;
  297. UVMapping details2;
  298. UVMapping details3;
  299. // Dedicated for blend mask
  300. UVMapping blendMask;
  301. #endif
  302. // Store information that will be share by all UVMapping
  303. float3 vertexNormalWS;
  304. float3 triplanarWeights;
  305. #ifdef SURFACE_GRADIENT
  306. // tangent basis for each UVSet - up to 4 for now
  307. float3 vertexTangentWS0, vertexBitangentWS0;
  308. float3 vertexTangentWS1, vertexBitangentWS1;
  309. float3 vertexTangentWS2, vertexBitangentWS2;
  310. float3 vertexTangentWS3, vertexBitangentWS3;
  311. #endif
  312. };
  313. float GetMaxDisplacement()
  314. {
  315. return _TessellationMaxDisplacement;
  316. }
  317. void ApplyDisplacementTileScale(inout float height)
  318. {
  319. #ifdef _DISPLACEMENT_LOCK_TILING_SCALE
  320. height *= _InvTilingScale;
  321. #endif
  322. }
  323. #include "InTerra_Tessellation.hlsl"
  324. float3 ComputePerVertexTerrainDisplacement(float3 positionRWS, float3 normalWS, float2 uv, float4 vertexColor)
  325. {
  326. float3 height;
  327. Tessellation(positionRWS, normalWS, uv, height);
  328. return height;
  329. }
  330. float3 GetVertexDisplacement(float3 positionRWS, float3 normalWS, float2 texCoord0, float2 texCoord1, float2 texCoord2, float2 texCoord3, float4 vertexColor)
  331. {
  332. float2 sampleCoords = float2(0.0, 0.0);
  333. #ifdef VARYINGS_DS_NEED_TEXCOORD0
  334. sampleCoords = texCoord0.xy;
  335. #endif
  336. #ifdef VARYINGS_DS_NEED_TEXCOORD0
  337. sampleCoords = texCoord0.xy;
  338. #endif
  339. #ifdef VARYINGS_DS_NEED_TEXCOORD1
  340. sampleCoords = texCoord1.xy;
  341. #endif
  342. #ifdef VARYINGS_DS_NEED_TEXCOORD2
  343. sampleCoords = texCoord2.xy;
  344. #endif
  345. #ifdef VARYINGS_DS_NEED_TEXCOORD3
  346. sampleCoords = texCoord3.xy;
  347. #endif
  348. return ComputePerVertexTerrainDisplacement(positionRWS, normalWS, sampleCoords, vertexColor);
  349. }
  350. float GetTessellationFactor(AttributesMesh input)
  351. {
  352. #if SHADERPASS == SHADERPASS_SHADOWS
  353. return _TessellationFactor * _TessellationShadowQuality;
  354. #else
  355. return _TessellationFactor;
  356. #endif
  357. }
  358. VaryingsMeshToDS ApplyTessellationModification(VaryingsMeshToDS input, float3 timeParameters)
  359. {
  360. #if defined(_TESSELLATION_DISPLACEMENT)
  361. input.positionRWS += GetVertexDisplacement(input.positionRWS + _WorldSpaceCameraPos, input.normalWS,
  362. #ifdef VARYINGS_DS_NEED_TEXCOORD0
  363. input.texCoord0.xy,
  364. #else
  365. float2(0.0, 0.0),
  366. #endif
  367. #ifdef VARYINGS_DS_NEED_TEXCOORD1
  368. input.texCoord1.xy,
  369. #else
  370. float2(0.0, 0.0),
  371. #endif
  372. #ifdef VARYINGS_DS_NEED_TEXCOORD2
  373. input.texCoord2.xy,
  374. #else
  375. float2(0.0, 0.0),
  376. #endif
  377. #ifdef VARYINGS_DS_NEED_TEXCOORD3
  378. input.texCoord3.xy,
  379. #else
  380. float2(0.0, 0.0),
  381. #endif
  382. #ifdef VARYINGS_DS_NEED_COLOR
  383. input.color
  384. #else
  385. float4(0.0, 0.0, 0.0, 0.0)
  386. #endif
  387. );
  388. #endif // _TESSELLATION_DISPLACEMENT
  389. return input;
  390. }
  391. #endif