Why does vertex displacement create gaps between faces within the same mesh?

I used URP Shader Graph to create a vertex displacement shader (wind effect) and cannot figure out why gaps in the character mesh are introduced.

My mesh is exported from blender to .fbx and imported into Unity. In blender, it is shaded flat. I checked there are no duplicated vertices at the edges. In Unity, the weld vertices option is also checked. I also tried to export smooth shaded, the results are the same.

For the vertex displacement effect, I only want to affect certain vertices on my character mesh, such as the hair and cloth, which are all attached to the same mesh. I store the information in UV1, so each vertex either maps to black or white on the same color atlas.

In my URP shader graph, if the vertex maps to a white color, I give it an offset calculated from a scrolling noise texture.

No issues for color shading, I am using flat shading with a color atlas, so vertices may share the exact same spot on the atlas UV0. I sample the UV0 coords and map to the color atlas texture.

You can see only some vertices are moving, but there the seams are, there are gaps. I cannot figure out why this is happening, can anyone help please? Thanks!

Unity_WORWZMjQ3O

“Weld Vertices” only works if all properties are the same, including UVs, Normals, Tangents, and Vertex Color (Unity - Manual: Model tab (unity3d.com)). Blender shows them as a single vertex, but at the engine level, each vertex can only have one UV coordinate, normal, etc. and so they must be duplicated along sharp edges or at the boundaries of UV islands. That is probably what’s happening here, although I’m not sure why it works on other parts which also use flat shading and therefore should also have duplicate vertices with different normals.

Thanks, I understand now that there needs to be duplicated vertices for each face for flat shading. I overlooked it.

But even if a single vertex position is duplicated into 3 or 4 vertices for each of the adjoining faces, during the vertex pass, why won’t every “same” vertex still compute to the same new displaced position? Their UV positions are all the same, and I only used UV positions to calculate the new positions.

After debugging the issue more, I realized that I developed a misconception about UV mapping due to working with color atlas and flat shading for a long time.

UV maps are used for mapping surfaces from a 3D model to a 2D plane. When using flat shading and color atlas technique, I am used to scaling the faces into a single point and move the point to the color for that face, and this caused me to think that I can set vertex information using UV map. This inadvertently caused missing information in my UV map which resulted in wrong shader calculation when a vertex cannot be found in my wind UV map.

I now changed my method to use Vertex Color instead to set information for my vertices that I want wind to affect. In blender, I can set vertex color in Texture Painting > Vertex Painting mode.

In URP shader graph, there is a Vertex Color node that can be used in the Vertex Shader pass.

Problem solved.

1 Like