CameraFacingBillboardTree.shader 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
  2. Shader "Hidden/TerrainEngine/CameraFacingBillboardTree" {
  3. Properties{
  4. _MainTex("Base (RGB) Alpha (A)", 2D) = "white" {}
  5. _NormalTex("Base (RGB) Alpha (A)", 2D) = "white" {}
  6. _TranslucencyViewDependency("View dependency", Range(0,1)) = 0.7
  7. _TranslucencyColor("Translucency Color", Color) = (0.73,0.85,0.41,1)
  8. _AlphaToMask("AlphaToMask", Float) = 1.0 // On
  9. }
  10. SubShader{
  11. Tags {
  12. "IgnoreProjector" = "True" "RenderType" = "TreeBillboard" }
  13. Pass {
  14. ColorMask rgb
  15. ZWrite On Cull Off
  16. // AlphaToMask [_AlphaToMask]
  17. CGPROGRAM
  18. #pragma vertex vert
  19. #pragma fragment frag
  20. #pragma multi_compile_fog
  21. #include "UnityCG.cginc"
  22. #include "UnityBuiltin3xTreeLibrary.cginc"
  23. #if SHADER_API_D3D11 || SHADER_API_GLCORE
  24. #define ALBEDO_NORMAL_LIGHTING 1
  25. #endif
  26. struct v2f {
  27. float4 pos : SV_POSITION;
  28. fixed4 color : COLOR0;
  29. float3 uv : TEXCOORD0;
  30. UNITY_FOG_COORDS(1)
  31. UNITY_VERTEX_OUTPUT_STEREO
  32. float4 screenPos : TEXCOORD2;
  33. #if defined(ALBEDO_NORMAL_LIGHTING)
  34. float3 viewDir : TEXCOORD3;
  35. #endif
  36. };
  37. #if defined(ALBEDO_NORMAL_LIGHTING)
  38. CBUFFER_START(UnityTerrainImposter)
  39. float3 _TerrainTreeLightDirections[4];
  40. float4 _TerrainTreeLightColors[4];
  41. CBUFFER_END
  42. #endif
  43. void CameraFacingBillboardVert(inout float4 pos, float2 offset, float offsetz)
  44. {
  45. float3 vertViewVector = pos.xyz - _TreeBillboardCameraPos.xyz;
  46. float treeDistanceSqr = dot(vertViewVector, vertViewVector);
  47. float distance = sqrt(treeDistanceSqr);
  48. if (treeDistanceSqr > _TreeBillboardDistances.x)
  49. offset.xy = offsetz = 0.0;
  50. // Create LookAt matrix
  51. float3 up = float3(0, 1, 0);
  52. float3 zaxis = vertViewVector / distance; // distance won't be 0 since billboard would already be clipped by near plane
  53. float3 xaxis = normalize(cross(up, zaxis)); // direct top down view of billboard won't be visible due its orientation about yaxis
  54. float vertexCameraDistance = distance - _TreeBillboardDistances.z;
  55. float fadeAmount = saturate(vertexCameraDistance / _TreeBillboardDistances.w);
  56. pos.w = fadeAmount;
  57. if (vertexCameraDistance > _TreeBillboardDistances.w)
  58. pos.w = 1.0;
  59. // positioning of billboard vertices horizontally
  60. pos.xyz += xaxis * offset.x;
  61. float radius = offset.y;
  62. // positioning of billboard vertices veritally
  63. pos.xyz += up * radius;
  64. }
  65. v2f vert(appdata_tree_billboard v) {
  66. v2f o;
  67. UNITY_SETUP_INSTANCE_ID(v);
  68. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
  69. CameraFacingBillboardVert(v.vertex, v.texcoord1.xy, v.texcoord.y);
  70. o.uv.z = v.vertex.w;
  71. o.pos = UnityObjectToClipPos(v.vertex);
  72. o.uv.x = v.texcoord.x;
  73. o.uv.y = v.texcoord.y > 0;
  74. #if defined(ALBEDO_NORMAL_LIGHTING)
  75. o.viewDir = normalize(ObjSpaceViewDir(v.vertex));
  76. #endif
  77. o.color = v.color;
  78. o.screenPos = ComputeScreenPos(o.pos);
  79. UNITY_TRANSFER_FOG(o,o.pos);
  80. return o;
  81. }
  82. float LuxScreenDitherToAlpha(float x, float y, float c0)
  83. {
  84. #if (SHADER_TARGET > 30) || defined(SHADER_API_D3D11) || defined(SHADER_API_GLCORE) || defined(SHADER_API_GLES3)
  85. //dither matrix reference: https://en.wikipedia.org/wiki/Ordered_dithering
  86. const float dither[64] = {
  87. 0, 32, 8, 40, 2, 34, 10, 42,
  88. 48, 16, 56, 24, 50, 18, 58, 26 ,
  89. 12, 44, 4, 36, 14, 46, 6, 38 ,
  90. 60, 28, 52, 20, 62, 30, 54, 22,
  91. 3, 35, 11, 43, 1, 33, 9, 41,
  92. 51, 19, 59, 27, 49, 17, 57, 25,
  93. 15, 47, 7, 39, 13, 45, 5, 37,
  94. 63, 31, 55, 23, 61, 29, 53, 21 };
  95. int xMat = int(x) & 7;
  96. int yMat = int(y) & 7;
  97. float limit = (dither[yMat * 8 + xMat] + 11) / 64.0;
  98. return saturate( c0 * (1 + c0) - limit);
  99. #else
  100. return 1.0;
  101. #endif
  102. }
  103. float LuxComputeAlphaCoverage(float4 screenPos, float fadeAmount)
  104. {
  105. #if (SHADER_TARGET > 30) || defined(SHADER_API_D3D11) || defined(SHADER_API_GLCORE) || defined(SHADER_API_GLES3)
  106. float2 pixelPosition = screenPos.xy / (screenPos.w + 0.00001);
  107. pixelPosition *= _ScreenParams;
  108. float coverage = LuxScreenDitherToAlpha(pixelPosition.x, pixelPosition.y, fadeAmount);
  109. return coverage;
  110. #else
  111. return 1.0;
  112. #endif
  113. }
  114. half3 CalcTreeLighting(half3 viewDir, half3 lightColor, half3 lightDir, half3 albedo, half3 normal, half backContribScale)
  115. {
  116. half backContrib = saturate(dot(viewDir, -lightDir));
  117. half ndotl = dot(lightDir, normal);
  118. backContrib = lerp(saturate(-ndotl), backContrib, _TranslucencyViewDependency) * backContribScale;
  119. half3 translucencyColor = backContrib * _TranslucencyColor;
  120. const half diffuseWrap = 0.8;
  121. ndotl = saturate(ndotl * diffuseWrap + (1 - diffuseWrap));
  122. return albedo * (translucencyColor + ndotl) * lightColor;
  123. }
  124. sampler2D _MainTex;
  125. sampler2D _NormalTex;
  126. fixed4 frag(v2f input) : SV_Target
  127. {
  128. fixed4 col = tex2D(_MainTex, input.uv.xy);
  129. col.rgb *= input.color.rgb;
  130. #if defined(ALBEDO_NORMAL_LIGHTING)
  131. half3 normal = tex2D(_NormalTex, input.uv.xy).xyz;
  132. normal = normalize(normal);
  133. half3 albedo = col.rgb;
  134. // half3 light = UNITY_LIGHTMODEL_AMBIENT * albedo;
  135. half3 light = ShadeSH9(half4 (normal, 1)) * albedo;
  136. const half backContribScale = 0.2;
  137. light += CalcTreeLighting(input.viewDir, _TerrainTreeLightColors[0].rgb, _TerrainTreeLightDirections[0], albedo, normal, backContribScale);
  138. light += CalcTreeLighting(input.viewDir, _TerrainTreeLightColors[1].rgb, _TerrainTreeLightDirections[1], albedo, normal, backContribScale);
  139. light += CalcTreeLighting(input.viewDir, _TerrainTreeLightColors[2].rgb, _TerrainTreeLightDirections[2], albedo, normal, backContribScale);
  140. col.rgb = light;
  141. #endif
  142. //col.rgb = half3(1,0,0);
  143. float coverage = LuxComputeAlphaCoverage(input.screenPos, input.uv.z);
  144. col.a *= coverage;
  145. clip(col.a - _TreeBillboardCameraFront.w );
  146. UNITY_APPLY_FOG(input.fogCoord, col);
  147. return col;
  148. }
  149. ENDCG
  150. }
  151. }
  152. Fallback Off
  153. }