Substrate - Feedback Thread

Here is an update on what we ended up doing. So we understand that the behavior that we had in 5.6 was actually a bug, since you cannot have IOR 0 physically, so we are not expecting that behavior to come back. However, since this is a big issue for us, we had to find a workaround for it. we realized, if we turn off all lighting channels of the glass meshes, since it wont receive any light from the skylight, it wont reflect the skylight as well, so we directly see the backdrop mesh. However this means that the edges of the glass will appear darker, since there is no light in the scene that can bounce on them. To fix that, we enabled “affect dynamic indirect lighting” on the backdrop mesh, so with emissivity of the already existing hdri texture on the backdrop mesh, we see some minor light bounces on the edges of the glasses. This is a compromise since ideally we don’t want the backdrop to contribute anything to the lighting of the scene, that must be handled by the skylight actor in our lighting plugin, but since typically the backdrop intensity is not that high (otherwise it looks fully white) the difference is negligible. I should mention that we also changed our backdrop material a bit as well and started using Pathtracing ray type swtich to only select the main and indirect specular rays. This way at least rest of the lighting is not affected by the backdrop. However it would be fantastic if in the future we will get the option to separate the reflection rays from GI rays. As of now reflection and GI are tied together which is a big limitation.

I’m having some trouble with substrate translucence. I cant get any distortion happening, either through IOR or a normal map. Followed 3 tutorials and still nothing.
Im using 5.7.4.
Project settings - Substrate- all ticked except experimental
Sample material-

Does anybody have any ideas?

There is a RefractionMethod to setup on the material now. Defaults to None.

Yeah, sorry, I didnt add that part of my setup, but it is set to IOR, tried the newer IOR based on F0 too, still nothing.

So I finally got translucency working, I had the ‘effects’ scalability too low. However, my glass windows (simple cuboid) get this distorted offset ‘copy’ of the inside (that isnt meant to be a floating extra frame). At this point it should be more reflection than refraction (F0=0.04, F90=1). I asked AI, that kept pointing to screen space reflections, but I’ve completely disabled that in the material and Post Process.
Any help would be appriciated!

Just disable refraction on thin flat translucent materials. A plane of glass really doesn’t need it.

1 Like

So thats the intended look in 5.7? My glass all looked fine in 5.6 with the same materials

You may want to try switching your refraction method similarly to how the documentation describes:

The refraction implementation may have changed from 5.6 to 5.7, I am unsure.

“Intended” is not that cut and dry. When light enters a pane of glass and refracts, it bends. But then it passes back out of the glass and bends back to the same direction it originally headed in (with a slight positional offset based on the thickness of the glass).

When you use screen space refraction, it usually only accounts for the first bend, which distorts the image and causes the issue you’re seeing. The second bend that corrects the ray can be added but is kind of pointless - it would make far more sense to simply ignore the refraction on a flat pane of glass instead. Window glass is specifically engineered to minimize refraction. Just disable it.
On a curved surface, however, the ray will not bend back to its original vector - so the effect works better. But it is still a screen space approximation and will be prone to artifacts.

This issue has been around for as long as screen space refraction - not just in Unreal Engine and not just substrate.

I wouldn’t say my curved glass is behaving any better. That distortion seems like the opposite of what I should see. In fact, setting the IOR to a negative does seem to be producing the right distortion, although that has artifacts. All Scalability settings are on Epic, and I increased the PostProcess refraction bounces to 4 to see if that would sort it, but didnt.

Curved glass still won’t be accurate it’s just better because most viewers don’t actually understand how the light should bend on a curved surface so when it’s all distorted they’ll likely accept it.

The only way to get accurate refraction is to use ray-traced translucency. But that will come with other quality hits elsewhere, in addition to the performance hit.. so it’s not a clear cut win.

Another option is to use cube maps. This is how the famously good looking Half Life Alyx bottle and liquid shaders handled refraction, so it can be very convincing for bottles and glasses. Here’s an old example I made ages ago:

1 Like

That looks like a good solution, I’ll try this instead. I asked my brother (who has no artistic tendancies at all) to test my scene, he picked up on it straight away. Should have known he would head straight to the drinks trolley :joy: . Apologies for derailing the thread.

1 Like

@SebHillaire
Thank you for the amazing feature! I have a question and a feature request regarding the shadow rendering of Toon BSDF. Is it possible to apply cel-shading to shadows cast from other meshes onto this material? Or conversely, shadows cast by this material onto other materials?
Currently, the self-shadowing on the mesh using this material looks beautifully toon-shaded. However, shadows cast by other meshes onto this material remain photorealistic.
This breaks the visual consistency, and I would love to find a way to fix it. This issue also occurs with multi-part meshes, where a shadow from one part cast onto another part looks realistic rather than stylized.

Are there any plans to support this feature in the future? Or is there already a way to achieve this that I might be missing?
Of course, features like contour or outlines that others have mentioned are also useful and important aspects of toon shading. However, those can often be supplemented through techniques such as post-processing. In the case of my request, though, I believe this is an essential requirement for using the Toon BSDF node in a commercial game production environment.
Thanks again for your great work!

Hello,

Thanks for the feedback!

Shadow: there is no such plan sorry. Shadow has no information about the caster “style”. We already have different shadow look based on the tech used (CSM, SM, VSM, RT) and that is already complex for soft shadow effects. So shadows will likely remain a reaction from a surface material according to its style for now.

Silhouette/Edges are not part of the BSDF definition as of today. We would like to extend that but it is to be designed for some use cases. As you noted, post processes can already be used, as well as the inverted hull technique.


In general, unfortunately, we all have to understand that no BSDF / shading model will be able to accommodate for all art directions and possibilities. That is the reality, especially for real time application and games. We want the toon BSDF to be a solid base for NPR but for anything specific and too intricate & complex in the engine as a general features (as in: a feature should not slow everything down), one may need to modify the engine source. We will do our best to extend and open up the tech and extend possibilities, but it is sure we cannot answer all the ask and needs I have already seen everywhere on the internet when it comes to that toon BSDF and NPR. Everyone has some special definition for what should happen with NPR. We try to gather them all as much as possible for all of our and everyone else games while keeping it performant.

2 Likes

Thank you for the response! I’m currently exploring the Toon Profile shadow settings you created, as they seem capable of achieving the result I’m looking for.

I’m still trying to fully grasp how it works, so would it be possible for you to share a simple example of how PatternUVs in ToonBSDF and ShadowHatchingPatternTexture in the Toon Profile are intended to be used together?

I’d like to use it as a small demo to better understand the underlying workflow and principle.

For the edge outline, it would be best if it could be a general material feature rather than only part of the Toon BSDF. For example, if someone wants to combine a toon and realistic shaded object in a scene, and wants to unify them with an outline. It would help a lot. Post-process based ouline is limited when it comes to screen pixels, and depending on the object distance to the screen, it can cover the whole object as I move away from the camera. So, having a solution on a surface level is way better in general.

I do not want that thread to diverge into documentation :slight_smile: . Today documentation for toon is on on the tooltips (detail panel property, node input pins). Anything unclear can be reported.

That being said, here is an exemple of setup:

Basically the pattern UVs is used to sample the texture 2D space and the shadow value (affected by transmittance controlled using Shadow Extinction on the profile) is input to the mapping Shadow Hatching Pattern Distribution Ramp that then selected which channel from the texture to apply as shadow (R, G, B and A). Here the texture has some light horizontal hatching in R, vertical x horizontal in G, VxHxDiagonal in B and fully black in A.

This could be achieved a many ways also but that is the current way.

Please read the tool tips for more details.

1 Like

Hello, I have an issue with a Substrate enabled project.
I migrated to a Subtrate enabled project and I also tried converting the project in place (then enabling Substrate, and converting the material to Substrate) a project with a ‘Legacy’ material from UE5.6 to UE5.7.4
And my instructions went from:
Base Pass Shader: 262 instructions

To
Base Pass Shader: 1043 Instructions

Some Info: Nanite, Lumen, VSM, TSR, Deffered.

Legacy Material
Material Domain: Surface
Blend Mode: Opaque
Shading Model: Subsurface

It went from this, UE5.1 to UE5.6:

To this, UE5.7.4:

Thank you very much.

1 Like

Hello,

Good question.

Not sure how your material looks like after but I guess you use substrate nodes now and plug in the Front Materials? Given that the material is red, it means that you are using the adaptive gbuffer?

Here is a small instruction count measurement I have done on a Subsurface profile only simple materials using the shader stat window on one of our test project with some settings:

Substrate0 Gbuffer0

  • Root node input VS 148 - PS 218

  • Substrate Slab VS xxx - PS xxx - slab node ignored when substrate disabled

Substrate1 Gbuffer0 (optimized Substrate, enabled by default and our games run with it, similar cost to when substrate is disabled, instr count is not always a good representative of cost)

  • Root node input VS 148 - PS 301

  • Substrate Slab VS 148 - PS 297

Substrate1 Gbuffer1 (high quality cinematic, needs more optimisation, I guess this is what you are using?)

  • Root node input VS 148 - PS 1105

  • Substrate Slab VS 148 - PS 1077

-
As you can see different complexity, different base pass cost. A few extra notes:

  • Substrate compiles in more instructions due to special packing, conversion from legacy to Substrate for different shading model; and also because it can do more.

    • Just keep in mind that not all those instructions are executed.

    • And we work toward optimizing the unused one away when possible.

  • This increase in cost as you can see is especially true for the adaptive GBuffer that also has more aggressive and specialized packing for some specific cases.

    • More general, higher cinematic quality, all the features

    • It needs more optimisation to be shippable at this stage.

  • The stat window gives clue about cost but it is not a precise representative cost, this stat will be less and less representative the more we have feature and use cases to handle in pixel shaders.

3 Likes

Thank you very much for your reply.

I had no experience with Substrate, and I spent the last couple of days going through the documentation, talking with other devs and doing some testings, and I came to understand that Substrate works differently from the Legacy material.

Substrate with ‘Adaptive GBuffer’ will add 781 additional instructions to a material using the Shading Model: Subsurface, even if you just plug in a simple 3Vector or a scalar. Or even if a simple scalar is connected to the Substrate Slab BSDF: SSS MFP pin.
With ‘Blendable GBuffer’ it will add 187 additional instructions.

I also came to understand that there isn’t something I can do on my end to optimize further or get rid of those additional instructions. Except of course to not use SSS or not connect anything in the SSS MFP pin.
Also that the ‘Shader Complexity View’ is not intended to be use with Substrate, but only with Legacy materials.

Thank you very much for your time, and sorry for the unnecessary inconvenience.

1 Like