How can I make my mask (truly) transparent?

Godot Version

4.4.1

Question

I’m following this tutorial to try and recreate splatoon mechanics

and im using this mask texture


My shader nodes look like this

If I convert my mask to linear it becomes transparent but it overwrites previous splats

My question is how can I prevent the paint mask from overwriting previous splats?

Is your (source png) mask texture transparent? With black edges it seems like it’s built for addative blending instead of alpha mixing.

Make sure you aren’t falling afoul of the zbuffer as well; if you haven’t disabled depth writes for those decals, they’ll fight.

that is a horrendous tutorial.

just use a decal, it is true 3D.

spawn decals, keep score of how many there are, maybe something to prevent more than 2 decals from existing too close to each other for performance (so there are no duplicate decals occupying the almost exact same space).

I used them for bullet holes and performance is good, and the smaller they are, the better.

If they want to do this for painting terrain, the decals aren’t going to be small unless there are a whole lot of them.

1 Like

performance with a viewport and dozens of 2d sprites is no better.

  • one is rendering on the GPU and will work better with a better GPU.

  • the other is rendering with software and sending an entire image to the GPU every time something changes. I’ve done this, for a top-down managerial project, and there is always some stutter when that happens that is not good for a real time game with dozens of players spraying paint every second.
    for this the optimal solution would be a Texture2DRID, but they are very difficult to code.

and, just add 5 small decals in a scene instead of a single big one.

and look at this quick test with medium sized decals in 4.4:


performance is basically the same.

I’m inclined to think that for the desired use case (splatoon-style terrain painting) sprites/decals/&c. are going to have several problems.

  • assuming you want to be able to paint everything, ultimately you’re going to have a lot of these things, especially if the level is big
  • coverage calculations (ie: who painted more?) become nontrivial, unless you don’t care about overlaps
  • “is this part of the terrain painted?” becomes a a 2D collision problem

I think if I were to tackle something like this I’d probably look into a scheme more like shadow maps; a texture I could write into that maps onto the terrain, and potentially a CPU-side bitmap to drive it so coverage and hit tests don’t have to jump the GPU divide.

this is a tutorial, meaning its directed at people who are learning. and the use cases for this could be to add bullet holes or splatter, which in godot should be done with a decal. another use could be in a game like portal where areas can be painted to place portals, and decals are also the solution.
the only use for this is if you want to 100% recreate splattoon, so it’s a bad tutorial.

splatton is a game about painting surfaces, so the levels tend to be small.
and a big level is also going to have performance problems with a viewport, because you are using a generated texture on all the surfaces, so
bigger map = you need a bigger texture

I would add that using decals allows using different materials for the level, which is not possible with the viewport method.

it’s actually more difficult with a texture, you need to convert it to a gigantic array, and then count every single pixel and compare it with a color.
with decals, you know how many decals there are and can tell them apart too.

yes, that’s probably right. but it could work.
if we downscale it a bit (for simplicity, we are not using Texture2DRID because we don’t have the talent), something like the mario minigame in jamboree where you paint a canvas, could be made with decals. those games are not very exact either but players have to agree with the results.

The OP said they wanted to do splatoon mechanics, so I’m assuming that tutorial was only relevant in as much as it represented a possible path to the goal.

I think decals/sprites are going to scale badly for that. I’d be happy to be proven wrong, but my gut feeling is that as the level gets painted and your set of decals/sprites builds up, performance drops.

Using a paint texture (or textures…) does have down sides; unless you pull fancy shader tricks you’ll potentially see texel artifacting, and you’ll probably have to design the level geometry with at least some concessions to how the textures are tiled if you aren’t stretching one huge texture over the level.

On the other hand, the paint texture solves several potential problems:

It scales well; unless you do something very weird in the shaders, performance should be largely unrelated to how much paint is on the map. The paint texture is always there, so you’re always paying the cost, but that means you can plan for it.

Coverage and checking whether an area is painted become trivial; you keep a separate PackedByteArray on the CPU side that has a cell for every texel in the texture, and when you splat paint onto the texture you also splat values into the coverage array. Any tests you want to do, any coverage stats, you can do directly on the CPU-side array rather than having to query the actual texture or read from the GPU. The byte array could be a bitmap (that is, one bit per texel), or it could be wider if you want to allow for multiple colors.

Change detection becomes easy. If you want to determine whether the paint color of a texel is changing, you can look in the CPU-side array before you write to it. So, if (say) you have a powerup that you have to pick up by painting the floor under it, you can do that relatively easily.

I have actually built a system like this in the past (admittedly, in the 90s), and it does work.