Seams between tiles

Started by
21 comments, last by szecs 11 years, 10 months ago
This seems to be a texture bleeding issue when linear filtering is enabled. Here are some hints/tricks to get rid of it:
1. You tiles should be of power of two size, this could prevent texture bleeding from mipmapping.
2. Try to use array textures: put each tile on a single layer (thought I don't know if the iphone supports this). Don't try to archive this with 3d textures (=>mipmapping issues)!
3. Try to clamp to the tile borders using a shader, add a small border to the tiles,but your total tile size(including border) should be still a power of 2.
Advertisement
In OpenGL both pixel as well as texel centers have a fractional co-ordinate of .5. When using .0 for the texel co-ordinates, you hit exactly between 4 texels. If further interpolation is on then you may get artifacts at the borders of tiles. Hence try to use texel co-ordinates where the fractional part is .5 to address texel perfect. This means for (u,v) in the case of POT textures
u := ( x + 0.5 ) / texture_width_in_texels
v := ( y - 0.5 ) / texture_height_in_texels

(Notice please that 0.5 - y may be needed instead, dependent on how you define y to run over the texture.)
[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

[background=rgb(250, 251, 252)]3. Try to clamp to the tile borders using a shader[/background]

[/font][/quote]

Would you mind demonstrating how this works (preferably with a CG shader)?

Rotorz Limited (http://www.rotorz.com)

Check out our latest game Munchy Bunny!
Editor Tool: Rotorz Tile System (for Unity 3D)
A simple shader idea (without border,just clamping), 4 textures on a single one, each tileable:


vec2 texture_coord = ..input..

// retrieve fraction part of coords to map coord into [0..1]
texture_coord = fract(texture_coord);

// clamp to 1/2 pixel, i,e. DELTA = 0.5/1024.0 for 1024 texture, play around with values to see its effect, consider mipmaps, which halfs the resolution at the underlying level
texture_coord = clamp( texture_coord, vec2(0.0)+vec2(DELTA), vec2(1.0)-vec2(DELTA));

// shift and scale texture to according corner
texture_coord = texture_coord * vec2(0.5) + vec2(OFFSET_X,OFFSET_Y);



But I think, that you will archive better quality when using a border (repeating texture accordingly).
Thanks for the example! I will have a play :-)

Also, the screenshots for Gnoblins look amazing, well done!
Rotorz Limited (http://www.rotorz.com)

Check out our latest game Munchy Bunny!
Editor Tool: Rotorz Tile System (for Unity 3D)
I've been experimenting and found that disabling mip-mapping on my texture and simply offsetting UV coordinates (on mesh, not in shader) by 1 / width and 1 / height of atlas using:


lower_left_uv.x += 1 / width;
lower_left_uv.y += 1 / height;
upper_left_uv.x += 1 / width;
upper_left_uv.y -= 1 / height;
upper_right_uv.x -= 1 / width;
upper_right_uv.y -= 1 / height;
lower_right_uv.x -= 1 / width;
lower_right_uv.y += 1 / height;


Whilst this seems to work (through trial and error) is there any logic to this?

thanks
Rotorz Limited (http://www.rotorz.com)

Check out our latest game Munchy Bunny!
Editor Tool: Rotorz Tile System (for Unity 3D)
you need a incomplete Mipmap pyramid (older cards don't support that. And I never checked if that feature is available into OpenGL ES) Even extruding borders will give seams for lowest mipmap levels. because lowest mipmap levels are an average of above levels.

If you have a 512x512 atlas made of 8x8 tiles each one with 64x64 pixel then instead of using a mipmap pyramid of log2(512)=9 levels. you have to use a mipmap pyramid of log2(64)=6 levels. And you have to care each single tile reducing it by few pixels (for example reduce down to 54x54) and fill the pixels around with extrusion of the tile. With farest geometries artifacts may still occurr, but with some fog are nicely hided. (you still need to readapt texture coordinates to 54x54 subtile instead of 64x64 subtile)


Texture arrays is still a valid alternative (i think TA were born for these problems).

Peace and love, now I understand really what it means! Guardian Angels exist! Thanks!

[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

[background=rgb(250, 251, 252)]you need a incomplete Mipmap pyramid[/background]

[/font][/quote]
Are you saying that this applies when I have mipmapping disabled?

[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

[background=rgb(250, 251, 252)]Texture arrays is still a valid alternative (i think TA were born for these problems)[/background]

[/font][/quote]
Yes these would certainly improve matters because I could take a completely different route. Unfortunately ShaderLab (in Unity) does not provide bindings for sampler2DArray

Rotorz Limited (http://www.rotorz.com)

Check out our latest game Munchy Bunny!
Editor Tool: Rotorz Tile System (for Unity 3D)

disabling mip-mapping

Disabling mip-mapping is not the best idea. For one you will get strong artifacts when moving around and using detailed textures, and it is slower than using mipmapping.


Whilst this seems to work (through trial and error) is there any logic to this?

Yes, the reason is, that on a atlas the naive pixel coordinates are often between two adjacent textures. Therefore the samples taken at the border will include texture data from the adjacent texture (reason: linear filtering). To reduce the effect, you need to move your coord away to the center of the border pixel which you have done by moving it by a whole pixel away (half would be enough).

This could be done with lower mipmapping levels too, but in this case you need to move it away depending on the mipmap level, that is

level 0: 1/width
level 1: 1/ (width/2) = 2/width
level 2: 1/ (width/4) = 4/width
level 3: 1/ (width/8) = 8/width
...

As you can see, higher mipmap levels result in a relative broad border, so you can't just calculate it once and apply it to all levels. Either you need to ajdust it dynamically depending on the mipmap level (expensive, newer hardware needed) or you should repeat the border of your tile. As far as I remember the latter has been done in the id-tech5 engine (megatextures utilize lot of atlases).
[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

[background=rgb(250, 251, 252)]Disabling mip-mapping is not the best idea. For one you will get strong artifacts when moving around and using detailed textures, and it is slower than using mipmapping[/background]

[/font][/quote]

I don't think that is the case for me because I have an orthographic camera. Somebody suggested to me that there is very little advantage to mipmapping for 2D...

[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

[background=rgb(250, 251, 252)]As you can see, higher mipmap levels result in a relative broad border, so you can't just calculate it once and apply it to all levels. Either you need to ajdust it dynamically depending on the mipmap level (expensive, newer hardware needed) or you should repeat the border of your tile. As far as I remember the latter has been done in the id-tech5 engine (megatextures utilize lot of atlases).[/background]

[/font][/quote]

Very interesting, thanks for pointing that out.

Rotorz Limited (http://www.rotorz.com)

Check out our latest game Munchy Bunny!
Editor Tool: Rotorz Tile System (for Unity 3D)

This topic is closed to new replies.

Advertisement