Eliminating texture seams at terrain chunk

Started by
9 comments, last by Bow_vernon 9 years, 2 months ago
Hi, fellow game developer. nice to see you!

I've decided that I'd make games for my android phones. It has several limitation such as GLES max texture dimension. So in my terrain editor, I implement a new feature that is basically chunked texture. I store the complete texture data on the memory, but for each terrain chunk (being 32*32 tiles or 33*33 vertices) there is an OpenGL Texture assigned for it (which, dynamically change its data according to the global data). Each chunk texture has x,y coordinate of the global data as well as width and height.

Whenever I "paint" the global texture, each affected chunk would apply its changes. It works well, but I notice an artifact when rendering. I understand that it's caused by the GL_LINEAR filter I set for the minification and magnification filter. Each of the chunk texture would samples its own "mipmap" without taking account the neighboring chunk. So it's visually wrong. However, I still don't know how to minimize this effect. How would you solve this kind of problem? I'm trying to think a simple way out but seriously, coding this game editor had me drained inside out. I can't think clearly.

PS: these texture aren't diffuse texture. It's alpha map for the terrain texture splatting. For this simple test, I generate the global texture on the fly using simple noise calculation. It's tileable but since there're seams at the edge of each chunk, it breaks realism.

Here is how the terrain chunking looks with GL_LINEAR filter

1510980_653994921375583_5090747062442770

And here it is with GL_NEAREST instead. Unsurprisingly, no artifacts is seen here.

11001863_653994931375582_505464589805159

TL;DR : How would you eliminate the seams at the terrain chunk's edge?

Edit : uv wrap mode is GL_CLAMP_TO_EDGE
Advertisement

If you want perfect tiling between the right side of one texture and the left side of another separate texture then you need to add borders of 2^N where N is the number of mip-levels not including the full-sized texture, and fill this border with the edge-pixels from the texture it's supposed to tile into, in order to make sure that all the N mip-levels have proper blending.

You probably don't need more than 4 or 8 pixel borders as it won't be very noticeable for smaller mips.

If you want to improve performance or texture usage, I would recommend placing the chunk textures in groups to form larger textures, so any chunks that share a group effectively form a smaller square terrain where a single texture covers all those chunks, and only border these textures.

Do your textures have their wrap mode set to GL_CLAMP_TO_EDGE? I'm pretty sure that would eliminate the worst of the artefacts you are experiencing there.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

If you want perfect tiling between the right side of one texture and the left side of another separate texture then you need to add borders of 2^N where N is the number of mip-levels not including the full-sized texture, and fill this border with the edge-pixels from the texture it's supposed to tile into, in order to make sure that all the N mip-levels have proper blending.
You probably don't need more than 4 or 8 pixel borders as it won't be very noticeable for smaller mips.


So are these border pixels part of the pixel data or are they separate properties that can be set in opengl? For example this texture chunk is 1024x1024. If adding border would increase dimension, suppose it's 4 pixel border. Wouldn't it make it 1028x1028 thus violating non power of two requirements? but it's interesting though. I'll look it up more later

Do your textures have their wrap mode set to GL_CLAMP_TO_EDGE? I'm pretty sure that would eliminate the worst of the artefacts you are experiencing there.


Well it's already using GL_CLAMP_TO_EDGE. Sorry I didnt mention it earlier


So are these border pixels part of the pixel data or are they separate properties that can be set in opengl? For example this texture chunk is 1024x1024. If adding border would increase dimension, suppose it's 4 pixel border. Wouldn't it make it 1028x1028 thus violating non power of two requirements? but it's interesting though. I'll look it up more later

It would, so you have to let the usable part of the texture be 1016x1016 to add 4 pixel borders at each edge. This usually isn't a problem as with bilinear filtering and scaling anyway it won't look any different, just set the texture coords to be [4/1024, 1020/1024] instead of [0, 1].

Are you sure your texture is tileable? It certainly doesn't look it. Try downloading a proper tiling texture, and see if the problem still exists..


Are you sure your texture is tileable? It certainly doesn't look it.

This strikes me as well. Given the random nature of your texture contents, it's not clear you'll be able to tell if it is tiling or not, since with sampling set to GL_NEAREST, it just looks like noise.

Try generating textures with larger-scale features, and see if the feature line up. My guess would be you have an small error in the texture coordinates at the edge of each tile.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

I think you have misunderstood the OP, or else I have. I believe his intentions are to have every tile use a completely separate texture that can be individually painted for texture splatting or blending between layers. (If that is the case I assume it will often be quite magnified when viewed close-up, at which point borders are usually necessary).

I believe his intentions are to have every tile use a completely separate texture that can be individually painted for texture splatting or blending between layers

That is my understanding as well, but the errors he is currently seeing are not consistent with my experience of that scenario. Those seams are far more apparent than is reasonable for just filtering error.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

I think the uv mapping is not continuous, ie if an edge is shared between 2 quads, the uv value of vertex doesn't match.
(assuming that 2 quads uv map doesn't overlap)

This topic is closed to new replies.

Advertisement