Using DistanceToNearest in a material in multiple ways at once?

Hello!

I’ve been looking into ways to use the DistanceToNearestSurface node for a variety of uses. Most prominently, within my water/ocean shader. I’ve got a few ideas about how I might use the node within the same material, but ideally I would have the distance fields of certain objects effect the material in different ways to other objects. Is there any way of achieving this?

For example, one object might create a blue glow around it, while another would give off a red one? Simple example, as the intended effect would be far more complex than just a re-colour, but the idea is the same.

Obviously, if it were just a re-colour, I could use the object position in a Collection Parameter to colour the distance field in it’s local area, but that doesn’t quite cut it, as these effects could potentially overlap, and I don’t want to store the position of every potential object that could interact with the material (which could be hundreds). Another example would be: Some objects create ripples in the material, others only affect a flow map, and so on.

Any advice here would be greatly appreciated.

A quick thought, could certain objects output a distance field into a separate channel? Is there a way of designating a channel for certain distance fields? And then I could pull out the result with a component mask? Probably an oversimplified thought method, as I’m not super familiar with how they’re generated.

I dont know of a way to do this, but I have a very rough idea/concept, which i am interested to hear people thoughts on:
distance fields are 8 bit, therefore I assume they they have a range of greyscale values between 0 and 256.

lets say you have 25 different unique meshes, and you want to be able to distinguish between them in the distance field material functions.
If you reduce the number of values allowed in each of those 25 objects to 10 values, then you have created a sortoff identifier for each object. object one occupies the range 0 to 10, object two occupies range 10 to 20, object 3 ocupies range 20 to 30…
Now you can split you objects into 25 different “channels” persay inside your material.

Is that possible, what do people think?

It’s an interesting concept, right? Feels like it’d allow for a lot more use cases for Distance Fields.

It would be relatively easy to split that information up within the material, but the issue comes from figuring out how to get the mesh distance fields to only work within that range, which I can’t seem to find any example of as of yet.

I’ve read up a little bit about multi-channel distance fields being used for more precise vector shapes/fonts:

Not sure if Unreal uses multi-channel distance fields at all, but even 4 channels would provide some flexibility.

GitHub - Chlumsky/msdfgen: Multi-channel signed distance field generator Can produce some pretty sharp results. There is a plugin on the Marketplace that makes use of this technique, but does it in a very limited way. Instead of exposing it’s alpha data to a Font Param node like the built-in SDF TextRender Actor does ( so you can use your own lit materials as you see fit ) it doesn’t do this and forces it’s own setup. Sadly much less useful overall.

To anyone stumbling upon this, there is hacky, unprecise way to achieve “isolating” items:

  1. Enable and use custom stencil ID (and custom depth) on the meshes you want to isolate/mask (you’ll need “CustomDepth + Stencil” enabled in the project settings)
  2. Use DistanceFieldGradient to offset the CustomID SceneTexture sampling in your surface shader
  3. Use DistanceToNearestSurface to “mask” the parts you don’t want.

Here’s what the node setup looks like:

Example with a that material applied to a plane in the TopDown example with columns

You can then have fun with the stencil ID the same way you would in a post-process.
i.e here is the if stencilID==50 mask:

It’s obviously a very dirty result, but maybe it can be useful to someone!