Fur Shader Passes

From Warren's Fast Fur Shader
Revision as of 18:30, 12 September 2023 by Warren (talk | contribs) (Added descriptions of Skin and Undercoat passes.)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

My shader draws the fur as geometric layers, stacked on top of each other.

Rendering Passes

GPU programs (ie. "shaders") render objects in passes. Each pass runs through the shader pipeline, from start to finish (ie. from mesh to pixels), before another pass can start.

Fast Fur requires 3 mandatory passes per frame, with shadows and complex light sources each requiring 1 more.

Why not only 1 mandatory pass?

Because 3 passes is faster!

Pass 1 - The Skin

The first version of my shader did everything in 1 pass, because that's what other fur shaders were doing.

I was then asked to add some expensive lighting effects, like specular lighting and normal maps. I did, and the shader's speed dropped by more than half. Yikes!

The compromise I decided to try rendering only the skin "expensively". To do that, I had to split the Skin and Fur off into a separate passes. Then I speed-tested it against the original, simpler, 1-pass version.

Guess which one was faster?

The more complex, "expensive" looking version.

...

Um, wut?

That wasn't what I was expecting, lol..., but I'll take it!

As far as I can tell (and this really is just a guess!), rending the opaque skin at the same time as the mostly see-through fur results in the GPU texture caches missing a lot. So it's actually faster to render the skin completely separately, in its own pass, than to try to draw it at the same as the other fur layers.

The speed increase is so great, in fact, that it more than offsets the speed decrease of rending the skin "expensively". So it was a win-win discovery for both speed and quality!

Pass 2 - The Undercoat

One of the speed tricks added in v2.0 was to move the skin outwards as you got further away. You can't see the bottom layers of fur when you get farther away, so moving the skin outwards allowed the shader to skip rendering them.

It worked great! It was like a ~30% speed boost with no noticable loss of quality!

Except for the seams... yeah, those are very much a noticable loss of quality

Moving the skin outwards creates gaps if your UV seams don't line up perfectly, which virtually nobody's does.

On most avatars, it's okay, because the fur is usually thick enough where the seams are that it hides them pretty well.

But for a lot of people, the seams are really, really bad. For them, the option to turn, "Body Expansion when Far" off was added, but that means ~30% lower quality because of lower layer density.

The compromise I decided to try was to render the bottom fur layer as opaque and move that outwards, instead of the skin.

Visually, this works, because the skin fills in any visible seams.

Performance-wise, it doesn't, likely for the same reason it was slower to render the skin at the same time as the fur. They are just too different looking.

So the Undercoat pass was added.

Pass 3 - The Fur