I was just playing around with the default terrain sample from docs, loading a tiled (9x9) terrain I’ve made in WorldMachine (heightmaps only).
It works quite nicely, each chunk being generated in runtime, on height map load event (~150ms for the generation of each tile).
Vertices line up properly, only normals create a visible seam on border. This isn’t a bug I know, as the calculateNormals method knows only of the currently generated tile. But do you have any ideas on how to solve this?
My idea would be to either make sure that all generated tiles have equal normals at their borders OR you change the normals at the borders to be equal (say 0, 1, 0) OR for each adjacent tile you go and change the normals at the edges where the tiles meet to be the average of the two.
You probably want to change normals before you create a mesh.
Best would be to take two matching vertices, and set average of their normal to both of them. This will give right results and then you create mesh and it will look good.
@max@vaios the normals array returned is a single dimension array holding one value per index. How should I work with this? Finding each point on border and tweaking all three normal dimensions?
Thanks @max, after figuring out the order at which vertices were defined, your code worked beautifully. Though there was no need from my visual tests to do this for the corners. Only for horiz/ver. sides.
The only solution that seems to be working is to use a splatmap (RGBA colormap) to arrange the textures on the terrain, and set CLAMP TO EDGE to that specific splatmap.
So did you originally have 1 texture per 1 mesh? And the textures must seamlessly connect to each other?
The only way I know to fully remove any seams in such situation (done that) is to add border pixels. Suppose you have 256x256 connected tile textures. Imagine they’re all connected into a single big texture. For each tile, you crop it AND an additional border around it (say, 4 pixels) and get a 260x260 texture. Then you shrink it (with these borders) back to 256 to preserve the power of two. So in the end you should have a small overlap between adjacent tiles. Then you need to shrink the UVs correspondingly, so they don’t include the border. The border is only needed for bilinear texture filtering to take correct neighboring values, so you don’t have the seam, but instead the texture is interpolated towards adjacent tile’s pixels.
Now, all this will only work if your texture isn’t mipmapped and doesn’t use anisotropic filtering. If you want mipmapping to work, you can do the same, but use a larger border, not 4 pixels, but 8, 16, 32 etc, then it should work fine with auto-generated mipmaps to some extent (or you can waste less by generating mipmaps manually - maintaining the same border size on every level). Anisotropic filtering will also need a wider border.
No, I don’t have any textures per mesh, only heightmaps from world machine. If I create a splatmap/colormap then the seams are gone. So yes, I’ve a partial solution right now.
I was aware also of this border solution, though I was trying to texture the terrain completely procedurally. Using a number of textures based on criteria like slope, angle, height. But when mixing in the shader I posted above I get these seams.
If you have 1 heightmap per mesh, same border stuff applies. If the heightmap is global and covers multiple meshes, then you shouldn’t have such seams.
Hmm, it is a global heightmap in world machine, that is tiled (using blending) on export to 24x24 heightmap images. The heightmaps are tiled perfectly (vertices line up) and only normals needed some care.
Anyhow, thanks for the help! I will go for the splatmap approach and maybe create some masks on world machine for slopes, erosions, peaks etc.