Lux URP Tree Creator Library.hlsl 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #ifndef LUXLWRP_TREELIBRARY_INCLUDED
  2. #define LUXLWRP_TREELIBRARY_INCLUDED
  3. float LuxScreenDitherToAlpha(float x, float y, float c0)
  4. {
  5. #if (SHADER_TARGET > 30) || defined(SHADER_API_D3D11) || defined(SHADER_API_GLCORE) || defined(SHADER_API_GLES3)
  6. //dither matrix reference: https://en.wikipedia.org/wiki/Ordered_dithering
  7. const float dither[64] = {
  8. 0, 32, 8, 40, 2, 34, 10, 42,
  9. 48, 16, 56, 24, 50, 18, 58, 26 ,
  10. 12, 44, 4, 36, 14, 46, 6, 38 ,
  11. 60, 28, 52, 20, 62, 30, 54, 22,
  12. 3, 35, 11, 43, 1, 33, 9, 41,
  13. 51, 19, 59, 27, 49, 17, 57, 25,
  14. 15, 47, 7, 39, 13, 45, 5, 37,
  15. 63, 31, 55, 23, 61, 29, 53, 21 };
  16. int xMat = int(x) & 7;
  17. int yMat = int(y) & 7;
  18. float limit = (dither[yMat * 8 + xMat] + 11) / 64.0;
  19. return saturate( c0 * (1 + c0) - limit - 0.01h);
  20. #else
  21. return 1.0;
  22. #endif
  23. }
  24. float LuxComputeAlphaCoverage(float4 screenPos, float fadeAmount)
  25. {
  26. #if (SHADER_TARGET > 30) || defined(SHADER_API_D3D11) || defined(SHADER_API_GLCORE) || defined(SHADER_API_GLES3)
  27. float2 pixelPosition = screenPos.xy / (screenPos.w + 0.00001);
  28. pixelPosition *= _ScreenParams.xy;
  29. float coverage = LuxScreenDitherToAlpha(pixelPosition.x, pixelPosition.y, fadeAmount);
  30. return coverage;
  31. #else
  32. return 1.0;
  33. #endif
  34. }
  35. inline float3 Squash(in float3 pos)
  36. {
  37. float3 planeNormal = UNITY_ACCESS_INSTANCED_PROP(Props, _SquashPlaneNormal).xyz;
  38. float3 projectedVertex = pos.xyz - (dot(planeNormal.xyz, pos.xyz) + UNITY_ACCESS_INSTANCED_PROP(Props, _SquashPlaneNormal).w) * planeNormal;
  39. pos = float3(lerp(projectedVertex, pos.xyz, UNITY_ACCESS_INSTANCED_PROP(Props, _SquashAmount)));
  40. return pos;
  41. }
  42. float4 SmoothCurve( float4 x ) {
  43. return x * x *( 3.0 - 2.0 * x );
  44. }
  45. float4 TriangleWave( float4 x ) {
  46. return abs( frac( x + 0.5 ) * 2.0 - 1.0 );
  47. }
  48. float4 SmoothTriangleWave( float4 x ) {
  49. return SmoothCurve( TriangleWave( x ) );
  50. }
  51. // Detail bending
  52. inline float3 AnimateVertex(float3 pos, float3 normal, float4 animParams)
  53. {
  54. // animParams stored in color
  55. // animParams.x = branch phase
  56. // animParams.y = edge flutter factor
  57. // animParams.z = primary factor
  58. // animParams.w = secondary factor
  59. // Fade in Wind
  60. float4 wind = UNITY_ACCESS_INSTANCED_PROP(Props, _Wind) * UNITY_ACCESS_INSTANCED_PROP(Props, _SquashAmount);
  61. float origLength = length(pos);
  62. float fDetailAmp = 0.1f;
  63. float fBranchAmp = 0.3f;
  64. // Phases (object, vertex, branch)
  65. float fObjPhase = dot(UNITY_MATRIX_M._m03_m13_m23, 1); //dot(unity_ObjectToWorld._14_24_34, 1);
  66. float fBranchPhase = fObjPhase + animParams.x;
  67. float fVtxPhase = dot(pos.xyz, animParams.y + fBranchPhase);
  68. // x is used for edges; y is used for branches
  69. float2 vWavesIn = _Time.yy + float2(fVtxPhase, fBranchPhase );
  70. // 1.975, 0.793, 0.375, 0.193 are good frequencies
  71. float4 vWaves = (frac( vWavesIn.xxyy * float4(1.975, 0.793, 0.375, 0.193) ) * 2.0 - 1.0);
  72. vWaves = SmoothTriangleWave( vWaves );
  73. float2 vWavesSum = vWaves.xz + vWaves.yw;
  74. // Edge (xz) and branch bending (y)
  75. float3 bend = animParams.y * fDetailAmp * abs(normal.xyz);
  76. bend.y = animParams.w * fBranchAmp;
  77. pos.xyz += ((vWavesSum.xyx * bend) + (wind.xyz * vWavesSum.y * animParams.w)) * wind.w;
  78. // Primary bending
  79. pos.xyz += animParams.z * wind.xyz;
  80. pos = normalize(pos) * origLength;
  81. return pos;
  82. }
  83. // Expand billboard and modify normal + tangent to fit
  84. inline void ExpandBillboard (in float4x4 mat, inout float3 pos, inout float3 normal, inout float4 tangent)
  85. {
  86. // tangent.w = 0 if this is a billboard
  87. float isBillboard = 1.0f - abs(tangent.w);
  88. // billboard normal
  89. float3 norb = normalize(mul(float4(normal, 0), mat)).xyz;
  90. // billboard tangent
  91. float3 tanb = normalize(mul(float4(tangent.xyz, 0.0f), mat)).xyz;
  92. pos += mul(float4(normal.xy, 0, 0), mat).xyz * isBillboard;
  93. normal = lerp(normal, norb, isBillboard);
  94. tangent = lerp(tangent, float4(tanb, -1.0f), isBillboard);
  95. }
  96. void TreeVertBark (inout VertexInput v)
  97. {
  98. v.positionOS.xyz *= UNITY_ACCESS_INSTANCED_PROP(Props, _TreeInstanceScale.xyz);
  99. v.positionOS = AnimateVertex(v.positionOS, v.normalOS, float4(v.color.xy, v.texcoord1.xy));
  100. v.positionOS = Squash(v.positionOS);
  101. v.color.rgb = UNITY_ACCESS_INSTANCED_PROP(Props, _TreeInstanceColor.rgb) * _Color.rgb;
  102. //v.normalOS = normalize(v.normalOS);
  103. //v.tangentOS.xyz = normalize(v.tangentOS.xyz);
  104. }
  105. void TreeVertLeaf (inout VertexInput v)
  106. {
  107. ExpandBillboard (UNITY_MATRIX_IT_MV, v.positionOS, v.normalOS, v.tangentOS);
  108. v.positionOS.xyz *= UNITY_ACCESS_INSTANCED_PROP(Props, _TreeInstanceScale.xyz);
  109. v.positionOS = AnimateVertex (v.positionOS, v.normalOS, float4(v.color.xy, v.texcoord1.xy));
  110. v.positionOS = Squash(v.positionOS);
  111. v.color.rgb = UNITY_ACCESS_INSTANCED_PROP(Props, _TreeInstanceColor.rgb) * _Color.rgb;
  112. // v.normalOS = normalize(v.normalOS);
  113. // v.tangentOS.xyz = normalize(v.tangentOS.xyz);
  114. }
  115. half ScreenDitherToAlpha(float x, float y, float c0)
  116. {
  117. #if (SHADER_TARGET > 30) || defined(SHADER_API_D3D11) || defined(SHADER_API_GLCORE) || defined(SHADER_API_GLES3)
  118. //dither matrix reference: https://en.wikipedia.org/wiki/Ordered_dithering
  119. const float dither[64] = {
  120. 0, 32, 8, 40, 2, 34, 10, 42,
  121. 48, 16, 56, 24, 50, 18, 58, 26 ,
  122. 12, 44, 4, 36, 14, 46, 6, 38 ,
  123. 60, 28, 52, 20, 62, 30, 54, 22,
  124. 3, 35, 11, 43, 1, 33, 9, 41,
  125. 51, 19, 59, 27, 49, 17, 57, 25,
  126. 15, 47, 7, 39, 13, 45, 5, 37,
  127. 63, 31, 55, 23, 61, 29, 53, 21 };
  128. int xMat = int(x) & 7;
  129. int yMat = int(y) & 7;
  130. half limit = (dither[yMat * 8 + xMat] + 11.0h) / 64.0h;
  131. //could also use saturate(step(0.995, c0) + limit*(c0));
  132. //original step(limit, c0 + 0.01);
  133. return lerp(limit*c0, 1.0h, c0);
  134. #else
  135. return 1.0h;
  136. #endif
  137. }
  138. half ComputeAlphaCoverage(float4 screenPos, float fadeAmount)
  139. {
  140. #if (SHADER_TARGET > 30) || defined(SHADER_API_D3D11) || defined(SHADER_API_GLCORE) || defined(SHADER_API_GLES3)
  141. float2 pixelPosition = screenPos.xy / (screenPos.w + 0.00001);
  142. pixelPosition *= _ScreenParams.xy;
  143. half coverage = ScreenDitherToAlpha(pixelPosition.x, pixelPosition.y, fadeAmount);
  144. return coverage;
  145. #else
  146. return 1.0;
  147. #endif
  148. }
  149. #endif