Terrain.shader 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. // Implements correct triplanar normals in a Surface Shader with out computing or passing additional information from the
  2. // vertex shader. Instead works around some oddities with how Surface Shaders handle the tangent space vectors. Attempting
  3. // to directly access the tangent matrix data results in a shader generation error. This works around the issue by tricking
  4. // the surface shader into not using those vectors until actually in the generated shader code. - Ben Golus 2017
  5. Shader "Custom/Terrain" {
  6. Properties {
  7. _WaterColor ("Water Color", Color) = (1,1,1,1)
  8. _WaterEdge("Water Edge Hardness", Range(0, 1)) = 0.2
  9. [NoScaleOffset]_WaterRoughness ("Water Roughness", 2D) = "white" {}
  10. _ParallaxStrength("Parallax Strength", Range(0, 0.1)) = 0.05
  11. //01
  12. [NoScaleOffset]_Albedo01 ("Albedo 01", 2D) = "white" {}
  13. [NoScaleOffset]_Normal01("Normal 01", 2D) = "bump" {}
  14. [NoScaleOffset]_MRHAO01 ("Metal/Rough/Height/AO 01", 2D) = "white" {}
  15. _TextureScale01("Texture Scale 01", Float) = 1.0
  16. _Falloff01("Blend Falloff 01", Range(0, 1)) = 0.2
  17. //02
  18. [NoScaleOffset]_Albedo02 ("Albedo 02", 2D) = "white" {}
  19. [NoScaleOffset]_Normal02("Normal 02", 2D) = "bump" {}
  20. [NoScaleOffset]_Normal02Detail("Normal 02 Detail", 2D) = "bump" {}
  21. [NoScaleOffset]_MRHAO02 ("Metal/Rough/Height/AO 02", 2D) = "white" {}
  22. _TextureScale02("Texture Scale 01", Float) = 1.0
  23. _Falloff02("Blend Falloff 01", Range(0, 1)) = 0.2
  24. //03
  25. [NoScaleOffset]_Albedo03 ("Albedo 03", 2D) = "white" {}
  26. [NoScaleOffset]_Normal03("Normal 03", 2D) = "bump" {}
  27. [NoScaleOffset]_MRHAO03 ("Metal/Rough/Height/AO 03", 2D) = "white" {}
  28. _TextureScale03("Texture Scale 01", Float) = 1.0
  29. _Falloff03("Blend Falloff 01", Range(0, 1)) = 0.2
  30. //04
  31. //[NoScaleOffset]_Albedo04 ("Albedo 04", 2D) = "white" {}
  32. //[NoScaleOffset]_Normal04("Normal 04", 2D) = "bump" {}
  33. //[NoScaleOffset]_MRHAO04 ("Metal/Rough/Height/AO 04", 2D) = "white" {}
  34. //_TextureScale04("Texture Scale 01", Float) = 1.0
  35. //_Falloff04("Blend Falloff 01", Range(0, 1)) = 0.2
  36. }
  37. SubShader {
  38. Tags { "RenderType"="Opaque" }
  39. LOD 200
  40. CGPROGRAM
  41. #pragma surface surf Standard fullforwardshadows vertex:vert addshadow
  42. #pragma target 5.0
  43. #include "UnityStandardUtils.cginc"
  44. #include "UnityCG.cginc"
  45. #include "AutoLight.cginc"
  46. #include "Tessellation.cginc"
  47. // #define TRIPLANAR_UV_OFFSET
  48. // hack to work around the way Unity passes the tangent to world matrix to surface shaders to prevent compiler errors
  49. #if defined(INTERNAL_DATA) && (defined(UNITY_PASS_FORWARDBASE) || defined(UNITY_PASS_FORWARDADD) || defined(UNITY_PASS_DEFERRED) || defined(UNITY_PASS_META))
  50. #define WorldToTangentNormalVector(data,normal) mul(normal, half3x3(data.internalSurfaceTtoW0, data.internalSurfaceTtoW1, data.internalSurfaceTtoW2))
  51. #else
  52. #define WorldToTangentNormalVector(data,normal) normal
  53. #endif
  54. // Reoriented Normal Mapping
  55. // http://blog.selfshadow.com/publications/blending-in-detail/
  56. // Altered to take normals (-1 to 1 ranges) rather than unsigned normal maps (0 to 1 ranges)
  57. half3 blend_rnm(half3 n1, half3 n2)
  58. {
  59. n1.z += 1;
  60. n2.xy = -n2.xy;
  61. return n1 * dot(n1, n2) / n1.z - n2;
  62. }
  63. sampler2D _Albedo01, _Normal01, _MRHAO01;
  64. sampler2D _Albedo02, _Normal02, _MRHAO02;
  65. sampler2D _Albedo03, _Normal03, _MRHAO03;
  66. sampler2D _Normal02Detail;
  67. sampler2D _WaterRoughness;
  68. half _WaterEdge, _ParallaxStrength;
  69. half _Falloff01, _Falloff02, _Falloff03, _Falloff04;
  70. half _TextureScale01, _TextureScale02, _TextureScale03;
  71. half4 _WaterColor;
  72. struct vertdata {
  73. float4 vertex : POSITION;
  74. float4 tangent : TANGENT;
  75. float3 normal : NORMAL;
  76. float4 texcoord : TEXCOORD0;
  77. float4 texcoord1 : TEXCOORD1;
  78. float4 texcoord2 : TEXCOORD2;
  79. fixed4 color : COLOR;
  80. float3 tangentViewDir : TEXCOORD3;
  81. UNITY_VERTEX_INPUT_INSTANCE_ID
  82. };
  83. struct Input {
  84. float3 worldPos;
  85. float3 viewDir;
  86. float3 worldNormal;
  87. float2 uv_MainTex;
  88. float4 color : COLOR;
  89. float3 tangentViewDir : TEXCOORD3;
  90. INTERNAL_DATA
  91. };
  92. void vert (inout vertdata v, out Input o) {
  93. UNITY_INITIALIZE_OUTPUT(Input,o);
  94. float3 worldPos = mul (unity_ObjectToWorld, v.vertex).xyz;
  95. float3x3 objectToTangent = float3x3(v.tangent.xyz,cross(v.normal, v.tangent.xyz) * v.tangent.w,v.normal);
  96. v.tangentViewDir = mul(objectToTangent, ObjSpaceViewDir(v.vertex));
  97. o.tangentViewDir = normalize(v.tangentViewDir);
  98. o.tangentViewDir.xy /= o.tangentViewDir.z;
  99. }
  100. void surf (Input IN, inout SurfaceOutputStandard o) {
  101. IN.worldNormal = WorldNormalVector(IN, float3(0,0,1));
  102. // top down UVs
  103. float2 UVY = IN.worldPos.xz;
  104. fixed4 vertCol = IN.color;
  105. //Albedo
  106. fixed4 Albedo01 = tex2D(_Albedo01, UVY * _TextureScale01);
  107. fixed4 Albedo02 = tex2D(_Albedo02, UVY * _TextureScale02);
  108. fixed4 Albedo03 = tex2D(_Albedo03, UVY * _TextureScale03);
  109. //fixed4 Albedo04 = tex2D(_Albedo04, UVY * _TextureScale04);
  110. half blend01 = smoothstep(vertCol.r, vertCol.r-_Falloff01, 1-Albedo01.a);
  111. half blend02 = smoothstep(vertCol.g, vertCol.g-_Falloff02, 1-Albedo03.a);
  112. float2 UVY2 = IN.worldPos.xz;
  113. UVY2 += IN.tangentViewDir * _ParallaxStrength * blend01;
  114. Albedo02 = tex2D(_Albedo02, UVY2 * _TextureScale02);
  115. Albedo03 = tex2D(_Albedo03, UVY * _TextureScale03);
  116. fixed4 AlbedoFinal = Albedo01;
  117. AlbedoFinal = lerp(AlbedoFinal, Albedo02, blend01);
  118. AlbedoFinal = lerp(AlbedoFinal, Albedo01, blend02);
  119. //AlbedoFinal = lerp(AlbedoFinal, Albedo04, blend03);
  120. // tangent space normal map
  121. half3 Normal01 = UnpackNormal(tex2D(_Normal01, UVY * _TextureScale01));
  122. half3 Normal02 = UnpackNormal(tex2D(_Normal02, UVY2 * _TextureScale02));
  123. half3 Normal03 = UnpackNormal(tex2D(_Normal03, UVY * _TextureScale03));
  124. //half3 Normal04 = UnpackNormal(tex2D(_Normal04, UVY * _TextureScale04));
  125. half3 Normal02Detail = UnpackNormal(tex2D(_Normal02Detail, UVY*0.1));
  126. // flip normal maps' x axis to account for flipped UVs
  127. half3 absVertNormal = abs(IN.worldNormal);
  128. // swizzle world normals to match tangent space and apply reoriented normal mapping blend
  129. half3 tangentNormal = lerp(Normal01,Normal02, blend01);
  130. tangentNormal = lerp(tangentNormal, Normal03, blend02);
  131. //tangentNormal = lerp(tangentNormal, Normal04, blend03);
  132. tangentNormal = blend_rnm(half3(IN.worldNormal.xz, absVertNormal.y), tangentNormal);
  133. // sizzle tangent normals to match world normal and blend together
  134. half3 worldNormal = normalize(tangentNormal.xzy);
  135. // convert world space normals into tangent normals
  136. float3 NormalFinal = WorldToTangentNormalVector(IN, worldNormal);
  137. //Roughness
  138. half Roughness01 = tex2D(_MRHAO01, UVY * _TextureScale01).a;
  139. half Roughness02 = tex2D(_MRHAO02, UVY2 * _TextureScale02).a;
  140. half Roughness03 = tex2D(_MRHAO03, UVY * _TextureScale03).a;
  141. //half Roughness04 = tex2D(_MRHAO04, UVY * _TextureScale04).a;
  142. fixed4 RoughnessFinal = lerp(0.3, Roughness02, blend01);
  143. RoughnessFinal = lerp(RoughnessFinal, Roughness03, blend02);
  144. //RoughnessFinal = lerp(RoughnessFinal, Roughness04, blend03);
  145. /*
  146. //waterLevel
  147. half blendY = 1-smoothstep(0.96, 1, absVertNormal.y);
  148. half waterLevel = smoothstep(IN.color.r, IN.color.r - 0.3, clamp(0, 1, colY.a + blendY));
  149. half waterLevel2 = smoothstep(0, 0.1, waterLevel);
  150. //half waterLevel = blendY;
  151. */
  152. //water
  153. float blend = 1-Albedo01.a;
  154. half3 upNormal = WorldToTangentNormalVector(IN, float3(0,1,0));
  155. AlbedoFinal = lerp(AlbedoFinal*_WaterColor, AlbedoFinal, smoothstep(IN.color.a+_WaterEdge, IN.color.a+1, blend));
  156. NormalFinal = lerp(upNormal, NormalFinal, smoothstep(IN.color.a+_WaterEdge, IN.color.a, blend));
  157. RoughnessFinal = lerp( tex2D(_WaterRoughness, UVY * 0.3).a * 0.95, RoughnessFinal, smoothstep(IN.color.a+_WaterEdge, IN.color.a, blend));
  158. // set surface ouput properties
  159. o.Albedo = AlbedoFinal;
  160. //o.Occlusion = occ;
  161. o.Metallic = 0;
  162. o.Smoothness = RoughnessFinal;
  163. o.Normal = NormalFinal;
  164. }
  165. ENDCG
  166. }
  167. FallBack "Diffuse"
  168. }