August 1, 2016

Rolling Displacement: Cheap AND Good-Looking Cloth for Console and PC

88 instructions - The number of instructions necessary to render beautiful silk cloth
75 instructions - Vertex shader cost of 3D cloth displacement

I have spent years trying to get APEX cloth to work on characters without needing NVIDIA's APEX integration with Maya or 3DS Max, but I cannot figure out how to authorize it, nor have I seen anyone else do it. In my open world project, Jake, the main character was always butt-naked. He was intended to have a red flowing cape. My folk's chargin with having a naked character and insistence that he wear something made me decide to try a different tactic: cloth displacement and normal calculation from textures. And surprisingly, the results from this method look even better than low-density APEX simulations.



The overall gist of this method is to offset sine and cosine waves flowing down the cloth by textures to flow in a unique pattern, transform from local space to world space and combine them to form the resulting vertex displacement, and using the sine data to drive a normal calculation. To the best of my knowledge, nobody has come up with a displacement/normal driven technique like this before. I'm calling this method "Rolling Cloth" due to the way the sine waves roll with the curvature of bends in the cloth rather than across them.

The benefits of this method are:
  • Extraordinarily cheap and detailed cloth displacement (great for console, mobile, and PC, assuming the API can handle texture displacement)
  • Rolling normals calculation looks great on low-poly cloth, even with no displacement at all
  • Highly scaleable to intended hardware
  • Normal calculation is fairly accurate
  • Artistically driven by textures for great flexibility in final results
  • Looks great with smaller textures (64-128 pixels)
  • Easily supports tiling cloth texture normals
The limitations of this method are:
  • Requires API to be capable of running textures to vertex displacement
  • Wind is manually driven by attributes in local space, not automatic in world space
    • Oddly enough, this is why the shader does not support triangle explosion through tessellation, because transforming from local to world space is incompatible with tessellation
  • The cloth is NOT simulated, so it will pass through world objects and characters
  • Movement rolls with bends in the fabric instead of across them

The whole material setup and finished result. Not too complicated, but looks great!
UVs on my cloth are set up so I can use a simple texture coordinate gradient as a mask and flow direction. In the mask, black areas will be swayed before white areas. The mask may require some fiddling to get right. For the trigonometry waves, I suggest the Face and Vertical waves are Sine and Cosine of the same period so you get a nice self-preserving circular motion. The negative of the first sine wave will just yield an unnatural linear displacement diagonally. The Lateral wave should be different than the first two swaying back and forth. If you want to prevent the cloth from looping, you can adjust the lateral motion or add more waves here at different periods.
The strengths of the Face/Lateral/Vertical transforms are purely visual. Eyeball it. If it looks right, it is right. The normals calculation, though, works the best when divided by the number of  transforms, and when it's scaled to their intensity. You can replace the 0,0,1 in the normals generator with a tiling normal map and it will work just as well. That "Normal of Mask" is actually a normal map of the grayscale mask. It's important the mask and normals are smooth, so don't be afraid to use a gaussian blur or low-res textures for them.
Multiply each wave times the mask, then add them together for the normals calculation. For the transform, multiply each transform by its corresponding Wave*Mask result, then simply add the results together. For this cloth, I wanted a silky cloth, so I used a 0.7 semi-metallic level and 0.6 roughness. You can mess with these numbers for different types of silk. Subsurface looks the best when I multiply the color by 0.2. This material is Two-sided, and using the Two-sided shading model. Cloth shading can yield nice cloth results as well. You can even use an opacity mask to show holes through the cloth.

No comments:

Post a Comment