Groom binding precision issue

Hello!

We’re facing an issue with the groom binding on short fur. The algorithm is creating triangle-shaped patterns on the fur when the underlying geometry deforms.

See the repro project and the following images (two versions provided, one with long furs and one with short furs relaxed to put in evidence the triangle patterns):

The fur on rest pos:

long

[Image Removed]

short relaxed

[Image Removed]

The fur deformed by Unreal:

long

[Image Removed]

short relaxed

[Image Removed]

The fur deformed by Houdini and imported as a groom cache:

long

[Image Removed]

short relaxed

[Image Removed]

I believe the issue is that only one frame coordinate is computed per-triangle, so every strand on a triangle gets the exact same transformation ?

And so when two neighbour triangles are deforming somewhat differently it creates this breaking pattern ?

Could an improvement of this be that the transformation of each strand be computed individually via a smoothed frame coordinate between the three points of the triangle ? Using barycentric coordinates as weight.

Thanks in advance !

Maxime

[Attachment Removed]

Steps to Reproduce
Open the level sequence and observe that the unreal binding is creating triangle-shaped patterns while the houdini groom cache is staying smooth.

[Attachment Removed]

Indeed, when normals are available, the tangent frame is reconstructed based on the current triangle’s vertices. This means the same tangent frame is shared for all the hair lying on the same triangle. When normals are available (I don’t recall when we introduced that probably 5.6), the tangent frames use the interpolated normal to reconstuct a smooth surface, and alleciate the artifact you showed.

I don’t see any attached project. Would you mind sharing it?

Thank you!

/Charles.

[Attachment Removed]

It seems to work all fine in 5.8. So I supposed you are missing some change. It looks like the normal interpolation was in 5.6, but there was a bug in the geometry cache, causing the normal buffer to be incorrect under certain condition. IIRC, this happens when the geometry cache has topology changes while playing its animation. I believe there is an option on import to enforce a fixed topology. Could that be the answer?

Otherwise you could try to integrate the fix from CL 44065777 (Github).

[Image Removed]

/Charles.

[Attachment Removed]

I tested in our 5.6 stream to be as close as possible as your case, but I couldn’t reproduce the issue as far as I can tell.

I attached a video of what I’m seeing.

/Charles.

[Attachment Removed]

Hi, thanks for the details. I could see and reproduce the issue in 5.6. Technically we would need to vertex tangent info for interpolating the tangent frame smoothly. But due limit in storage space this is not possible. I did some small change which encode a prefered tangent orientation, and seems to produce better result. I attached the shader changes, that you need to decompress in Engine\Shaders\Private\HairStrands.

Let me know if that work for your.

/Charles.

[Attachment Removed]

I tried to do a larger change to pipe the actual mesh tangent vectors and use it during the interpolation, but it seems there are some seams (see the red line having divergent direction for some of the vertices in the picture below). Thus it feels this approach won’t work as well.

[Image Removed]In the past, projects encountering that artifact, increased the surface’s tesselation. So I think you will have to resort to this as well.

/Charles.

/Charles.

[Attachment Removed]

Hello Charles !

So I did tests with subdiv, it does help reduce the clumping effect overall but it’s still messy triangle-wise.

Though I discovered that using a guide cache where guides are bound to the geometry cleanly (using Houdini in this case) helps a lot !

The result is very clean, so we might go this way if we can’t fix the binding algorithm.

But we still have an issue with that, guides are interpolated in time when using temporal samples and we want no motion blur.

I didn’t see a way to control that, so I’ll make another ticket here.

Thanks !

Maxime

[Attachment Removed]

Ok, thank you for the update!

/Charles.

[Attachment Removed]

Hi,

For visiblity to other, I protopyped an approach using the underlying vertex tangent basis. As mentioned before, this is a relatively invasive change. I attached a zip containing all the necessary changes for 5.6. With that change I get smooth tangent basis for the rendering strands, and the triangle shapes are no longer visible.

/Charles.

[Attachment Removed]

Hello Charles !

Sorry about that, I thought I uploaded the repro project but seems like not..

Here it is.

Thanks a lot !

[Attachment Removed]

It happens so that this fix is already implemented in our build, I had seen it in the commit history and thought it would be good to have it.

So… it does not fix the issue unforturnately.

The geometry is not changing its topology while playing the animation, and I’m not sure what option you’re referring to.

I tried the “Apply Constant Topology Optimizations”, without luck.

I also have the “Recompute Normals” toggled (without it, I had completely broken normals and fur).

[Attachment Removed]

I think I still see the issue on your video, but not really sure as depending on the viewpoint we can see it better or not.

On the animation, the frame where we see it the most is 1011.

On your video you’re a little far I think, if you zoom in you’ll probably be able to see it better.

Let me know !

[Attachment Removed]

I can also reproduce the issue in a vanilla 5.7.4 freshly downloaded from the launcher.

[Attachment Removed]

Hello !

I tested your fixes, on the little patch of this ticket it works great, but unfortunately on the full groom and geometry of our character it creates lots of problems.

Initially (works ok but we can see the clumping induced by the main issue of this ticket)

[Image Removed]

With your fixes

[Image Removed]

Thanks !

[Attachment Removed]

Here is another alembic of the geometry patch animated like in our shot, in case you want to debug on simple data.

A good frame to look at is 1080.

[Image Removed]

Thanks !

Maxime

[Attachment Removed]

Hmm ok, too bad :frowning:

On my side, I also developed a binding system internally that we are using since a long time, and on this case I also have quite bad results even though I do some kind of smoothing. The result is different, less “triangulated”, but still wrong. Though Houdini is making it very good, might need to check how they do it.

Thanks for the insight on using subdiv, I’ll make some tests with that and let you know.

Thanks !

Maxime

[Attachment Removed]

done here: [Content removed]

[Attachment Removed]