Disney’s Dr. Facilier shadow effect in Unreal Engine 4

This weekend I stumbled upon a reddit post about Dr. Facilier’s interesting shadow in The Princess and the Frog and it inspired me to experiment with Forward shading in Unreal Engine 4 to re-create a similar effect in real-time shading. OP pointed out that The Shadow Man’s shadow changes the wallpaper his shadow is cast on. A subtle but quite interesting effect!

With Forward rendering enabled we have a different shading pipeline to play with instead of UE4’s default deferred pipeline, the one I was interested in is the LightAttenuation buffer. The exact available data with Epic’s new Forward rendering is still mostly unknown to me, a good reason to try this new shading pipeline as a Sunday tech-doodle!

The result:

The implementation is really quite basic, I used the LightAttenuationTexture available only in Forward-rendering of the engine to find which part of affected by light. To access this buffer you need to use the Custom-node in the material editor, and apply the following code:

return Square(Texture2DSampleLevel(LightAttenuationTexture, LightAttenuationTextureSampler, UV, 0));

“UV” is an input parameter (so make sure it’s added to the param list of the custom node) in which we feed the ScreenAlignedUVs node output.

For those interested, I found this snippet in the engine’s shader folder at …/4.14/Engine/Shaders/Common.usf and contains the function  GetPerPixelLightAttenuation(float2 UV);

Below is the crude sample of the material used in the GIF:

There is not a whole lot going on, simply blending between the wallpaper and the skull pattern based on the light attenuation value of that pixel is screenspace. The texture samplers use my WorldUVs material function which I’ve posted about some time ago.

The effect visualized with two-tone instead of textures:

This LightAttenuationTexture may not be the perfect source for detailed lighting information, but did the trick for this simple effect recreation. Baked light for example needs to sample the lightmap data (as light attenuation is available from dynamic lights only) But this proved good enough for my specific case of the shadowed wallpaper.

I have a few more forward rendering experiments I’d like to write about soon (including, Borderlands 3’s new crosshatching on a material level might require some forward shading magic. I tweeted about my first results earlier this week) But for now, the weekend is over and it’s back to actual game development!

Enjoy your week!

7 Comments

  1. That’s really interesting! I was looking into messing with forward rendering and fragment shaders but i read in the forums that ue4 isn’t really open to such things. I’m just starting out with that kind of programming. Any tips for messing with ue4 with fragment shading?

    • Hi George,

      I linked to the shader folder in the blog in case you’re wondering where the shader files are located, that’s where I find the specific names of samplers and buffers if I need something for my Custom HLSL implementations. I believe there is almost no official docs on this unfortunately. There are some built-in custom implementation such as the SpiralBlur node which are good references for learning some syntax and let you play around.

      As for knowing what to look for, I did learn a lot about Forward and deferred shading a long time ago, having a basic understanding of how the pipeline works will help a lot in finding the shader variables you need for your own effects.

      • Hiya, just giving this a try now and only the texture plugged into B in the lerp is coming through. Wasn’t sure what to put for the parameter that’s hooked up to the Power node (you called it LightAttPowerExp) so I bypassed that node temporarily but I’m still not getting anything. I put UV in for the input of the custom node like you said, too.

        The only other difference I have is that I don’t have the MF_WorldUVs nodes. couldn’t find them. i assume these are the nodes you mentioned that are from a previous post. do i need them for this to work?

      • Were there steps you had to do in the editor for the project as a whole to get it to work? Like set up some settings for the lights? I set everything to movable: the lights and the object with the material and the object casting the shadow and it’s still not working.

        • It’s for Forward rendering only, which you must set in the Project Settings. Do note that Forward shading is very different from the default Deferred. In my case any other differences didn’t matter since it was just a solo experiment, but for a full project it’s a serious trade-off.

          Also, yes the MF_WorldUVs is custom, it’s basically doing a simple UV layout on the objects, this isn’t required and you could just use regular UVs node.

  2. I tried to recreate the BP that shows on the picture. But when i applying the changes at the material editor, it said there is compilation error in the nodes and might now display apporpriately in feature level SM5. Unreal didn’t tell me what the problem exactly is and the shader doesn’t work at all. Have you ran into the same problem?

Leave a Reply