shader building is an absolute nightmare

hey guys,

Can someone explain the proper pipeline to work with shaders to avoid thousands of shader rebuilds with every single change?

Clearly I’m doing something wrong here. I’ve never seen anything like this in all the years of working in games. I have a case now where I made 3 materials being used on several objects via materials instances. Every time I change the slightest thing, it’s a mega long process of waiting for ~2500 shaders to compile. This is only three custom materials. I have plans for more, but I can’t imagine what the wait time will be every time I update a material. I think my case is a little special because i’m using material functions (which is what I’m working on right now) causing everything to rebuild because this function is being used in my three base materials, but I still can’t imagine this is normal. Using this in a AAA environment would bring development to a crippling halt.

Isn’t the point of a DDC to help this problem? I see that I have a DDC going that I assume is being used. The folder exists in the engine install folder (the default location). I never did anything manually to get this setup.

Also - is this because I made my material function in Unreal as opposed to coding one by hand in C++?

Any advice would be great!

thanks!

So this just happened - I hit apply to update my material function. Waited for ~2500 shaders to build. Re-imported a texture being referenced in it, hit save… now I’m waiting for ~2500 shaders to rebuild. This makes no sense at all. I didn’t even modify it and I have to wait for this again.

How many instructions is the material? And what do those functions do? To avoid compiling the material ever time you make a change try converting whatever you can to parameters and then iterate on the material instance of that base material.

If you use parameters and instances, update don’t require the shader to be rebuilt.

Here’s an example of how that was used in the Unreal Tournament Outpost map.

You don’t need to use Quixel in order to use that workflow.

Thanks guys,

This is basically exactly my workflow, but because my target platform is iOS, i separated my master material up a little to save on instructions where I don’t need them. For example - I have an OpaqueLit, OpaqueLit_AlphaMask and OpaqueLit_Emissive. This way I’m not calculating emissive on surfaces where I’m not using it and same for alpha masking.

What I’ve basically done is create a material function that’s acting as a faked post process, because unreal doesn’t support custom post processes (specifically the SceneTexture node) on any mobile platform (even though iOS fully supports that functionality). My material function is the data for my post processes which I’ve plugged into the emissive pass of my three master materials.

I’ve exposed many parameters (pretty much every single one) for the instances and also from a material collection because those “post process” values are global variables being modified by various blueprints. My opaque material has only 124 instructions so it’s pretty inexpensive.

When I say simple changes is cause tons of rebuilds, I mean something like removing a simple add node in the material. I know that can mean anything, so to be specific, at the end of my material right before the output i removed an addition of a small value and it cause every material to rebuild.

just wanted to keep you guys up to date. As predicted it was not the fault of the shaders at all, but because for whatever reason my DDC default settings were not setup for my project. When restarting the editor it would basically invalidate all the shaders and build them all again.

For global parameters you should use Material parameter collections. This way you can save lot of per object blueprint updating. Using Material Parameter Collections in Unreal Engine | Unreal Engine 5.3 Documentation