+1 vote

Hi,

I am trying to apply a shader to a tilemap.

My shader applies a simple texture to all the area covered by the tiles.

if I use the following shader code :

void fragment() {
    vec4 color = texture(mapTexture, UV);
    COLOR = color;
    COLOR.a = texture(TEXTURE,UV).a;
}

This results in each tile having the shader but the lines between tiles are visible.

TileImage
TileImage

If I change UV by SCREEN_UV it results in the lines between the squares going away and the texture applies to the whole area. But then I have another problem the texture doesn't move with the camera.

I have tried moving the texture in the shader using the following code snippet:

void vertex(){
    world_pos = (global_transform * vec4(VERTEX, 0.0, 1.0)).xy;
}

void fragment() {
    vec2 uv =  world_pos.xy / screen_size.xy;
    vec4 color = texture(mapTexture, UV);
    COLOR = color;
    COLOR.a = texture(TEXTURE,UV).a;
}

And setting in my script the global_transform :

MapMaterial.set_shader_param("global_transform", get_global_transform())

But it just results in weird stripping.

tileStretching

Any idea of what I am doing wrong ?

Godot version 3.3
in Engine by (27 points)
edited by

1 Answer

0 votes

The "Lines" between the tiles in your first pictures are called seams and happens because your texture isn't seamless. You get this effect from any texture that you repeat over and over.

Various methods are used to get rid of this behaviour and is a craftsmanship of it's own, in this case you seem to use some kind of noise texture, my recommendation in that case is to use the built in 'noiseTexture' as your base, and add the color of the noise in the shader. Make sure to tick the box 'seamless' in the settings. this should get rid of the seams. To color it orange you just multiply it with the color vector of choice inside the shader. for orange it would be something like (1, 0.5, 0).

If you don't want your texture to repeat at all, then you would have to change your UVs to match your tiling. This is done first through dividing the UVs by the number of tiles:


vec2 numoftiles = vec2(4,6); //the number of tiles in x and z direction
vec2 globaluv = UV/numof_tiles;

then you have to add an x and z index property to each tile as a uniform and add a corresponding offset to the global UVs. In godot 3.x this can only be done through cloning the material for each tile since there is no way to set per instance properties.

uniform vec2 offset;//must be changed per instance. This means that the shader can be reused, but the material can't.

uniform sampler2D mapTexture;

void fragment(){
     vec2 num_of_tiles = vec2(4,6); //the number of tiles in x and z direction
     vec2 global_uv = (UV + offset)/num_of_tiles;
     COLOR = texture(mapTexture, global_uv);
}

I'm somewhat unsure whether the offset is correctly applied, if it's not your seams will still be present, then try and use the icon.png as map and resend an image and I'll try correcting the offset value ;)

by (210 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.