1617a3babSopenharmony_ci/* 2617a3babSopenharmony_ciThe MIT License (MIT) 3617a3babSopenharmony_ci 4617a3babSopenharmony_ciCopyright (c) 2022 Sascha Willems 5617a3babSopenharmony_ci 6617a3babSopenharmony_ciPermission is hereby granted, free of charge, to any person obtaining a copy 7617a3babSopenharmony_ciof this software and associated documentation files (the "Software"), to deal 8617a3babSopenharmony_ciin the Software without restriction, including without limitation the rights 9617a3babSopenharmony_cito use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10617a3babSopenharmony_cicopies of the Software, and to permit persons to whom the Software is 11617a3babSopenharmony_cifurnished to do so, subject to the following conditions: 12617a3babSopenharmony_ci 13617a3babSopenharmony_ciThe above copyright notice and this permission notice shall be included in all 14617a3babSopenharmony_cicopies or substantial portions of the Software. 15617a3babSopenharmony_ci 16617a3babSopenharmony_ciTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17617a3babSopenharmony_ciIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18617a3babSopenharmony_ciFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19617a3babSopenharmony_ciAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20617a3babSopenharmony_ciLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21617a3babSopenharmony_ciOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22617a3babSopenharmony_ciSOFTWARE. 23617a3babSopenharmony_ci*/ 24617a3babSopenharmony_ci 25617a3babSopenharmony_ci#version 450 26617a3babSopenharmony_ci 27617a3babSopenharmony_cistruct Particle { 28617a3babSopenharmony_ci vec4 pos; 29617a3babSopenharmony_ci vec4 vel; 30617a3babSopenharmony_ci vec4 uv; 31617a3babSopenharmony_ci vec4 normal; 32617a3babSopenharmony_ci float pinned; 33617a3babSopenharmony_ci}; 34617a3babSopenharmony_ci 35617a3babSopenharmony_cilayout(std430, binding = 0) buffer ParticleIn { 36617a3babSopenharmony_ci Particle particleIn[ ]; 37617a3babSopenharmony_ci}; 38617a3babSopenharmony_ci 39617a3babSopenharmony_cilayout(std430, binding = 1) buffer ParticleOut { 40617a3babSopenharmony_ci Particle particleOut[ ]; 41617a3babSopenharmony_ci}; 42617a3babSopenharmony_ci 43617a3babSopenharmony_ci// todo: use shared memory to speed up calculation 44617a3babSopenharmony_ci 45617a3babSopenharmony_cilayout (local_size_x = 10, local_size_y = 10) in; 46617a3babSopenharmony_ci 47617a3babSopenharmony_cilayout (binding = 2) uniform UBO 48617a3babSopenharmony_ci{ 49617a3babSopenharmony_ci float deltaT; 50617a3babSopenharmony_ci float particleMass; 51617a3babSopenharmony_ci float springStiffness; 52617a3babSopenharmony_ci float damping; 53617a3babSopenharmony_ci float restDistH; 54617a3babSopenharmony_ci float restDistV; 55617a3babSopenharmony_ci float restDistD; 56617a3babSopenharmony_ci float sphereRadius; 57617a3babSopenharmony_ci vec4 spherePos; 58617a3babSopenharmony_ci vec4 gravity; 59617a3babSopenharmony_ci ivec2 particleCount; 60617a3babSopenharmony_ci} params; 61617a3babSopenharmony_ci 62617a3babSopenharmony_cilayout (push_constant) uniform PushConsts { 63617a3babSopenharmony_ci uint calculateNormals; 64617a3babSopenharmony_ci} pushConsts; 65617a3babSopenharmony_ci 66617a3babSopenharmony_civec3 springForce(vec3 p0, vec3 p1, float restDist) 67617a3babSopenharmony_ci{ 68617a3babSopenharmony_ci vec3 dist = p0 - p1; 69617a3babSopenharmony_ci return normalize(dist) * params.springStiffness * (length(dist) - restDist); 70617a3babSopenharmony_ci} 71617a3babSopenharmony_ci 72617a3babSopenharmony_civoid main() 73617a3babSopenharmony_ci{ 74617a3babSopenharmony_ci uvec3 id = gl_GlobalInvocationID; 75617a3babSopenharmony_ci 76617a3babSopenharmony_ci uint index = id.y * params.particleCount.x + id.x; 77617a3babSopenharmony_ci if (index > params.particleCount.x * params.particleCount.y) 78617a3babSopenharmony_ci return; 79617a3babSopenharmony_ci 80617a3babSopenharmony_ci // Pinned? 81617a3babSopenharmony_ci if (particleIn[index].pinned == 1.0) { 82617a3babSopenharmony_ci particleOut[index].pos = particleOut[index].pos; 83617a3babSopenharmony_ci particleOut[index].vel = vec4(0.0); 84617a3babSopenharmony_ci return; 85617a3babSopenharmony_ci } 86617a3babSopenharmony_ci 87617a3babSopenharmony_ci // Initial force from gravity 88617a3babSopenharmony_ci vec3 force = params.gravity.xyz * params.particleMass; 89617a3babSopenharmony_ci 90617a3babSopenharmony_ci vec3 pos = particleIn[index].pos.xyz; 91617a3babSopenharmony_ci vec3 vel = particleIn[index].vel.xyz; 92617a3babSopenharmony_ci 93617a3babSopenharmony_ci // Spring forces from neighboring particles 94617a3babSopenharmony_ci // left 95617a3babSopenharmony_ci if (id.x > 0) { 96617a3babSopenharmony_ci force += springForce(particleIn[index-1].pos.xyz, pos, params.restDistH); 97617a3babSopenharmony_ci } 98617a3babSopenharmony_ci // right 99617a3babSopenharmony_ci if (id.x < params.particleCount.x - 1) { 100617a3babSopenharmony_ci force += springForce(particleIn[index + 1].pos.xyz, pos, params.restDistH); 101617a3babSopenharmony_ci } 102617a3babSopenharmony_ci // upper 103617a3babSopenharmony_ci if (id.y < params.particleCount.y - 1) { 104617a3babSopenharmony_ci force += springForce(particleIn[index + params.particleCount.x].pos.xyz, pos, params.restDistV); 105617a3babSopenharmony_ci } 106617a3babSopenharmony_ci // lower 107617a3babSopenharmony_ci if (id.y > 0) { 108617a3babSopenharmony_ci force += springForce(particleIn[index - params.particleCount.x].pos.xyz, pos, params.restDistV); 109617a3babSopenharmony_ci } 110617a3babSopenharmony_ci // upper-left 111617a3babSopenharmony_ci if ((id.x > 0) && (id.y < params.particleCount.y - 1)) { 112617a3babSopenharmony_ci force += springForce(particleIn[index + params.particleCount.x - 1].pos.xyz, pos, params.restDistD); 113617a3babSopenharmony_ci } 114617a3babSopenharmony_ci // lower-left 115617a3babSopenharmony_ci if ((id.x > 0) && (id.y > 0)) { 116617a3babSopenharmony_ci force += springForce(particleIn[index - params.particleCount.x - 1].pos.xyz, pos, params.restDistD); 117617a3babSopenharmony_ci } 118617a3babSopenharmony_ci // upper-right 119617a3babSopenharmony_ci if ((id.x < params.particleCount.x - 1) && (id.y < params.particleCount.y - 1)) { 120617a3babSopenharmony_ci force += springForce(particleIn[index + params.particleCount.x + 1].pos.xyz, pos, params.restDistD); 121617a3babSopenharmony_ci } 122617a3babSopenharmony_ci // lower-right 123617a3babSopenharmony_ci if ((id.x < params.particleCount.x - 1) && (id.y > 0)) { 124617a3babSopenharmony_ci force += springForce(particleIn[index - params.particleCount.x + 1].pos.xyz, pos, params.restDistD); 125617a3babSopenharmony_ci } 126617a3babSopenharmony_ci 127617a3babSopenharmony_ci force += (-params.damping * vel); 128617a3babSopenharmony_ci 129617a3babSopenharmony_ci // Integrate 130617a3babSopenharmony_ci vec3 f = force * (1.0 / params.particleMass); 131617a3babSopenharmony_ci particleOut[index].pos = vec4(pos + vel * params.deltaT + 0.5 * f * params.deltaT * params.deltaT, 1.0); 132617a3babSopenharmony_ci particleOut[index].vel = vec4(vel + f * params.deltaT, 0.0); 133617a3babSopenharmony_ci 134617a3babSopenharmony_ci // Sphere collision 135617a3babSopenharmony_ci vec3 sphereDist = particleOut[index].pos.xyz - params.spherePos.xyz; 136617a3babSopenharmony_ci if (length(sphereDist) < params.sphereRadius + 0.01) { 137617a3babSopenharmony_ci // If the particle is inside the sphere, push it to the outer radius 138617a3babSopenharmony_ci particleOut[index].pos.xyz = params.spherePos.xyz + normalize(sphereDist) * (params.sphereRadius + 0.01); 139617a3babSopenharmony_ci // Cancel out velocity 140617a3babSopenharmony_ci particleOut[index].vel = vec4(0.0); 141617a3babSopenharmony_ci } 142617a3babSopenharmony_ci 143617a3babSopenharmony_ci // Normals 144617a3babSopenharmony_ci if (pushConsts.calculateNormals == 1) { 145617a3babSopenharmony_ci vec3 normal = vec3(0.0); 146617a3babSopenharmony_ci vec3 a, b, c; 147617a3babSopenharmony_ci if (id.y > 0) { 148617a3babSopenharmony_ci if (id.x > 0) { 149617a3babSopenharmony_ci a = particleIn[index - 1].pos.xyz - pos; 150617a3babSopenharmony_ci b = particleIn[index - params.particleCount.x - 1].pos.xyz - pos; 151617a3babSopenharmony_ci c = particleIn[index - params.particleCount.x].pos.xyz - pos; 152617a3babSopenharmony_ci normal += cross(a,b) + cross(b,c); 153617a3babSopenharmony_ci } 154617a3babSopenharmony_ci if (id.x < params.particleCount.x - 1) { 155617a3babSopenharmony_ci a = particleIn[index - params.particleCount.x].pos.xyz - pos; 156617a3babSopenharmony_ci b = particleIn[index - params.particleCount.x + 1].pos.xyz - pos; 157617a3babSopenharmony_ci c = particleIn[index + 1].pos.xyz - pos; 158617a3babSopenharmony_ci normal += cross(a,b) + cross(b,c); 159617a3babSopenharmony_ci } 160617a3babSopenharmony_ci } 161617a3babSopenharmony_ci if (id.y < params.particleCount.y - 1) { 162617a3babSopenharmony_ci if (id.x > 0) { 163617a3babSopenharmony_ci a = particleIn[index + params.particleCount.x].pos.xyz - pos; 164617a3babSopenharmony_ci b = particleIn[index + params.particleCount.x - 1].pos.xyz - pos; 165617a3babSopenharmony_ci c = particleIn[index - 1].pos.xyz - pos; 166617a3babSopenharmony_ci normal += cross(a,b) + cross(b,c); 167617a3babSopenharmony_ci } 168617a3babSopenharmony_ci if (id.x < params.particleCount.x - 1) { 169617a3babSopenharmony_ci a = particleIn[index + 1].pos.xyz - pos; 170617a3babSopenharmony_ci b = particleIn[index + params.particleCount.x + 1].pos.xyz - pos; 171617a3babSopenharmony_ci c = particleIn[index + params.particleCount.x].pos.xyz - pos; 172617a3babSopenharmony_ci normal += cross(a,b) + cross(b,c); 173617a3babSopenharmony_ci } 174617a3babSopenharmony_ci } 175617a3babSopenharmony_ci particleOut[index].normal = vec4(normalize(normal), 0.0f); 176617a3babSopenharmony_ci } 177617a3babSopenharmony_ci} 178