CTI_BillboardVertex.cginc 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. float _TreeScale;
  2. float _TreeWidth;
  3. float _TreeHeightLimit;
  4. float _ShadowOffset;
  5. #if defined(UNITY_PASS_SHADOWCASTER)
  6. uniform float4 unity_BillboardCameraParams;
  7. #define unity_BillboardCameraPosition (unity_BillboardCameraParams.xyz)
  8. #endif
  9. float3 unity_BillboardSize;
  10. #if defined(_EMISSION)
  11. float4 _TerrainLODWind;
  12. float _WindStrength;
  13. #endif
  14. struct appdata_bb {
  15. float4 vertex : POSITION;
  16. float3 normal : NORMAL;
  17. float4 tangent : TANGENT;
  18. float4 texcoord : TEXCOORD0;
  19. float4 texcoord1 : TEXCOORD1;
  20. fixed4 color : COLOR;
  21. UNITY_VERTEX_INPUT_INSTANCE_ID
  22. };
  23. struct Input {
  24. float2 uv_MainTex;
  25. fixed4 color;
  26. UNITY_DITHER_CROSSFADE_COORDS
  27. };
  28. float SmoothCurve(float4 x) {
  29. return x * x * (3.0 - 2.0 * x);
  30. }
  31. float4 TriangleWave(float4 x) {
  32. return abs(frac(x + 0.5) * 2.0 - 1.0);
  33. }
  34. float4 AfsSmoothTriangleWave(float4 x) {
  35. return (SmoothCurve(TriangleWave(x)) - 0.5) * 2.0;
  36. }
  37. // Billboard Vertex Function
  38. void AFSBillboardVert (inout appdata_bb v) {
  39. float4 position = v.vertex;
  40. float3 worldPos = v.vertex.xyz + float3(unity_ObjectToWorld[0].w, unity_ObjectToWorld[1].w, unity_ObjectToWorld[2].w);
  41. // float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
  42. // Add some kind of self shadowing when looking against sun
  43. // might need some more love - and looks weird in forward
  44. // #if defined(UNITY_PASS_SHADOWCASTER)
  45. // float offset = saturate(1.0 - saturate( dot(normalize(worldPos - _WorldSpaceCameraPos ), _WorldSpaceLightPos0.xyz) ) * 2.0); // ok
  46. // position.xz -= _WorldSpaceLightPos0.xz * saturate(offset) * _ShadowOffset;
  47. // #endif
  48. // Store Color Variation
  49. #if !defined(UNITY_PASS_SHADOWCASTER)
  50. float3 TreeWorldPos = abs(worldPos.xyz * 0.125f);
  51. v.color.r = saturate((frac(TreeWorldPos.x + TreeWorldPos.y + TreeWorldPos.z) + frac((TreeWorldPos.x + TreeWorldPos.y + TreeWorldPos.z) * 3.3)) * 0.5);
  52. #endif
  53. // ////////////////////////////////////
  54. // Set vertex position
  55. #if defined(UNITY_PASS_SHADOWCASTER)
  56. // We have to distinguish between depth and shadows (forward)
  57. // this is 0.0 while rendering the shadows but something else when unity renders depth
  58. float testShadowcasterPass = unity_BillboardCameraPosition.x + unity_BillboardCameraPosition.y + unity_BillboardCameraPosition.z;
  59. #if defined (SHADOWS_CUBE) || defined (SPOT)
  60. float3 eyeVec = (testShadowcasterPass == 0.0) ? normalize(_WorldSpaceLightPos0.xyz - worldPos) : normalize(_WorldSpaceCameraPos - worldPos);
  61. #else
  62. float3 eyeVec = (testShadowcasterPass == 0.0) ? -_WorldSpaceLightPos0.xyz : normalize(_WorldSpaceCameraPos - worldPos);
  63. #endif
  64. #else
  65. float3 eyeVec = normalize(_WorldSpaceCameraPos - worldPos);
  66. #endif
  67. float3 billboardTangent = normalize(float3(-eyeVec.z, 0, eyeVec.x));
  68. float3 billboardNormal = float3(billboardTangent.z, 0, -billboardTangent.x); // cross({0,1,0},billboardTangent)
  69. float2 percent = v.texcoord.xy;
  70. float3 billboardPos = (percent.x - 0.5) * unity_BillboardSize.x * v.texcoord1.x * billboardTangent;
  71. billboardPos.y += (percent.y * unity_BillboardSize.y * 2.0 + unity_BillboardSize.z) * v.texcoord1.y * _TreeHeightLimit;
  72. position.xyz += billboardPos;
  73. v.vertex.xyz = position.xyz;
  74. v.vertex.w = 1.0f;
  75. // Wind
  76. #if defined(_EMISSION)
  77. worldPos.xyz = abs(worldPos.xyz * 0.125f);
  78. float sinuswave = _SinTime.z;
  79. float4 vOscillations = AfsSmoothTriangleWave(float4(worldPos.x + sinuswave, worldPos.z + sinuswave * 0.8, 0.0, 0.0));
  80. float fOsc = vOscillations.x + (vOscillations.y * vOscillations.y);
  81. fOsc = 0.75 + (fOsc + 3.33) * 0.33;
  82. //v.vertex.xyz += _TerrainLODWind.xyz * fOsc * pow(percent.y, 1.5); // pow(y,1.5) matches the wind baked to the mesh trees
  83. // Needed since Unity 5.4., needed in Unity 5.5. as well. Not needed since 5.6. anymore
  84. // Detect single billboards which seem to have a very special unity_ObjectToWorld matrix and get corrupted by wind
  85. #if (UNITY_VERSION >= 540 && UNITY_VERSION < 560)
  86. float3 p1 = mul(unity_ObjectToWorld, float4(0,0,0,1)).xyz;
  87. float3 p2 = mul(unity_ObjectToWorld, float4(0,0,1,1)).xyz;
  88. float scale = p2.z - p1.z;
  89. v.vertex.xyz += _WindStrength * _TerrainLODWind.xyz * fOsc * pow(percent.y, 1.5) / scale; // pow(y,1.5) matches the wind baked to the mesh trees
  90. #else
  91. v.vertex.xyz += _WindStrength * _TerrainLODWind.xyz * fOsc * pow(percent.y, 1.5); // pow(y,1.5) matches the wind baked to the mesh trees
  92. #endif
  93. #endif
  94. // ////////////////////////////////////
  95. // Get billboard texture coords
  96. float angle = atan2(billboardNormal.z, billboardNormal.x); // signed angle between billboardNormal to {0,0,1}
  97. angle += angle < 0 ? 2 * UNITY_PI : 0;
  98. /*
  99. // SpeedTree Billboards seem to have shrinked uvs, so we expand them // padding seems to be 0.05?
  100. float minmax = v.texcoord.x * 2 - 1;
  101. minmax *= 1.0 / 0.85; // (1.0 - 0.06977); // 0.95
  102. v.texcoord.x = saturate( minmax * 0.5 + 0.5);
  103. // Adjust texccord to clamped height
  104. v.texcoord.y *= _TreeHeightLimit;
  105. */
  106. // Set Rotation
  107. angle += v.texcoord1.z;
  108. // Write final billboard texture coords
  109. const float invDelta = 1.0 / (45.0 * ((UNITY_PI * 2.0) / 360.0));
  110. float imageIndex = fmod(floor(angle * invDelta + 0.5f), 8);
  111. float2 column_row;
  112. column_row.x = imageIndex * 0.25; // we do not care about the horizontal coord that much as our billboard texture tiles
  113. //column_row.y = (imageIndex > 3) ? 0 : 0.5;
  114. column_row.y = saturate(4 - imageIndex) * 0.5;
  115. v.texcoord.xy = column_row + v.texcoord.xy * float2(0.25, 0.5);
  116. // ////////////////////////////////////
  117. // Set Normal and Tangent
  118. v.normal = billboardNormal.xyz;
  119. v.tangent = float4(billboardTangent.xyz, -1.0);
  120. //v.color.b = saturate( 1.0 - dot(eyeVec, billboardNormal.xyz) );
  121. }