[Unity or not]Problem with repetition in texture atlas

Started by
2 comments, last by tanzanite7 11 years, 11 months ago
[color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)]What I'm trying to do is use the [/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(255, 235, 144)]texture[/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)] [/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(255, 235, 144)]atlas[/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)] to combine multiple terrain textures into one big [/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(255, 235, 144)]texture[/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)].[/background][/font]
[color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)]As you can see in the screenshot, the seams are clearly visible. and it gets worse when viewed from smaller angles. There are a few things I have tried.[/background][/font]


seam.jpg

[color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)]Attempt 1:[/background][/font]
[color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)]In order to locate the [/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(255, 235, 144)]problem[/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)], I changed to a debug [/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(255, 235, 144)]texture[/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)] with no tiles and no [/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(255, 235, 144)]texture[/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)] [/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(255, 235, 144)]atlas[/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)]. Here's what I did.[/background][/font]
[color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)]when the uv calculation function was [/background][/font]
[color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)]uv = worldPos.xz;[/background][/font]
[color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)]tex2D(_DiffuseTex_0, uv);[/background][/font]

[color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)]There is no seam.[/background][/font]
[color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)]After I changed the uv calculation function to[/background][/font]

[color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)]uv = frac(worldPos.xz);[/background][/font]
[color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)]tex2D(_DiffuseTex_0, uv);[/background][/font]

[color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)]the seams would show up. (one might suspect why I would make this change because I used frac() in the full version of my uv calculation. My thinking was that because the [/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(255, 235, 144)]texture[/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)] UV expects values ranging from [0, 1] (both 0, 1 inclusive). But frac() only outputs to [0, 1) (0 inclusive, 1 exclusive). Another observation is that even though frac() only outputs to [0, 1), when the input uv has no fraction component, the result should be 0. And 0 should tell the sampler to sample the first row/column in the sub-texture. but the screenshot shows otherwise. The simplified version of my uv calculation is 'uv = baseUV + frac(uv); '[/background][/font]

[color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)]After searching the forum, it seems other people experienced this [/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(255, 235, 144)]problem[/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)] and categorized it as texel bleeding in the [/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(255, 235, 144)]texture[/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)] [/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(255, 235, 144)]atlas[/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)]' mipmaps. But after a few experiments, I still can not conclude it is a [/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(255, 235, 144)]problem [/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)]of mipmap. Here what I did.[/background][/font]

[color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)]Attempt 2:[/background][/font]
[color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)]I used 'Texture2D.PackTextures' in Unity to combine all the small terrain textures. According to the API documentation, it will merge their mipmaps as well. So I did. It seemed it did merge the textures and all of their mipmaps, but the outcome is exactly the same as before. [/background][/font]

[color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)]Attempt 3:[/background][/font]
[color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)]One thing did work out was disabling the mipmap generation and the seams would go away.[/background][/font]

[color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)]So Attempt 1 tells me it might have something to do with the UV mapping; yet Attempt 2 is hinting that it has nothing to do with mipmap; and Attempt 3 tells me it does relate to the [/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(255, 235, 144)]problem[/background][/font][color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)] of mipmap.[/background][/font]

[color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)]Partial Shader Code:[/background][/font]
[indent=1]

/*
the texture '_DiffuseTex_0' is the final merged texture that has the size 2048 x 2048.
It contains 16 sub-textures with each being 512 x 512. There are 4 sub-textures in each row and a total of 4 rows.
baseUV is the uv coordinate calculated based on the type of terrain type.
e.g. (0,0) being the 1st terrain type,
(0,0.25) being the 2nd terrain type,
(0.75, 0.75) being the 16th terrain type.worldPos.xz is fed to the uv parameter.
*/
float4 GetDiffuseTex(float2 baseUV, float2 uv)
{
float correction = 1.0f/512.0f;
float indent = 0.0f;
uv /= _Repetition; // to scale the texture.

uv = baseUV + (correction * indent + frac(uv) * (1 - indent *2* correction) ) *_TileSize;
// Another test was using indentation to make it only sample from the inner portion of the sub-texture,
// and it didn't help neither.

//uv = (baseUV + frac(uv) *_TileSize);
//uv = frac(uv);

return tex2D(_DiffuseTex_0, uv);
}


[color=#111111][font=Helvetica, Arial, sans-serif]

[background=rgb(254, 254, 254)]So does anyone know how to resolve these seams? Thanks in advance![/background][/font]

Advertisement
One problem is, that you do not sample the pixel, but the space between two pixels. I.e you put 4 textures in an atlas like this

AABB
AABB
CCDD
CCDD

When you try to sample CC with (0,0) to (0.5,0.5) , the border coordinates 0.5 will be a linear combination of C and its according neighbor textures. At the source texture, this will only effect one pixel (still a smallborder). But with increasing mipmap level this will get more obvisouly.

A simple way to avoid this, is to repeat each texture in the texture atlas, i.e. a small border of 8 to 16 pixels and sample only the inner texture. (scale your 512x512 texture down to 480x480 and use a 16 pixel border where you repeat the texture).
Out of interest why do you want to use an atlas for this task?
Your approach is incomplete (aka. wrong for the time being).

The 2x2 pixel errors are exactly what one would expect - the derivatives it gets from the 2x2 area (that is the way how hardware gets the derivatives needed for mipmaping) are wrong as your UV coordinates jump around there. You need to select the correct mipmap level in your texture lookup yourself as you just unavoidably made the derivatives it normally calculates itself - unusable.

As has been asked and i have to ask myself too: why are you trying to use a texture atlas? Hardware limitations (ie. not PC)?

This topic is closed to new replies.

Advertisement