No Description

cloth.comp 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. #version 450
  2. struct Particle {
  3. vec4 pos;
  4. vec4 vel;
  5. vec4 uv;
  6. vec4 normal;
  7. float pinned;
  8. };
  9. layout(std430, binding = 0) buffer ParticleIn {
  10. Particle particleIn[ ];
  11. };
  12. layout(std430, binding = 1) buffer ParticleOut {
  13. Particle particleOut[ ];
  14. };
  15. // todo: use shared memory to speed up calculation
  16. layout (local_size_x = 10, local_size_y = 10) in;
  17. layout (binding = 2) uniform UBO
  18. {
  19. float deltaT;
  20. float particleMass;
  21. float springStiffness;
  22. float damping;
  23. float restDistH;
  24. float restDistV;
  25. float restDistD;
  26. float sphereRadius;
  27. vec4 spherePos;
  28. vec4 gravity;
  29. ivec2 particleCount;
  30. } params;
  31. layout (push_constant) uniform PushConsts {
  32. uint calculateNormals;
  33. } pushConsts;
  34. vec3 springForce(vec3 p0, vec3 p1, float restDist)
  35. {
  36. vec3 dist = p0 - p1;
  37. return normalize(dist) * params.springStiffness * (length(dist) - restDist);
  38. }
  39. void main()
  40. {
  41. uvec3 id = gl_GlobalInvocationID;
  42. uint index = id.y * params.particleCount.x + id.x;
  43. if (index > params.particleCount.x * params.particleCount.y)
  44. return;
  45. // Pinned?
  46. if (particleIn[index].pinned == 1.0) {
  47. particleOut[index].pos = particleOut[index].pos;
  48. particleOut[index].vel = vec4(0.0);
  49. return;
  50. }
  51. // Initial force from gravity
  52. vec3 force = params.gravity.xyz * params.particleMass;
  53. vec3 pos = particleIn[index].pos.xyz;
  54. vec3 vel = particleIn[index].vel.xyz;
  55. // Spring forces from neighboring particles
  56. // left
  57. if (id.x > 0) {
  58. force += springForce(particleIn[index-1].pos.xyz, pos, params.restDistH);
  59. }
  60. // right
  61. if (id.x < params.particleCount.x - 1) {
  62. force += springForce(particleIn[index + 1].pos.xyz, pos, params.restDistH);
  63. }
  64. // upper
  65. if (id.y < params.particleCount.y - 1) {
  66. force += springForce(particleIn[index + params.particleCount.x].pos.xyz, pos, params.restDistV);
  67. }
  68. // lower
  69. if (id.y > 0) {
  70. force += springForce(particleIn[index - params.particleCount.x].pos.xyz, pos, params.restDistV);
  71. }
  72. // upper-left
  73. if ((id.x > 0) && (id.y < params.particleCount.y - 1)) {
  74. force += springForce(particleIn[index + params.particleCount.x - 1].pos.xyz, pos, params.restDistD);
  75. }
  76. // lower-left
  77. if ((id.x > 0) && (id.y > 0)) {
  78. force += springForce(particleIn[index - params.particleCount.x - 1].pos.xyz, pos, params.restDistD);
  79. }
  80. // upper-right
  81. if ((id.x < params.particleCount.x - 1) && (id.y < params.particleCount.y - 1)) {
  82. force += springForce(particleIn[index + params.particleCount.x + 1].pos.xyz, pos, params.restDistD);
  83. }
  84. // lower-right
  85. if ((id.x < params.particleCount.x - 1) && (id.y > 0)) {
  86. force += springForce(particleIn[index - params.particleCount.x + 1].pos.xyz, pos, params.restDistD);
  87. }
  88. force += (-params.damping * vel);
  89. // Integrate
  90. vec3 f = force * (1.0 / params.particleMass);
  91. particleOut[index].pos = vec4(pos + vel * params.deltaT + 0.5 * f * params.deltaT * params.deltaT, 1.0);
  92. particleOut[index].vel = vec4(vel + f * params.deltaT, 0.0);
  93. // Sphere collision
  94. vec3 sphereDist = particleOut[index].pos.xyz - params.spherePos.xyz;
  95. if (length(sphereDist) < params.sphereRadius + 0.01) {
  96. // If the particle is inside the sphere, push it to the outer radius
  97. particleOut[index].pos.xyz = params.spherePos.xyz + normalize(sphereDist) * (params.sphereRadius + 0.01);
  98. // Cancel out velocity
  99. particleOut[index].vel = vec4(0.0);
  100. }
  101. // Normals
  102. if (pushConsts.calculateNormals == 1) {
  103. vec3 normal = vec3(0.0);
  104. vec3 a, b, c;
  105. if (id.y > 0) {
  106. if (id.x > 0) {
  107. a = particleIn[index - 1].pos.xyz - pos;
  108. b = particleIn[index - params.particleCount.x - 1].pos.xyz - pos;
  109. c = particleIn[index - params.particleCount.x].pos.xyz - pos;
  110. normal += cross(a,b) + cross(b,c);
  111. }
  112. if (id.x < params.particleCount.x - 1) {
  113. a = particleIn[index - params.particleCount.x].pos.xyz - pos;
  114. b = particleIn[index - params.particleCount.x + 1].pos.xyz - pos;
  115. c = particleIn[index + 1].pos.xyz - pos;
  116. normal += cross(a,b) + cross(b,c);
  117. }
  118. }
  119. if (id.y < params.particleCount.y - 1) {
  120. if (id.x > 0) {
  121. a = particleIn[index + params.particleCount.x].pos.xyz - pos;
  122. b = particleIn[index + params.particleCount.x - 1].pos.xyz - pos;
  123. c = particleIn[index - 1].pos.xyz - pos;
  124. normal += cross(a,b) + cross(b,c);
  125. }
  126. if (id.x < params.particleCount.x - 1) {
  127. a = particleIn[index + 1].pos.xyz - pos;
  128. b = particleIn[index + params.particleCount.x + 1].pos.xyz - pos;
  129. c = particleIn[index + params.particleCount.x].pos.xyz - pos;
  130. normal += cross(a,b) + cross(b,c);
  131. }
  132. }
  133. particleOut[index].normal = vec4(normalize(normal), 0.0f);
  134. }
  135. }