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