[SHELVED] Material Layering Feedback for 4.19

We definitely understand the concerns about duplicating assets - I believe what we will probably do is create a way to apply layers to meshes in the scenes, so that you can create a layer once and either use it in a stack or use it by itself in the scene.

Our current plan is to have this functionality in 4.20, but we don’t have any specifics on the implementation yet. It’ll be in the release notes and the documentation when we do, though!

So, right now we are primarily iterating on workflow and UI, and haven’t yet done substantial optimization passes. Our goal is for this to not add any additional runtime cost (and to save costs for well-constructed material layer stacks).

There may be some additional shader compilation at design time, for thumbnails, for toggling visibility, or when adding layers - we will definitely take a look at making this as smooth as possible though.

Thanks!

Hi ther, :slight_smile: I have quick question:

Case: I have few ML (material layers) in my material, and i’m using different MLB (blend layer) for each. My material instance override texture param in each material and set one and same texture in every MLB type.
Question is: Is the mask texture loaded only once and cost as much as one mask?.
(in previous setup i used material functions for blend with input for mask, which was param in main material)

Thank you so much for your answers, Shadow.Storm. Glad to hear there’ll be optimizations, and a possibility of being able to use Layers just as Material Instances.

On another note, I watched the Q&A part of the stream, and searched this topic for “landscape”, but it’s still not clear to me whether the new system works with Landscape or not in 4.19. Should be a matter of creating a Blend function with a Landscape Layer Blend node, right? Well it doesn’t work for me - the layers don’t appear in the Paint section of the Landscape Mode tab.

I’m new to ue4, but do have extensive experience in ue3. So trying to get up to speed on the differences. I have read the documentation and watched the videos on this material layers feature but I must be missing something obvious, in the example material shown on the /video it shows what looks like a collapsed material property root/result node, but I have not been able to figure out how to convert it to that, or if that is a different expression or what.

Oh nm I found it… Use Material Attributes in the details of the material itself…

Hello everyone. Having fun with it. Here is a bit of new system abuse:

Awesome stuff ! If you have any feedback from the workflow so far, please let us know. :slight_smile:

Sure! I have few bugs to report (some features might actually be not implemented yet, so I can’t call them bugs), and some ideas:

  1. Cannot copy and paste colors (right mouse click doesn’t bring the menu to copy and paste color, so to duplicate the color I have to bring the color palette and get the color with the color picker.
  2. Dropping layers and blends to slots is broken since final UE4.19 release (worked in last preview), works only with the “assign arrow”
  3. Some times layers stops to update and have to reassign it to slots one more time to make it to work again, then again after some time it stops to update again. Especially happens when I duplicated the material instance and when I start to modify it, instead of creating a whole new instance.
  4. Would be nice to have possibility to change order of layers without reassigning them to layer stack from scratch, because you don’t want to lose any parameters changed in the instance. Maybe right mouse menu with “move up” and “move down” layer?
  5. Would be nice if we could pass the texture sample from one layer to another, or from blend to layer, sometimes I just want to change a bit the color, or rougness multiplier, but what I’m doing here is just my personal madness.
  6. What about parallaxed materials? I didn’t test it out yet, so I can’t tell what happens. Usually I had problems to lerp parallaxed textures. It’s hard to blend textures with different UV tiling without making a floating look.
  7. Will be possible to assign a layer, like a regular material to a mesh in the future, since I would prefer to have one library of materials and not two?

Anyway, I LOVE IT! This is really helpful, and has huge potential!

These two issues both happen because the layer panel uses a lot of custom logic so some of the common features need adding in on top. We’ve logged both of these and we’ll hopefully get to them for a future release!

Unfortunately this is a known issue and one we’d really like to fix asap. If you have a reproduction case please let us know and we’ll add it to the bug tracker.

In the latest internal version you can now drag and drop layers to re-order them and this should appear in the next major release. :slight_smile:

That’s an interesting use-case at least. One thing we would like to improve down the line is adding custom attributes to the material nodes, so hopefully in a future version (not 4.20!) you would be able to add a new pin on the “SetMaterialAttributes” node, say “Dirt Mask”, then read that back with a “GetMaterialAttributes” node in layers and blends as needed. You can technically do this in code right now but it’s global rather than per material.

We’re also looking at a better way to share parameters between layers and blends by making them global or linked. We haven’t nailed down what this will look like yet but that might also work for this problem.

Parallax-mapped materials should work fine with the system but it’s another case where the best solution might be a custom attribute, e.g. “Height Map”, which you could write on multiple layers and then blend them with a new graph that reads the height from both layers and performs a better blend. If this was global enough a feature you could definitely consider doing this in code either by adding a new. For a somewhat obscure example of a quick hack showing how it can be done right now:


I would begin by adding code for my local custom attributes at the bottom of FMaterialAttributeDefinitionMap::InitializeAttributeMap in MaterialShared.cpp:


AddCustomAttribute(FGuid(0xF7CB7613, 0x525A4F09, 0x8C129555, 0x7757A8AA), TEXT("UserCustom1"), TEXT("UserCustom1"), MCT_Float, FVector4(0,0,0,0));
AddCustomAttribute(FGuid(0xF7CB7614, 0x525A4F0A, 0x8C129556, 0x7757A8AB), TEXT("UserCustom2"), TEXT("UserCustom2"), MCT_Float3, FVector4(0,0,0,0));
AddCustomAttribute(FGuid(0xF7CB7615, 0x525A4F0B, 0x8C129557, 0x7757A8AC), TEXT("UserCustom3"), TEXT("UserCustom3"), MCT_Float3, FVector4(0,0,0,0));

This will create three new pin options on the Get and Set MaterialAttributes nodes called “UserCustom1”, “UserCustom2” and “UserCustom3”. The types and default values are at the end of each definition and the GUID at the start must be unique as it’s used to funnel the data through the material.

So after recompiling we can now use that custom attribute we added. Making a new layer below I’ve hooked a texture parameter up to UserCustom1 which I’m reserving in my workflow for data used in blends (calling it “HeightMask” would be acceptable to keep it clearer).

Then I can use the same data in a new blend graph:

And from there we can use those assets in a stack. Below here I have a base green layer and I’m blending in our new red layer based on the height (UserCustom1) is specified:

Some useful tips:

  • Notice how the parameters are still found and the data is passed through.
  • If the pin isn’t connected it won’t be used and doesn’t add any overhead to the final shader where it’s unused.
  • Any layers that don’t set a value for the custom data will get the default value we set earlier when adding the attribute, FVector4(0,0,0,0), just like other attributes.
  • If you open the graph on a project without your custom code the attributes will swap to “Missing” as they don’t recognize the type.

As above, this is something that’s really not user-friendly right now, ideally you’d be able to just type in a name within the material or make something like an Enum asset to use but we’re not quite there yet. :slight_smile:

This is definitely something that’s been a common request so we’ll see what we can add to improve usability here.
Thanks again for all the feedback!

I will definitely try this out :smiley:
Thank you so much for all your answers, and of course your great work.
Looking forward for the awesome updates :slight_smile:

I’m getting the following error and seems to resolve when I disable some layers (right now I only have 5 total)

[SM5] /Engine/Generated/Material.ush(19891.2-41): warning X3206: implicit truncation of vector type
[SM5] /Engine/Generated/UniformBuffers/Material.ush(41,14-41): error X4510: maximum ps_5_0 sampler register index (16) exceeded

That’s not a layers specific error and likely caused by having too many unique samplers in the material. The easy way to avoid it for non-mobile platforms is to set the Sampler on your Texture Sample (and similar) expressions to either “Shared: Wrap” or “Shared:Clamp” rather than the asset-specific sampler that’s set by default. This will bring the number down.

Usually you have something like 16 image samplers per shader in DirextX9.0c, to overcome the problem set the textures as shared, like said:

Hard to phrase what my request ist.
We have SetMaterialAttributes and GetMaterial Attributes. We can select single Material Inputs (BaseColor, Metallic ,Specular etc) from these.
Is there a possibility to have these Selections as a Parameter for LayerBlends? It would make LayerBlends more flexible, since we can Blend multiple Material Inputs together.

params.jpg

Hah! Exactly what I wished in post #101 and #102!
As for now we cannot create a single master layer to not waste too many instructions on various switches, either if in a layer or in a blend function, since it creates a massive shader compilation.
I have already created myself around 10 variants of master layers with “albedo, specular, roughness”, “albedo, metallic, normal” etc, etc…
Enabling/disabling the attributes through parameters would be wonderful. See my illustration.

By the way** Raildex **here is what you can do in a blend function. But as I said before, the compilation will go skyrockets. Right click and view image in new tab to see full resolution.
blend.jpg

I’d like this aswell, with an easy way to rebake the material layer and swap between the mesh using the material layer and map based material.

And yeah, i know where you want to go with it, and I agree. For instance; for dust I need- albedo and roughness only, for some scratches- roughness is enough, for some wetness- specular and roughness, for paint chips- albedo, roughness and normal, for plastic- albedo, specular and roughness, for metal- metallic and roughness, and so on.
Why would you want the attribute parameter switches? Well, because sometimes you have to tweak some values to match more precisely the surface below. For example dust needs sometimes a tiny bit of specularity if the surface below is quite reflective, or you just decided at some point to add some bumpiness to a paint layer, and your master layer didn’t provide that? You don’t want to add it, because at this point it will make heavier all the other instances that relays on it…
That’s why would be really great to be able to enable/disable attributes as parameters in a layer. Why not in a blend function? Well, not only because it would be easier to set up, but also because you wouldn’t repeat the whole complicated process of splitting attributes in each blend.