FluidCS11_ForceCS_Grid.hlsl 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. // RUN: %dxc -E main -T cs_6_0 %s | FileCheck %s
  2. // CHECK: threadId
  3. // CHECK: bufferLoad
  4. // CHECK: FMax
  5. // CHECK: FMin
  6. // CHECK: IMax
  7. // CHECK: IMin
  8. // CHECK: dot2
  9. // CHECK: Log
  10. // CHECK: Exp
  11. // CHECK: Sqrt
  12. // CHECK: bufferStore
  13. //--------------------------------------------------------------------------------------
  14. // File: FluidCS11.hlsl
  15. //
  16. // Copyright (c) Microsoft Corporation. All rights reserved.
  17. //--------------------------------------------------------------------------------------
  18. //--------------------------------------------------------------------------------------
  19. // Smoothed Particle Hydrodynamics Algorithm Based Upon:
  20. // Particle-Based Fluid Simulation for Interactive Applications
  21. // Matthias Müller
  22. //--------------------------------------------------------------------------------------
  23. //--------------------------------------------------------------------------------------
  24. // Optimized Grid Algorithm Based Upon:
  25. // Broad-Phase Collision Detection with CUDA
  26. // Scott Le Grand
  27. //--------------------------------------------------------------------------------------
  28. struct Particle
  29. {
  30. float2 position;
  31. float2 velocity;
  32. };
  33. struct ParticleForces
  34. {
  35. float2 acceleration;
  36. };
  37. struct ParticleDensity
  38. {
  39. float density;
  40. };
  41. cbuffer cbSimulationConstants : register( b0 )
  42. {
  43. uint g_iNumParticles;
  44. float g_fTimeStep;
  45. float g_fSmoothlen;
  46. float g_fPressureStiffness;
  47. float g_fRestDensity;
  48. float g_fDensityCoef;
  49. float g_fGradPressureCoef;
  50. float g_fLapViscosityCoef;
  51. float g_fWallStiffness;
  52. float4 g_vGravity;
  53. float4 g_vGridDim;
  54. float3 g_vPlanes[4];
  55. };
  56. //--------------------------------------------------------------------------------------
  57. // Fluid Simulation
  58. //--------------------------------------------------------------------------------------
  59. #define SIMULATION_BLOCK_SIZE 256
  60. //--------------------------------------------------------------------------------------
  61. // Structured Buffers
  62. //--------------------------------------------------------------------------------------
  63. RWStructuredBuffer<Particle> ParticlesRW : register( u0 );
  64. StructuredBuffer<Particle> ParticlesRO : register( t0 );
  65. RWStructuredBuffer<ParticleDensity> ParticlesDensityRW : register( u0 );
  66. StructuredBuffer<ParticleDensity> ParticlesDensityRO : register( t1 );
  67. RWStructuredBuffer<ParticleForces> ParticlesForcesRW : register( u0 );
  68. StructuredBuffer<ParticleForces> ParticlesForcesRO : register( t2 );
  69. RWStructuredBuffer<unsigned int> GridRW : register( u0 );
  70. StructuredBuffer<unsigned int> GridRO : register( t3 );
  71. RWStructuredBuffer<uint2> GridIndicesRW : register( u0 );
  72. StructuredBuffer<uint2> GridIndicesRO : register( t4 );
  73. //--------------------------------------------------------------------------------------
  74. // Grid Construction
  75. //--------------------------------------------------------------------------------------
  76. // For simplicity, this sample uses a 16-bit hash based on the grid cell and
  77. // a 16-bit particle ID to keep track of the particles while sorting
  78. // This imposes a limitation of 64K particles and 256x256 grid work
  79. // You could extended the implementation to support large scenarios by using a uint2
  80. float2 GridCalculateCell(float2 position)
  81. {
  82. return clamp(position * g_vGridDim.xy + g_vGridDim.zw, float2(0, 0), float2(255, 255));
  83. }
  84. unsigned int GridConstuctKey(uint2 xy)
  85. {
  86. // Bit pack [-----UNUSED-----][----Y---][----X---]
  87. // 16-bit 8-bit 8-bit
  88. return dot(xy.yx, uint2(256, 1));
  89. }
  90. unsigned int GridConstuctKeyValuePair(uint2 xy, uint value)
  91. {
  92. // Bit pack [----Y---][----X---][-----VALUE------]
  93. // 8-bit 8-bit 16-bit
  94. return dot(uint3(xy.yx, value), uint3(256*256*256, 256*256, 1));
  95. }
  96. unsigned int GridGetKey(unsigned int keyvaluepair)
  97. {
  98. return (keyvaluepair >> 16);
  99. }
  100. unsigned int GridGetValue(unsigned int keyvaluepair)
  101. {
  102. return (keyvaluepair & 0xFFFF);
  103. }
  104. //--------------------------------------------------------------------------------------
  105. // Force Calculation
  106. //--------------------------------------------------------------------------------------
  107. float CalculatePressure(float density)
  108. {
  109. // Implements this equation:
  110. // Pressure = B * ((rho / rho_0)^y - 1)
  111. return g_fPressureStiffness * max(pow(density / g_fRestDensity, 3) - 1, 0);
  112. }
  113. float2 CalculateGradPressure(float r, float P_pressure, float N_pressure, float N_density, float2 diff)
  114. {
  115. const float h = g_fSmoothlen;
  116. float avg_pressure = 0.5f * (N_pressure + P_pressure);
  117. // Implements this equation:
  118. // W_spkiey(r, h) = 15 / (pi * h^6) * (h - r)^3
  119. // GRAD( W_spikey(r, h) ) = -45 / (pi * h^6) * (h - r)^2
  120. // g_fGradPressureCoef = fParticleMass * -45.0f / (PI * fSmoothlen^6)
  121. return g_fGradPressureCoef * avg_pressure / N_density * (h - r) * (h - r) / r * (diff);
  122. }
  123. float2 CalculateLapVelocity(float r, float2 P_velocity, float2 N_velocity, float N_density)
  124. {
  125. const float h = g_fSmoothlen;
  126. float2 vel_diff = (N_velocity - P_velocity);
  127. // Implements this equation:
  128. // W_viscosity(r, h) = 15 / (2 * pi * h^3) * (-r^3 / (2 * h^3) + r^2 / h^2 + h / (2 * r) - 1)
  129. // LAPLACIAN( W_viscosity(r, h) ) = 45 / (pi * h^6) * (h - r)
  130. // g_fLapViscosityCoef = fParticleMass * fViscosity * 45.0f / (PI * fSmoothlen^6)
  131. return g_fLapViscosityCoef / N_density * (h - r) * vel_diff;
  132. }
  133. //--------------------------------------------------------------------------------------
  134. // Optimized Grid + Sort Algorithm
  135. //--------------------------------------------------------------------------------------
  136. [numthreads(SIMULATION_BLOCK_SIZE, 1, 1)]
  137. void main( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
  138. {
  139. const unsigned int P_ID = DTid.x; // Particle ID to operate on
  140. float2 P_position = ParticlesRO[P_ID].position;
  141. float2 P_velocity = ParticlesRO[P_ID].velocity;
  142. float P_density = ParticlesDensityRO[P_ID].density;
  143. float P_pressure = CalculatePressure(P_density);
  144. const float h_sq = g_fSmoothlen * g_fSmoothlen;
  145. float2 acceleration = float2(0, 0);
  146. // Calculate the acceleration based on neighbors from the 8 adjacent cells + current cell
  147. int2 G_XY = (int2)GridCalculateCell( P_position );
  148. for (int Y = max(G_XY.y - 1, 0) ; Y <= min(G_XY.y + 1, 255) ; Y++)
  149. {
  150. for (int X = max(G_XY.x - 1, 0) ; X <= min(G_XY.x + 1, 255) ; X++)
  151. {
  152. unsigned int G_CELL = GridConstuctKey(uint2(X, Y));
  153. uint2 G_START_END = GridIndicesRO[G_CELL];
  154. for (unsigned int N_ID = G_START_END.x ; N_ID < G_START_END.y ; N_ID++)
  155. {
  156. float2 N_position = ParticlesRO[N_ID].position;
  157. float2 diff = N_position - P_position;
  158. float r_sq = dot(diff, diff);
  159. if (r_sq < h_sq && P_ID != N_ID)
  160. {
  161. float2 N_velocity = ParticlesRO[N_ID].velocity;
  162. float N_density = ParticlesDensityRO[N_ID].density;
  163. float N_pressure = CalculatePressure(N_density);
  164. float r = sqrt(r_sq);
  165. // Pressure Term
  166. acceleration += CalculateGradPressure(r, P_pressure, N_pressure, N_density, diff);
  167. // Viscosity Term
  168. acceleration += CalculateLapVelocity(r, P_velocity, N_velocity, N_density);
  169. }
  170. }
  171. }
  172. }
  173. ParticlesForcesRW[P_ID].acceleration = acceleration / P_density;
  174. }