Cloth Simulation

Real-Time Physical Simulation of a Cloth in an Environment

Chetan Khanna

May 2023

Example image during simulation of a cloth
Example image during simulation of a cloth
Example image during simulation of a cloth

This project simulates the physics of a cloth based on a “mass-spring” philosophy. The cloth was represented by a mesh of vertices connected together by springs (of three types, each serving a different purpose: structural, shear, and bending). Simulating forces on these springs (and thus this grid) using physical laws (such as Hooke’s Law) realistically simulates the shapes and position of the entire cloth and visualize it.

I used Verlet integration was used to simulate the forces on these springs. In order to try and keep the simulation stable, Provot’s method to constrain the position of the springs at any time step was employed. This prevented the springs from “stretching out” just a little too far at some time step (which would eventually “balloon” as that addition force gets passed to the next spring) and the entire simulation “blowing up“.

I then implemented the ability for the cloth to intersect with spheres and planes in the scene. This enabled us to see how the cloth behaved when it collided with other objects.

After this, I also implemented the ability for the cloth to collide with itself. Since there was no checking for self collisions thus far, parts of the cloth could intersect and go through each other, which was physically unrealistic. In order to do this efficiently, I divided the cloth spatially into different “buckets” (based on a hash function I created) and put each vertex into a “bucket” (entry of our hashmap), and then for every point checked for collisions against the other points in that “bucket”. I then corrected points that were colliding. This improved the physical realism of the cloth—for example, enabling the cloth to fold on top of itself realistically when it collided with a plane.

The last part of the project was implementing shaders that allowed us to color the cloth in different ways. I implemented Blinn-Phong shading and Texture Mapping. I also implemented Bump and then Displacement Mapping, which used height maps to modify the normals and thus make the surface look bumpy. Displacement mapping went a step further: it made the surface actually be bumpy based on the height map by modifying the positions of the vertices. Our final use of the shaders was for environment-mapped reflections, allowing the cloth and sphere to effectively "mirror" the environment around us.

A cloth resting in the air, pinned in all four corners to imaginary points in space.
A cloth resting in the air, pinned in all four corners to imaginary points in space.

Experimenting with different constants

This section shows some results from this project. These results demonstrate the physically accurate nature of the simulation.

Reference view (default parameters)

This is what the cloth looks like with default parameters ks = 5000, damping set to 0.2% and density = 15.

Changing the spring constant ks

Increasing spring constant: ks = 50000

The cloth in the resting position with ks = 50000.
The cloth in the resting position with ks = 50000.

Increasing the spring constant from 5000 to 50000 did not appear to affect the speed at which the cloth “fell down” (at least significantly). However, the crease (at the upper part of the cloth) between the two pinned corners did become less prominent, and there are fewer creases (the cloth is straighter).

This is expected behavior; the springs require more force for any displacement, so the force of gravity is not causing as much of a displacement on the springs (or, perhaps more accurately, the force exerted by the lower strings on the upper ones isn’t affecting the displacement of the upper ones as much), thus causing the cloth to be less “stretchy” in a sense.

Decreasing spring constant: ks = 50

The cloth in the resting position with ks = 50.
The cloth in the resting position with ks = 50.

As expected, lowering the spring constant causes the cloth to be “stretchier”. There are multiple creases at the top now, rather than just one (and the dip between the two pinned corners is steeper). The cloth retains less of its shape, as can be demonstrated by the corners of the spring being very stretched out. This makes sense; it is the opposite of the case above, and thus even the “small” force applied by gravity affects the displacement of the springs more—and by one spring on the other).

Changing density

Increasing density: density = 1500

The cloth's final position with density = 1500. Normal shading enabled.
The cloth's final position with density = 1500. Normal shading enabled.

Increasing the density will increase the mass of the cloth.

Note how the increased density causes the cloth to drop more noticeably between the two pinned corners. This makes sense: a cloth density will mean the lower springs are pulling the upper springs down with more force (due to their larger mass).

(While the upper springs themselves may also have more mass, this doesn't outweigh the extra force of the lower springs—by the time we're at the top of the cloth, there are obviously many more springs pulling down on the cloth than pulling up on the cloth. “At the limit”, in other words, the mass of the upper spring would be virtually negligible compared to the mass of all the lower springs.)

For the same reasons, it also causes the cloth to appear “stretchier”. As expected (and for the opposite reason), the cloth will appear a lot less stretchy.

The cloth's final position with density = 1. Normal shading enabled.
The cloth's final position with density = 1. Normal shading enabled.

Impact of damping

A higher damping setting dd will slow down motion. During Verlet intgration, we multiply (1d)(1-d) with vtv_t (the velocity of the particle at time tt) when updating a particle's position for the new timestep; in other words, we scale down a particle's velocity at every timestep.

Damping drastically changes how quickly the cloth falls down, and all it’s movement (e.g. even the movement of the cloth’s springs between themselves).

Most noticeably, it also affects how much the cloth “oscillates” once it falls down. At lower damping settings, the cloth falls but then continues to oscillate at high amplitude and frequency. This makes sense; a lower damping setting means that the cloth doesn’t lose as much energy, and thus by the time it reaches the bottom it has far too much excess energy. It continues to oscillate for a long time, only losing a very minor amount of energy each time.

Because damping (obviously) also applies to the cloth’s springs, we also note how the cloth appears a lot less “smooth”. This is because the spring’s are moving much more “violently” when a force is applied on them (and this effect compounds and travels through springs—hence the continued “instability” that lasts for long). A higher damping settings tends to “smooth” out this effect by making the slight force one spring applies on the other at one moment in time not impact the spring’s next position as much.

Naturally, a high damping setting has the opposite effect, and all motion is slowed down. The cloth falls down very slowly, and barely oscillates around the bottom before coming to rest.

Illustration of the lack of damping: when the cloth first falls, it has so much energy that it is oscillating. Here the cloth is nearly 90 degrees offset from it’s rest point. Also note how the normals are often pointing in very different directions; a slight force applied by one spring on the cloth has a big impact on the rest.

The high damping setting creates a much smoother-looking cloth, and reduces the speed at which the cloth falls down. It also causes it to come to rest almost immediately.

Cloth-Sphere Interaction

This section implements a sphere in space and has the cloth interact physically with this sphere. The technical challenge involved here was to enable the cloth to handle collisions with other objects in a physically accurate manner while preserving the ability to render in real-time.

Results: Cloth rests on sphere, with varying ks

As we increase the spring constant value, the cloth gets stiffer (see the writeup of Part 1 for more details).

The cloth cannot "bend to the shape" of the sphere (and also be as affected by the force of gravity) at higher ks settings, so the cloth doesn't “drape down” as much.

The cloth, resting on the sphere, with ks = 5000. Notice how the cloth is “draping down” a lot.

The cloth, resting on the sphere, with ks = 50000. Notice how the cloth is not “draping down” when ks is set so high.

Addendum: Cloth Rests on Plane

This section shows the cloth interacting with a plane in space.

The cloth has collided with the plane and is now resting on the plane.
The cloth has collided with the plane and is now resting on the plane.

Self-Collisions

This section demonstrates the phsyical simulation once the cloth was able to interact with itself. Notice that the cloth can now collide with itself.

The following screenshots show a falling cloth colliding with itself (in chronologically descending order):

Impact of Spring Constant and Density on Cloth Self-Collisions

Varying Spring Constant ks

Increasing ks, in effect, increases the "rigidty" of the cloth. Therefore, the cloth doesn't “want to fold in on itself” too much, which means that when the cloth tends to have fewer folds when it is lying on the plane.

This makes sense; a higher ks means a spring on the cloth would have to exert much more force to displace the other spring (and eventually create a fold in this scenario) than it has to with a low ks.

For the same reason, the impact of a self-collision is “smaller” (i.e. more visible) when ks is set to a higher value. This means that the cloth looks somewhat smoother when ks is set to a high value.

The cloth has far fewer folds when we set ks = 100000.

The cloth has more folds when ks = 30000. Furthermore, notice the cloth looks somewhat more "dimpled”.

Even more folds (and “dimples”) are visible when ks is lowered further; this is consistent with the fact we are simulating a less rigid cloth.

Varying density

Increasing the density increases the mass of the cloth. As the mass of the cloth increases, the cloth tends to fold in on itself more, rather than flatly on the ground. Lower density cloths also tend to be smoother.

The cloth, generally resting on the plane, with density = 1.

The cloth, generally resting on the plane, with density = 100.

The cloth, generally resting on the plane, with density = 1000.

Shaders

Shaders are utilities that let us perform calculations in bulk as we render our scenes on the display. Our shaders calculate two things: the positions of vertices of our object (i.e. positions of vertices on the mesh) or the color of pixels (not exactly pixels—but rather the outputs of the objects created by the shader's calculations of vertex positions).

Since this data has to be calculated in bulk (for every vertex on the mesh/for every “sample" we take), but is not necessarily big (shaders only return a vector), a GPU is ideally optimized to carry out these calculations quickly and in a highly parallelized manner. Shaders, therefore (in our case), use the GPU to perform these calculations. This enables us to speed up our render times significantly.

Blinn-Phong Shading Model

The Blinn-Phong shading model is a model that allows us to compute the appearance of a surface based on the light in the scene. While it is not a physically correct shading model, it nevertheless approximates (and accounts for) a lot of the visual effects of light that we see.

The alternative approach, raytracing, is a newer technology and much more computationally expensive, so the Blinn-Phong shading model is actually one of the “default” ways of shading things (calcualting the appearance of a surface) in computer graphics today.

The model has three different components: ambient, diffuse, and specular. Each component is responsible for calculating a different visual effect, and these effects (components) are combined together to complete the model and thus compute a somewhat realistic appearance of a surface.

The ambient component is responsible for shading based on the “base” level of light (i.e. not on light sources). The diffuse component is based on light that comes from a light source but then is reflected out from the surface equally in all directions. The specular component is the most directionally-dependent, and responsible for the little bright spots (that move significantly based on the camera) from light sources you see on objects.

Ambient Only

Diffuse Only

Specular Only

Entire Blinn-Phong Model

Texture Shader with Red-White Cloth Texture

Bump Mapping and Displacement Mapping

Bump Mapping vs Displacement Mapping

Bump Mapping.

Displacement mapping.

With bump mapping, we only modify the normal vectors according to the height map—while with displacement vectors, we take this a step further and also modify the positions of the vertices themselves (i.e. actually change the geometry of the mesh). Displacement mapping is less "fake" compared to bump mapping, therefore.

This is clearly visible in the results. The cloth isn’t “draping down smoothly” with displacement mapping, but rather “fluctuating” based on the texture we used. The exact correspondence of heights/final vertex locations can change based on the height map we are using; a different height map (for a given texture) will mean the cloth will rest (physically) in a slightly different way. I chose to use the r component of the color vector stored at the texture coordinates for the vertex we were operating on, as suggested in the spec.

Coarse vs fine mapping

Bump mapping with coarse mesh (left), fine mesh (right)

Displacement mapping with coarse mesh (left), fine mesh (right)

Displacement mapping is able to take advantage of the finer mesh, since it changes the position of the vertices according to the height map (as explained above, bump mapping does not do this—it just changes the position of the normals and hence the shading, but not the physical locations of the vertices in space). This enables us to see a difference between the coarse and fine mesh. The difference is not nearly as pronounced with bump mapping.

Mirror Shader

On Cloth and Sphere

On Sphere

On Cloth

Bonus: Custom Shaders

I combined the Blinn-Phong model with texturing in order to have a nicely lit effect, in addition to simulating some transparency based on the lighting itself.

The result of combining Blinn-Phong with texturing made the renderings of texture cloths look a little bit more realistic, reminding me of a slight “beach towel” look.

For implementing transparency, I did some research and it turned out to be easy: reducing the alpha parameter would reduce the opacity. At first, I reduced this to 0.5 uniformly. The first two screenshots show this.

Finally, I then made this “shading-dependent", so that the larger stronger the diffuse component in the Blinn-Phong shading model, the more "solid" the object would look. Because this was done in a "proportional" manner, this meant that the areas with stronger specular shading would actually appear to be more transparent.

Custom shader screenshots

Notice the specular highlights from the light, indicating Blinn-Phong shading, on the textured cloth.

Notice the cloth is slightly transparent at the bottom.

Custom shader with per-vertex lighting-based transparency

Notice how parts that would typically have strong specular highlights are quite transparent; the other parts (which are mostly illuminated by diffuse lighting) are quite solid.