[Godot 2] How to color a cell from a Tilemap?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By woopdeedoo

It seems like there’s nothing in the TileMap node to alter the colors of a particular cell (not tile). But I wonder if this could be achieved somehow, with shaders or something else?

This is specifically for a classic roguelike kind of game. So basically what I need is to have a 64x40 grid of characters (which I do already), but I need a way to change each of their colors during runtime. [EDIT: To be clear, I need control over the color of the text (foreground color), and over the color around the text (background color), separately.]

(A shader on a tile doesn’t work, as that changes the color for all the instances of that same tile that are on the screen.)

(This is crossposted this from the Godot forums.)


EDIT2: I’m still interested in the using TileMaps, but in the meanwhile I figured out how to achieve what I want through shading loose sprites (no TileMap node). So basically I covered the screen with sprites, each of them with this shader:

uniform color fg;    // foreground color
uniform color bg;    // background color

if (COLOR.rgb == vec3(0.0, 0.0, 0.0)){    // I don't think I'll need alpha
    COLOR.rgb = bg.rgb;
} else {
    COLOR.rgb = fg.rgb;
}

Two things to keep in mind about this, as far as I’ve tested it:

  1. Each sprite is a preloaded Cell.tscn (Sprite as root, nothing else in it), as
    the loading time seems way faster by instancing preloaded scenes than
    to create Sprite objects on the fly.
  2. I have to create a CanvasItemMaterial for each sprite as I load them, so
    that they each gets a unique material (to which I assign that shader above,
    which is saved on a file).

That seems to work fine. The main “problem” is that while it performs rather well (at least without any game logic on top of it), the TileMap still performs ~4x better, and adding more TileMaps doesn’t seem to make a significant difference in performance, while this way it does.

So I’m still very interested in doing it with TileMaps instead, if possible.

:bust_in_silhouette: Reply From: eons

Tilemaps are a single structure, each tile gets a texture from the tileset so modulating a single cell is not possible, you can do something else:

Use another tilemap on top and draw special colored tiles with it on top of the other tilemap.
There is another problem, Godot 2 do not have a blend mode for the tilemap, only modulate per tile, but allows creating a material with shader, so you can make a fragment shader that says something like:

COLOR.rgb *= texscreen(SCREEN_UV);

on each coloring tile (it can be the same material loaded on the tiles, just save the resource in a file).

That way the tilemap will tint tiles (and anything) below it.

Well, that’s one way to color the text (it works, I just tried it). But as far as I understand it, this requires a fixed amount of fixed colors to begin with. I can’t say I’m pleased with that limitation.

Another problem I noticed I forgot to mention before is that I also need to change the background color separately. Maybe I could still use yet another tilmap for that, although I’m not sure how to make a shader for that. I’m just beginning to learn shaders…

I have to say though, that in the meanwhile I figured out how to achieve what I want through shading loose sprites (no TileMap node), so I have the screen covered with sprites, each of them with this shader:

uniform color fg;    // foreground color
uniform color bg;    // background color

if (COLOR.rgb == vec3(0.0, 0.0, 0.0)){    // I don't think I'll need alpha
	COLOR.rgb = bg.rgb;
} else {
	COLOR.rgb = fg.rgb;
}

That seems to work fine (though it seems I have to create a CanvasItemMaterial when I load each of the sprites, so that each of them gets a unique material – and I assign them the shader that’s saved on the disk). The main “problem” is that while it performs quite well (at least without any game logic on top of it), the TileMap performs ~4x better, and adding more TileMaps doesn’t seem to make a significant difference in performance, while this way it does.

And so I’m still very interested in doing it with a TileMap instead, if possible.

woopdeedoo | 2018-05-03 16:21