How to pass data into decals without a material instance for each one?

Is it possible to pass any data to the decal actor material, e.g. to control decal color? We can do this for Primitive Components (via custom primitive data) to have only one material and control the color of many primitives like that to reduce drawcalls significantly. But for decals, it’s not possible from what I see…?
… So if we need to control the color of each decal, then we need separate material instance for each one, which will probably result in a large drawcall amount…

I have an idea that won’t work in my case, but maybe it’ll be helpful for someone else: It works for stationary decals. You can set the decal location in a way that it contains e.g. vector3 color info in its location, then retrieve this info inside the material from the Actor Position node. For example:
Set the decal location to (50.000128, 0.000064, 0.000256). Here we have the color info: 128 Red, 64 Green, 256 Blue. Retrieve this info from the Actor Position node by getting the fraction and multiplying by 1000.
… It won’t work in my case since I need decals that move (attached), so the Actor Position constantly changes.
… Any other ideas?

Not sure if I’m not falling into a premature optimization trap here, maybe I’ll just use a separate dynamic material instance for every decal and it won’t be that bad, since the shader is very simple…? Need to test. But still, I only need the color to be changed, so it’s a pity that we can’t pass this info per-decal-component.

Still haven’t found a solution for this, but I guess that it’s just impossible, since we can’t have custom data in the decal component. Only Primitive Components are available for the custom data, unfortunately.

I’ve had an idea to ‘pack’ the info (I only need floats to e.g. select a UV row & column from texture atlas) into the decal actor scale/size/radius as decimals, so for example:

I scale the decal to 1.25 and include the data like that: 1.2500034
Then the decal reads the ‘34’ part and knows that I want to use row 3 and column 4 of the atlas.

… But it looks like we can’t access decal size/bounds/radius/scale/anything via the material :frowning:

How many different colours you are aiming at pottentially?
In one case, I’ve created a manager that would spawn new material instance only if there’s no other material with same params (if there is - just assign previously created one). I suppose it would help you partially if you have not so many different colours, but a lots of decals.

1 Like

That’s exactly what I’ve ended up doing, it’s a good solution to minimize material instances :slight_smile:
My first goal was an unlimited color palette, but I’ve limited it to user-selected 100 colors + a manager that finds already existing material instances with the same color and reuses them.

Of course, the question still stands and it looks like it’s not possible at the moment, but reusing material instances this way (+ limiting the max decal color/texture pool) is a good workaround.