I am studying hair card deformation code in HairCardsDeformation.usf. Looking at PIX captures in different scenarios is challenging my understanding of the code, so I wanted to get some clarification on the data that’s being passed around.
In our setup, we have a skeletal mesh with a groom asset comprising of 3 groups of hair cards: one with simulation disabled, and two with simulation enabled. Since the skeletal mesh has skinning enabled, I am looking at shader code corresponding to the permutation vector `PERMUTATION_DYNAMIC_GEOMETRY` set to 1.
My understanding so far is as follows:
- hair cards deformation as a holistic process applies both mesh skinning and groom simulation offsetting to guide vertices. For this specific shader, rest-pose and deformed (mesh skinning + sim offsetting) guide positions are in GuideRestPositionBuffer and GuideDeformedPositionBuffer respectively.
- ComputeDynamicGeometryOffset extracts the sim offsetting part of the deformation by doing a change of basis on rest and deformed guide vertices from world-space to rest and deformed triangle space respectively, and returning the difference. In my understanding, this decouples the mesh skinning from the sim offsetting, so a groom asset with simulation disabled should return all zeroes here, regardless of whether there is skinning going on
- the dynamic geometry offset of two adjacent guides is then calculated and interpolated according to the card vertex’s GuideLerp factor
- the rest-pose card vertex is fetched from CardsRestPositionBuffer; mesh skinning is then applied to it using the same trick as ComputeDynamicGeometryOffset, where it is first expressed in rest triangle space, and these same coordinates are then used as-is for a change of basis from deformed triangle space back to world-space
- the interpolated dynamic geometry offset is then added to it, applying the sim offsetting part of the deformation
- additionally, tangents and normals only have mesh skinning applied to them and not sim offsetting
Looking at a PIX capture, I was able to pinpoint the dispatch corresponding to the hair group that has simulation disabled (`HairCardsInterpolation > HairInterpolation(Cards) > HairStrands::CardsDeformation(Dynamic)`). Looking at values, I was expecting to always get all zeroes back from ComputeDynamicGeometryOffset, but this was not the case. I was able to confirm that using no animation would indeed make it so the deformed triangle is always the same as the rest triangle, but the behaviour of the dynamic geometry offset still eludes me.
Is my understanding correct? How is it that ComputeDynamicGeometryOffset is not all zeroes with simulation disabled?