Bi/Trilinear filtering with tilable images on a texture atlas

Hey guys,

I wonder if perhaps any of you artist types might have any suggestions. I have a texture atlas that I use for large parts of my environment. I will post a reduced version of it here:

Okay, each of the panels on this atlas are designed to tile both horizontally and vertically. Most of my static environment uses some combination of the panels on this atlas. And then Unity batches them and I get good frames rates. Super.

Except for one thing. To do this, I have to set the texture to use point filtering. Naturally this causes pixelation if the camera gets too close to a wall. I could live with that. But what is unacceptable is it makes the mip-mapping look terrible. As you are walking down a corridor, there are visible borders between the mip-maps using point filtering, and it looks awful.

If instead, I switch the texture over to bilinear or trilinear filtering, that seam between the mip-maps practically disappears (if you look really close, you can see it, but it’s nowhere near as jarring, and I can live with it). So that’s what I feel like I have to use.

Of course, the problem with that is by using those filters, I’m picking up colors from the adjoining tiles on the texture atlas at the borders of all my environment models (because the UV maps go right to the edge of each tile so that they repeat properly). Which is just as bad as the poor mip maps.

So, my question is, is there a way for me to fix this? If I pull back the UV maps a couple of pixels so they are not right on the edge (and thus don’t pick up the wrong colors), won’t that mess up my ability to tile? Is there another solution?

I have close to 50 environment pieces now (my “lego” box of parts, heh), each with 4 LODs, so it would be a lot of work to re-UV map all of them, but I’d rather do it now rather than when I have 200 pieces, if that’s what I need to do. [In fact, I’d probably only need to remap the LOD zeros, you wouldn’t be able to see the faint border lines on the LOD1+ anyway, they’d be way too far away].

Thanks for any advice.

Ron

Pull the UV maps back several pixels, and shrink the textures to match. Then solidify the texture to fill in the gaps. That way you can tile the textures, and the extended parts of the texture outside the UV mapped areas will prevent mipmaps from picking up pixels from the wrong textures.

–Eric

Thanks Eric. That sounds good. I think I will write a script in Maya to auto-shrink those UV coords, rather than try to do it by hand. That ought to make it nice and easy (and most importantly, fast!).

With trilinear filtering, how many pixels back do I need to be not to pick up the adjoining texture? Would 3 pixels do it?

The only way to do this is to double the size of the tile in the texture and then use the center of the tile.

I’ve tried creating my own mipmaps and ensuring the borders are always perfect and don’t bleed into the next texture but it didn’t work either.

I’ve spent easily 100+ hours on this and the only thing that worked was this: Texture atlas extension to the RTSS - Ogre Forums

Doubling the padding for every texture in the atlas is overkill. Experiment with the amount of padding needed to get results that you find acceptable.

Sorry, I don’t understand. Why would you need to double the tile size? As far as I can see, you only need a 3 or 4 pixel border around the edge to prevent bleeding. If you use the same color as the pixel on the border edge to push out those 3 or 4 pixels, it should still tile just fine, right? And I’m not really seeing the issue with mip maps. Even if they do (somehow) end up bleeding, you are going to be some distance away from the model with the texture. As it is, using bilinear or trilinear sampling in my game, you can just BARELY make out the bleed if you are standing right on top of it and know right where to look. By the time you hit the next mip map level, you won’t be able to see it, at least in my game. I think :slight_smile:

It would be nice if there was a way to clamp the texel sampler to stay within the extents of the UV map, but I guess we don’t have that option :slight_smile: I think that’s a hardware thing, you can’t even change it using a shader.

I tried 4, 10, 20, 50 pixels for bleeding but eventually a certain view angle produces a seam. I’m working on a racer so you are very close to the ground EDIT: and far away at the same time :slight_smile:

If you get it work please post back so I know I have to take another look at it. :slight_smile:

I’ve used about 5% padding and it worked well. Not sure how many pixels.

–Eric

That sounds like mip-maps issue. If you need tileable atlas and mip-maps you’re out of luck completely :wink:

Not if you write your own mip mapping scheme (should be possible as ar as I can tell, haven’t dabbled into that yet thou) where you define the tileable texture borders.

You guys have lost me. I feel like we are talking about different things. Or there is something I don’t understand (possible, since I haven’t implemented this yet other than to turn my texture to trilinear sampling).

My texture atlas is 2048x2048. Unity automatically generates 12 levels of mip maps for this texture. It uses them automatically, and as far as I can tell, there is no way to turn off their use. So mip-maps are a given, as far as I know.

But I don’t really see how that is incompatible with the system we are discussing. The UV map coords on the models are relative, so they aren’t going to move. Is it because the reduction in the texture size will end up blurring the texels between the different parts of the textures, and thus you could still get a bleeding effect when the texture sampling happens? Okay, I see that happening.

But c’mon. How far back from the texture would the camera have to be before that bleeding starts to happen? I don’t know at what distance Unity switches my texture from mip-map 0 to mip-map 1, but it’s certainly a ways back (10 m? 20 m?). At that distance, you are not going to see the bleed, you are just not. As I said, you can just BARELY see it if you are standing right on top of it (maybe in my game, because it is underground and fairly dark, and there is not a whole lot of extreme contrast between the different parts of my atlas, I don’t have as much of an issue as you guys are talking about?). Not to mention that the errant texels on mip-map 1 (+) will be a amalgamation of the correct and incorrect parts of the texture (combined when the texture was reduced), so even the errant colors will be mitigated. Thirdly, the entire texture quality is reduced, which is going to mitigate the effect of the border pixels even further.

Okay, sure, I guess bleeding will eventually happen as a result of mip-maps, and depending on how much of a buffer you are putting around the edges, I suppose it could happen as early as mip-map 1. But really, do you think players will pick up on that one texel border given the distance from the model they will be looking and the fact that the entire texture will have stepped down in quality?

Is it maybe a bigger deal if the original atlas is smaller, you have more contrast between the parts, and are in an outdoor area? Is that where it becomes an issue?

GPU decides the mipmapping, not Unity.

Most atlas creation tools generate the mip mapping for the individual textures before merging them into an atlas to fix this “bleed” issue or force the border texel to be locked (there are some more ways, but listing them all would take too long), this results in an atlas where no padding is necessary and no bleeding is possible (technically, there are some rounding off errors that can always happen).

and yes, because technically mip mapping reduces your texture resolution to a maximum of 4x4 (if i recall correctly), eventually one texture would bleed into another (or the padding would bleed into the texture, depending if you have padding or not). This would generate lines or visible discontinuities in the tiling texture when viewed from afar or from a sharp angle.

The distance this starts at is pretty close, but it also happens at sharp angles. In fact it’s really hard to predict when mip mapping is going to happen at all.

For further reading into mip mapping etc… this is a pretty good place: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter28.html

The reason you’re not seeing the issue till when you select point filtering is because point is the most visible setting where you would see these graphical artifacts, bilinear and trilinear are designed to blend between texels when the pixel is between them so you wouldn’t see it that fast due to the fact that it’s technically blending more with the correct texels than the incorrect texel.

The issue is at its greatest in large spaces, spaces with sharp angles etc… basically whenever mipmapping sets in. As Unity does not handle mipmapping in a way that’s beneficial to atlas textures, this is hard to fix except if you introduce your own mip mapping schemes (possible).

If you want to fix it yourself without programming, you technically already can, if you use DDS format, you can bake your own mip maps into there and unity will use those. I’m very sure there are some programs floating around to generate mipmaps for atlas textures or merging multiple textures with their mip map chain into one DDS.

I’m actually planning on creating an automatic atlasing tool for unity soonish (no promises, but it’s on my roadmap of things i’d like to do). Perhaps, at one point it’ll find its way to the asset store (again no promises as that one is up to my employer, not me).

edit: I’d like to add that even with the techniques said in my first paragraph, bleeding is still going to happen at certain resolutions (like 2x2 if you pack 16 textures into it), but those are the ways you can mitigate the bleeding to its fullest.

Interesting! Thanks Jessy, that helps my understanding.

Do you know where such tool can be found? As I said above, I currently have close to 50 models now for the environment, each with 4 LODs. If I can avoid it, I really don’t want to have to change all their UV maps so that I can add this “border” around each of the texture sections. If the border texel can be clamped, that solves the problem, and no UV map changes are needed. I’d be very interested in such a tool :slight_smile: [although how does that work? texel->pixel conversion is done on the hardware, and with bi/trilinear filtering, you are going to get bleed no matter what the texture looks like unless you have that border. Hmmm, maybe that’s not the solution I hope it is :slight_smile: ].

Actually, I don’t see any issue at all with point filtering (at least not with bleed at the borders). It’s only when I turn on a better filter that I see bleeding. Again, I think this is going back to the fact that in my game, mip-mapping bleed is not the problem, it’s the bleed coming from the texel->pixel conversion mechanism.

I’d post screenshots of this, but I’m not sure how they’d come out. You can barely see the bleed in real time when you are right up close, much less trying to see it on a screenshot. But I can try if it helps.

EDIT: And BTW, thanks everyone for the discussion. I’m not really a guru on the technical side of displaying graphics, so I’ve found this conversation most enlightening.

nvidia has a texture atlas tool: Texture Atlas Tools|NVIDIA
but prolly nothing useable for you.

If it really bothers you, I’d go for manually quickly creating the mipmaps or testing kaiser mip map filtering in the advanced texture properties in unity.
Technically you can also turn off mipmapping but this will introduce texture aliasing artifacts.

Wish I had this comment to look at before I wasted countless hours on the task a few months back lol :slight_smile:

You can, by unchecking “generate mip maps” in the texture importer, however this is intended for textures used in a 2D way, since in 3D the lack of mipmaps can result in some unacceptable artifacts depending on what you’re doing.

–Eric

I was about to say I don’t seem to have that option, but there it is, under “Advanced”. I never really looked at the advanced import settings for textures. Good to know, thanks Eric.

Trooper, I see what you mean :slight_smile:

I’ve made no attempt to fix this yet (or at least mitigate it). But yeah, I understand what you were saying now much better now. Tricky…

If padding is failing you, there are two ways to mitigate the excess bleed on the floor:

  • raise the anisoptropic value
  • lowering the texture mipmap bias, i.e.

UnityScript:

#pragma strict
var textures : Texture[];
var bias = 0.0;
function Start() {
    for (var t in textures)
        t.mipMapBias = bias;
}

C#:

    public Texture[] textures;
    public float bias = -0.9f; // one level down

    void Start()
    {
        foreach (Texture t in textures)
            t.mipMapBias = bias;
    }

Have you not tried Wrap Mode: Clamp?