Groom imprecisions

Hello !

We are facing some sort of precision issue with groom.

A groom on a creature’s ears is having points moving independently even though the binding is static.

It also happens on other parts of the body, and we can see it clearly when we’re in close-up and the animation of the underlying geometry is subtle.

I made a repro project to show the issue.

It contains 3 groom assets:

- one representing the original groom on both ears

- one with only one ear

- one with both ears but also a strand quite apart from the others

A level and level sequence is setup, with all grooms and a camera.

It also contains a folder MovieRenders with renders of the 3 groom assets.

And a folder original_data with alembic files.

We can observe with the original groom that some points of some strands are moving independently from the strand itself.

A render confirms it because it’s noisy.

With the groom on one ear only, there are no such movements, or at least a lot less perceptible.

The last groom is to show how degraded the quality of the strands are when a small strand is quite apart from the others.

This of course is not a good practice but it emphasize what appears to be a precision issue, maybe due to compression of the strands points for memory gains ?

What do you think about this issue ?

Would there be a fix to do ? Less compression maybe ? (as an option, for animation industry needing quality over memory usage)

We could also split more the grooms, but having issues on such short distances would mean to have lots of groom parts.

Thanks a lot !

Maxime

[Attachment Removed]

I found out about the CVar r.HairStrands.CompressedPosition, but it is already disabled.

[Attachment Removed]

I now understand that strand points are encoded on 16bits and are “localized” to their groom asset’s bounding box, which helps keeping precision in 16bits only. Unfortunately, it seems to be not enough for our needs :(.

I hardly see myself doing modifications to support 32bits encoding of strands points, as it would mean massive change in the engine ^^’

Would you consider adding such an option ? Much like the one existing to compress even more.

Or maybe the actual issue we see is not about this precision ?

Thanks !

Maxime

[Attachment Removed]

Hi Maxime,

Indeed this is likely related to the position encoding. The encoding is local to the bounding box (or to the first triangle if you are using binding). As you hinted it, this means you have some control to that: if you split your grooms into smaller groups (not different assets, just different groups), tight in space, you will reduce this kind of imprecision.

As you said, adding 32bits could be possible, but is a very invasible change that would won’t do/take on our side.

You can see where the position offset lives by using the Lit>Groom>RootBinding view mode. You can hover the position offset on the right, to see the rest/deformed position offsets (Cyan: rest, Purple: deformed).

[Image Removed]Single ear:

[Image Removed]Double ears

[Image Removed]

I hope this makes sense.

/Charles.

[Attachment Removed]

Hi,

Indeed, this is going to work differently with Nanite curve (precision is down the cluster encoding, which is controllable).

Same for binding, it will have to work differently with Nanite. We haven’t started to investigate that part yet.

/Charles.

[Attachment Removed]

I hope so as well :slight_smile:

/Charles.

[Attachment Removed]

Hi,

Technically it could be possible, this is just a non-trivial change to do and this is not something we are going to purse I believe.

/Charles.

[Attachment Removed]

Getting back to this. The failing example you gave is exaecerbing the issue (the “apart” strands) is really far from the ears. Do you have actual assets/example you could share where this starts to be problematic? I have some potential simpler/non-invasive solution, but I need to know the rough bound you are dealing with to see if this is practical or not.

The proposed solution would be to use fixed precision rather than floating precision, which would distribute the error evently, making the issue less pronouce. For doing that, we introduce some max extend. The simplest version of that is that these extend could be fixed if all your assets fix under 2/4m for instance.

Any way if you have some real problematic assets , that, would be great :slight_smile:

/Charles.

[Attachment Removed]

Thanks! For some reason, I can’t download the file you shared. It’s shown as “The file is no longer available.” Coudl you try to reshare them?

Thank you!

/Charles.

[Attachment Removed]

Hello!

I attached a simple solution, which improve visually your use case, but as the drawback to limit asset size to a +/-1m. I tried to increase that range, but the lack of precision come back, and you can see the hair moving slightly. So I’m not quite sure this will fit all your use case. When this solution does not work, it manifest as hairs all over the place :slight_smile:

You can turn on/off it in Engine\Shaders\Shared\HairStrandsDefinitions.h

#define HAIR_POSITION_FIXEDPOINT 1

You need to recompile the engine each time you do that. I will rebuild the grooms and groom bindings assets automatically when the value change.

/Charles.

[Attachment Removed]

Hi,

I bite the bullet and did the 32bit implementation we talked at the beginning of the thread. The change is actually fairly limited in term of code change. This should be more robust thatn the change I posted earlier.

Cheers,

/Charles.

[Attachment Removed]

Great to hear :slight_smile:

There is no immediate plan for this, but I’ll see if that makes sense.

Cheers,

/Charles.

[Attachment Removed]

Hi,

Thanks for confirming the source of the issue. And for the debug view of the actual offset used.

I understand this is a big change that you probably do not really need in the engine - at least for games.

For the cinema industry though, it’s not a small feature to have.

Maybe the future with Nanite curves will allow for more precisions ?

Anyway, thanks !

Maxime

[Attachment Removed]

Okey, thanks for the heads-up !

Hoping to have less haggle on this one day :slight_smile:

[Attachment Removed]

Hello again :slight_smile:

I was just thinking of something: if the solution to keep 16bits and have no imprecisions is to split the grooms in small groups, wouldn’t it be possible to do it automatically in the groom asset ?

You are already doing some chunking of the data, so I wonder if there could be an automatic chunking of a certain cube volume with each their own offset, so we keep the precision without sacrificing the workflow ?

Maxime

[Attachment Removed]

Hello !

Here is a better example that we have even though we split the groom.

This is only part of one arm/hand, and with an animation that stretch a little the geometry we can see the instabilities.

That would be awesome if we could have something less pronounced. We do have assets of limited sizes, so 2/4m is a good approximation of the maximum I think.

Thanks a lot !

Maxime

[Attachment Removed]

Here is the project again.

[Attachment Removed]

It worked. Thanks! :slight_smile:

/Charles.

[Attachment Removed]

Hello !

Great news ! I will try that asap and let you know :slight_smile:

When you say it limits “asset size to ~1m”, you mean hair groups or groom assets ? I guess hair group but just asking to be sure ^^

Thanks!

Maxime

[Attachment Removed]

Yes, hair groups.

/Charles.

[Attachment Removed]