How to get the texture of a single tilemap cell?


I want to use the texture of a cell as mask in a shader effect in a breakout game, but how do I get to it? Same thing if I am using an interactive building game and use a tilemap as basis, how would I preview the tile I want to place in the world?

My research leads me down the path of TileSetSource and TileSetAtlasSource. Then use the texture I'd get from the AtlasSource with and Atlastexture plus the TileData to get the single cell texture?

For Godot 4.

  • Nathan Lovato replied

    Could you please give us more information or a video or screenshot of what you're trying to achieve when you say "use the texture of a cell as mask in a shader effect in a breakout game" ? The solution may not require finding and extracting some tile's texture region.

    Regarding previewing a tile in a building game, the simplest way would be to have a second tilemap node, make it half transparent with the Modulate property, and just draw a tile in the cell the mouse is hovering, and update the drawn tiles as the mouse move. Very easy, it doesn't require fetching texture data and figuring out how to draw it in the right place.

    If you really do want to do it the harder way for practice, i.e. finding and extracting the texture from the tileset resource, please let us know. In general, we try to recommend the most productive Godot solutions we can find to a problem.

  • C
    CodeFox replied

    Sure, here is the effect I want to use:


    Whenever I break a block in a breakout game:


    That's why I want the single cell texture.

    Also, yeah, I guess you could do it with a double tilemap. But Then I'd have to make the cloning in code to avoid double configuration issues.

    It's kinda weird there isn't a direct function to directly get the texure. I would hope have that every time a tile is placed in memory it's not cut from an atlas texture every time.

  • Nathan Lovato replied

    Typically for a breakout game in Godot, you wouldn't use a tilemap, but rather individual scene instances, each with a sprite and collision shape.

    Getting the texture region of one tilemap cell isn't something Godot users commonly need to do as there are the sprite nodes etc. It's more of a rare need for very specific cases. Most shaders operating on a tilemap don't require extracting the region of one specific cell in isolation. That's why there isn't an API to directly get the texture region drawn in one tilemap cell, and it's a bit more involved.

  • C
    CodeFox replied

    I found setting up levels with help of tilemaps just so comfortable. Especially with the newly added power of custom tile data.

    I guess I could do it with an scene set on a tilemap? Getting the properties of the instances shouldn't be that hard?

    And as far as programming exercise, I'd really like to see the solution. I've wrecked my brain quite a while over it, and am a bit exhausted.

    So if it's not too big of an ask, could you ask for the solution?

    Best regards, Christoph

  • Răzvan Cosmin Rădulescu(razcore-rad) replied

    Well to be fair, Godot v4 introduces huge changes and we, like the rest of the world are trying to study these changes. It would be nice to have all the answers just like that, but sometimes we fall back on alternatives responses because we don't have the time to dig in a particular topic at the time.

    That said, from what I researched, there doesn't seem to be a simple way to grab the particular texture region. This is a code I came up with to figure out the coordinate from the atlas of a particular cell. This assumes that you're working with TileSetAtlasSource.

    extends TileMap
    # As you know TileMaps now use Layers so whenever we want to figure out a cell we need to
    # reference the given layer
    const LAYER := 0
    # And the same applies to tiles, we can have multiple sources with different textures so
    # these constants might be different depending on your case
    const SOURCE_ID := 0
    func _input(event: InputEvent) -> void:
    	if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
    		# Get the mouse position on LEFT button press in TileMap coordinates.
    		# This assumes `TileMap.global_position` is Vector2`.ZERO`.
    		var cell_position := local_to_map(event.position)
    		# We can now grab the coordinate in the atlas - that is to say in the `TileSet`
    		# source texture.
    		var atlas_coord := get_cell_atlas_coords(LAYER, cell_position)
    		# We get the atlas itself to access the texture and convert from
    		# `atlas_coord` to texture coordinate
    		var atlas_source: TileSetAtlasSource = tile_set.get_source(SOURCE_ID)
    		# We can finally compute the pixel location in the `TileSet` texture for
    		# this particular setup.
    		var texture_atlas_coord := atlas_coord * atlas_source.texture_region_size

    After grabbing the texture pixel coordinate of the cell you'll have to figure out how to grab that particular region and feed it into the shader. Hope that helps.

  • Nathan Lovato replied
    but sometimes we fall back on alternatives responses because we don't have the time to dig in a particular topic at the time.

    Actually, when we answer something else it's mostly because, for example in this case, the problem wasn't "I need to get the texture of a tilemap's cell" to me, if we take a step back I would suggest considering implementing the game differently, because using tiles you'll face lots of limitations that'll complicate your code compared to using sprites.

    For example, with tiles, it wouldn´t be easy to have animations like blocks rotating, flying around when hit, and other super cool effects for juicing the game.

    Then if getting a tilemap cell's texture is more of a curiosity thing, we're glad to help with that.