• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
Relfos

Seams between tiles

22 posts in this topic

I'm creating a 3d tile based game, where a level is composed of lots of small tiles 10x10 in size, that are stitched together in a big mesh during loading.
The problem is, there are some visible seams between each tile, that seem to be dependent of the camera position.
What could be causing this?
The problem looks a lot worse when multisampling is enabled (and the problem appears on both PC and iPhone port)
[img]http://img854.imageshack.us/img854/7424/seamsabug.jpg[/img]
0

Share this post


Link to post
Share on other sites
sadly, opengl hasnt got past the point where you have to make the image bigger because sampling reads outside the borders
this is especially the case for atlasing
if you have any plans to allow people with older (power of 2) cards, your textures suddenly get twice as big :)
if it was up to me, this shouldnt be needed

most people will tell you to use "border", but border doesnt work with multisampling
so, if you plan on enabling GL_MULTISAMPLE, then you must make all your textures twice as big, place the actual texture in the middle, and extrude all the edge pixels out to the sides
then your texcoords will be something like { 0.0 + 0.25, 1.0 - 0.25 } etc. where 0.25 is a const float based on your particular texture sizes
0

Share this post


Link to post
Share on other sites
[quote name='Kaptein' timestamp='1299685887' post='4783587']
sadly, opengl hasnt got past the point where you have to make the image bigger because sampling reads outside the borders
this is especially the case for atlasing
if you have any plans to allow people with older (power of 2) cards, your textures suddenly get twice as big :)
if it was up to me, this shouldnt be needed[/quote]

Gotten past the point?
Textures work precisely like they are supposed to. And what does power of 2 have to do with anything about borders?
That certainly doesn't require your textures to be twice as big, especially not in a texture atlas. Also cards that require powers of two get more and more rare.

[quote]
most people will tell you to use "border", but border doesnt work with multisampling
so, if you plan on enabling GL_MULTISAMPLE, then you must make all your textures twice as big, place the actual texture in the middle, and extrude all the edge pixels out to the sides
then your texcoords will be something like { 0.0 + 0.25, 1.0 - 0.25 } etc. where 0.25 is a const float based on your particular texture sizes
[/quote]

Why doesn't it work?
And why in the world would it require textures to be TWICE as big?
That's certainly not the case either.
0

Share this post


Link to post
Share on other sites
[quote name='Erik Rufelt' timestamp='1299687940' post='4783602']
wisdom
[/quote]

i just havent gotten it to work in my case, ive tried many times :)
the 2^n may be just me reading old tutorials, maybe wrong impression
and the atlasing thing was based on the first assumption, that multisampling requires even more pixels

you see, it works fine with a border until i move far away, then the seams start appearing
0

Share this post


Link to post
Share on other sites
Yes, all tiles are stored in a single 512x512. This does not use shaders, as it is an iPhone game.
For now setting the texture filter as GL_NEAREST_MIPMAP_NEAREST fixed the issue (well, almost).
For the other cases, slighty offsetting the UV coords of the tiles one pixel fixed it.
0

Share this post


Link to post
Share on other sites
i just checked my code to find out why im doing what i do :)
and yes, im also storing "tiles" in single textures, so i need internal borders too
i think ill try to reduce the images somewhat :)
0

Share this post


Link to post
Share on other sites
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 [url="http://www.opengl.org/wiki/Array_Texture"]array textures[/url]: 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.
0

Share this post


Link to post
Share on other sites
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.)
0

Share this post


Link to post
[quote][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3][left][background=rgb(250, 251, 252)]3. Try to clamp to the tile borders using a shader[/background][/left][/size][/font][/color][/quote]

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

Share this post


Link to post
Share on other sites
A simple shader idea (without border,just clamping), 4 textures on a single one, each tileable:

[CODE]
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);

[/CODE]

But I think, that you will archive better quality when using a border (repeating texture accordingly). Edited by Ashaman73
0

Share this post


Link to post
Share on other sites
Thanks for the example! I will have a play :-)

Also, the screenshots for Gnoblins look amazing, well done!
0

Share this post


Link to post
Share on other sites
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:

[CODE]
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;
[/CODE]

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

thanks
0

Share this post


Link to post
Share on other sites
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). Edited by DemonRad
0

Share this post


Link to post
Share on other sites
[quote][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3][left][background=rgb(250, 251, 252)]you need a incomplete Mipmap pyramid[/background][/left][/size][/font][/color][/quote]
Are you saying that this applies when I have mipmapping disabled?

[quote][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3][left][background=rgb(250, 251, 252)]Texture arrays is still a valid alternative (i think TA were born for these problems)[/background][/left][/size][/font][/color][/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
0

Share this post


Link to post
Share on other sites
[quote name='kruncher' timestamp='1339555129' post='4948695']
disabling mip-mapping
[/quote]
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.

[quote name='kruncher' timestamp='1339555129' post='4948695']
Whilst this seems to work (through trial and error) is there any logic to this?
[/quote]
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
[CODE]
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
...
[/CODE]
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).
1

Share this post


Link to post
Share on other sites
[quote][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3][left][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][/left][/size][/font][/color][/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...

[quote][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3][left][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][/left][/size][/font][/color][/quote]

Very interesting, thanks for pointing that out.
0

Share this post


Link to post
Share on other sites
[quote name='kruncher' timestamp='1339767474' post='4949527']
Somebody suggested to me that there is very little advantage to mipmapping for 2D...
[/quote]
Yes, when you develop a 2d game with a fix 1:1 texture mapping, you don't need mip-mapping at all, I was more or less referring the topic starter who creates a 3d game.
1

Share this post


Link to post
Share on other sites
[quote name='Ashaman73' timestamp='1299753842' post='4783949']
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 [url="http://www.opengl.org/wiki/Array_Texture"]array textures[/url]: 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.
[/quote]

May i ask if by generating mipmap levels at runtime could fix the problem as well ?
0

Share this post


Link to post
Share on other sites
[quote name='vNeeki' timestamp='1340133709' post='4950686']May i ask if by generating mipmap levels at runtime could fix the problem as well ?[/quote]The time of generation has no relevance to the problem.
0

Share this post


Link to post
Share on other sites
[quote name='tanzanite7' timestamp='1340236066' post='4951162']
[quote name='vNeeki' timestamp='1340133709' post='4950686']May i ask if by generating mipmap levels at runtime could fix the problem as well ?[/quote]The time of generation has no relevance to the problem.
[/quote]
But it has. Read back. It's not the [i]time[/i], but the [i]run time generation[/i] part that's relevant. [i]Run time[/i] doesn't mean an actual time, it means that something happens when the program is running.


If you generate the mip-map levels by yourself, then you can fix the problem. Following Ashaman's advices. But with a 3rd party library (like glut), I don't think so. Edited by szecs
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0