How it works...

We use 100 invocations per work group, 10 in each dimension. The first statement in the compute shader defines the number of invocations per work group:

layout( local_size_x = 10, local_size_y = 10 ) in; 

The uniform variables that follow define the constants in the force equations and the rest the lengths for each of the horizontal, vertical, and diagonal springs. The time step size is DeltaT. The position and velocity buffers are declared next. We define the position buffers at binding indexes 0 and 1, and the velocity buffers at indexes 2 and 3.

In the main function (step 4), we start by determining the number of particles in each dimension. This is going to be the same as the number of work groups times the work group size. Next, we determine the index of the particle for which this invocation is responsible for. Since the particles are organized in the buffers in row-major order, we compute the index by the global invocation ID in the y direction times the number of particles in the x dimension, plus the global invocation ID in the x direction.

In step 5, we initialize our force with the gravitational force, Gravity times the mass of a particle (ParticleMass). Note that it's not really necessary here to multiply by the mass since all particles have the same mass. We could just pre-multiply the mass into the gravitational constant.

In steps 6 and 7, we add the force on this particle due to each of the eight neighboring particles connected by virtual springs. For each spring, we add the force due to that spring. However, we first need to check to see if we are on the edge of the lattice. If we are, there may not be a neighboring particle (see the following diagram).

For example, in the preceding code, when computing the force due to the preceding spring/particle, we verify that gl_GlobalInvocationID.y is less than the number of particles in the y dimension minus one. If that is true, there must be a particle above this one. Otherwise, the current particle is on the top edge of the lattice and there is no neighboring particle above it. (Essentially, gl_GlobalInvocationID contains the particle's location in the overall lattice.) We can do a similar test for the other three horizontal/vertical directions. When computing the force for the diagonally connected particles, we need to check that we're not on a horizontal and a vertical edge. For example, in the preceding code, we're looking for the particle that is above and to the left, so we check that gl_GlobalInvocationID.x is greater than zero (not on the left edge), and that gl_GlobalInvocationID.y is less than the number of particles in the y direction minus one (not on the top edge):

Once we verify that the neighboring particle exists, we compute the force due to the spring connected to that particle and add it to the total force. We organized our particles in row-major order in the buffer. Therefore, to access the position of the neighboring particle, we take the index of the current particle and add/subtract the number of particles in the x direction to move vertically, and/or add/subtract one to move horizontally.

In step 8, we apply the damping force that simulates air resistance by adding to the total force DampingConst times the velocity. The minus sign here assures that the force is in the opposite direction of the velocity.

In step 9, we apply the Euler method to update the position and velocity based on the force. We multiply the force by the inverse of the particle mass to get the acceleration, then store the results of the Euler integration into the corresponding positions in the output buffers.

Finally, in step 10, we reset the position of the particle if it is located at one of the five pin positions at the top of the cloth.

Within the OpenGL render function (step 11), we invoke the compute shader multiple times, switching the input/output buffers after each invocation. After calling glDispatchCompute, we issue a glMemoryBarrier call to make sure that all shader writes have completed before swapping the buffers. Once that is complete, we go ahead and render the cloth using the positions from the shader storage buffer.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.16.147.124