PBR texture splatting (up to 64 textures)

I am trying to add support to the Unity Exporter For terrains… My Splatmap Shader gets the common GLSL EDGE SEAMS issue when using fract especally with a TEXTURE ATLAS…

I would love to see how your dealing with that :slight_smile:

I put up a SS here: Custommaterial and importmesh as I found a bug with pbrcustommaterial.

Its a very early prototype and the splatmap isn’t done yet as the terrain assignments are not yet complete. My use case is all square tiles hence the tiled look. I don’t see any obvious edge seams from my side. Using 1k splatmap, diffuse, normals, roughness and macro texture for testing purposes right now.

Hope it helps.

I’m interested in how you managed to fix the issue mentioned by @MackeyK24 as well.
I’ve been doing some experimenting for the past few days, as I needed some more juice for my terrain. I’m using an atlas for my textures, as well as an atlas for my splatmaps, giving me 12 out of 16 different texture tiles in this example: https://www.babylonjs-playground.com/#LIVRIY#37
I’m only using the RGB channels in the splat atlas, so only 3 texture tiles/splat tile. But it’s good enough for me :stuck_out_tongue:
Only real issue is the aliasing/edge issue, although I can live with that as long as I have those extra textures to play with.

1 Like

Hi, pls take a look at this: https://www.babylonjs-playground.com/#LIVRIY#38
comment and uncomment line 26/27 to see the difference.
Does this help?

1 Like

Thank you for your input. I’ve now been at it for 10 days straight!! without getting satisfying results. Having linear interpolation + atlassing + working mipmaps is just too damn hard :stuck_out_tongue:
My terrain requires loads of textures, so atlassing is a must, and at the same time, without mipmaps, or even decent mipmaps, it all looks terrible. My current stage of the terrain gives me a raging headache after 20 minutes, but it’s better than a blant and boring visual feel. I tried everything. Generating my own mipmaps(Using dds as it seems there might be a bug with ktx containers and mipmaps), all the samplingmodes, the 4-tap algo, half texel, repeated padding, various implementations and ported examples. I guess I’ll wait for Babylon to implement array textures or for someone else smarter than me to implement atlassing. I know a couple of guys are on top of it. It’s just a shame throwing away Webgl1 support, but damn :stuck_out_tongue:

Hi, sorry to hear that. Did the fix in the pg solve the edge seams? It looked well on my screen.

What still seems to be the problem ? Lemme know, thks !

It did help. The issue here is, that I want linear filtering in order to really take advantage of the textures, instead of the blocky look of the nearest filter. Now, using texture2DLodEXT instead of just texture2D, I’ve managed to “sort of” get rid of the seams. They are not perfect due to the 5px padding I use and this line:
sc.x+(sc.x0.005)+0.005, sc.y+(sc.y0.005)+0.005
Which is more or less trial and error. You can still see the padding, but it’s good enough for me.
I used this example: ogre/SGXLib_TextureAtlas.glsl at c7cf1e078a4ede4fbbc23b2c1a8441bc31af3a6b · OGRECave/ogre · GitHub
Which linked to this example: http://www.gamedev.net/topic/534149-solved-texture-seams-using-atlas-with-screenshots/
Which originates from this example: Terrain texturing explained - Journal of Ysaneya - GameDev.net

Look at this example using texture2D: https://www.babylonjs-playground.com/#LIVRIY#51
Now look at this example using texture2DLodEXT: https://www.babylonjs-playground.com/#LIVRIY#50
Huge difference, and since it’s an extension for webgl1(enabled by default in webgl2), I assume it’s decently supported.
So the last real issue now is mipmapping. I know nasim is working on a way of dealing with it, taking up a bit of extra space on the texture, but should be worth it, since the glitter you see in the background, caused my mipmaps, get’s crazy if you have a moving object close to the ground.
Look what happens if you force a lower resolution mipmap level: https://www.babylonjs-playground.com/#LIVRIY#52
The seams get pretty clear.

I did a test as well to see if the determination of mipmap level function worked as expected: https://www.babylonjs-playground.com/#LIVRIY#53

So I’m far from done, but still getting a little closer.

1 Like

I don’t have much to contribute here, except I’d be weary of assuming wide support for texture2DLodEXT. WebGL Stats shows support to be at ~50%, mainly due to mobile support only being around ~40% (though having said that, from a brief check of the ios devices I have on hand, they do support it, and most newer androids will support webgl2 anyway).

I was looking into texture wrapping with texture atlases a few months ago, and got near to where you are now before moving on. I agree that using array textures would be far simpler, but at the cost of webgl1 support (and therefore ios support).

1 Like

@Raggar hey thanks, its nice to know cos your initial post didn’t state what the main problem or use case was.

If you have to make an open world terrain, the view frustum is for first person and its not a batch asset, I’d normally ask myself if the details in the distance matter or can you take the shortcut and dof/fog pass it off. Reason is cos there’s always a cost-benefit relationship. WIth manual mipmapping, there’s higher mem consumption and texture space requirements etc. And is really not the modern approach to terrain creation these days. If your target release date is 5 yrs from now, then webgl1 support won’t matter either.

That said, the modern method is to use a macro texture on said mesh first. Then use the splatmap to decide where to blend what textures to. This avoids edge seams as there is no texture tiling and the result looks more natural. It does raise other issues tho as the workflow requires high to low poly asset creation.

I’d hate for you to spend hours pulling hairs when it could be spent making cooler stuff. Hope it helps, cheers!

Yo @phaselock … what do mean macro texture first the do splats gets rid of edge seams ???

no, I meant that in the dx12 world, a few hundred MBs worth of textures are commonplace these days as in AAA games. So splatmap simply pulls straight from the high res textures w/o need for atlases or tiling. 2 decades yrs ago, even 100mb allocated for textures would have been unthinkable.

Yeah I get that… the problem is the 8 texture max limit on mobile iOS devices

Need to be able to support 12 splat layers that would cost 28 textures

So only devices with 32 textures or greater can only be supported

Yeah. I’m not developing specifically for Mobile devices(Since none of mine can run any WebGL context with more than 10FPS) :stuck_out_tongue: , but I would prefer WebGL1. My GPU supports WebGL2, but I develop using WebGL1 for the sole reason of supported older GPU’s.

I’ve actually settled on using texture/texture2D with NEAREST samplingmode. You’ll see seams and less than perfect mipmapping, but I tried prototyping a small game using it, and it will certainly suffice.
I already use FOG , but only periodically, as it’s an “event” in the game, but haven’t tried DOF.
I tried creating a secondary texture to use for mipmaps(bad scale, was a test):https://www.babylonjs-playground.com/#LIVRIY#56
And the 4tap algo: https://www.babylonjs-playground.com/#LIVRIY#58
But I don’t really see a difference between the 4tap and one of the first approaches: https://www.babylonjs-playground.com/#LIVRIY#59
I might have done something wrong, but I’ll just stick to the last one for performance reasons.

1 Like

So, I’m done with the first pass of the texture splatting. Using 15 256x256 textures in a single 1024 atlas. Posted a couple of ss below. Foliage is not using the splat material. Have some perf issues which has nothing to do with the texture splatting. Otherwise, bjs looks sufficient for generating low/mid-res terrains at 30fps.

Hope it helps. Cheers!


Loooks really good :slight_smile:

1 Like

Can i please see the shader code :slight_smile:

Looks REALLY good!

1 Like

You can refer to @Raggar 's. His codes are excellent and quite similar to what I’m using. Only difference is he’s using rgb for the splat and segregating the splat map into different zones which is actually a fairly typical method.

Yeah, but how are you handling the edge seams when using a texture atlas… how are your textures packed into the atlas… are you saving each mip level in your texture atlas and manually picking your lod and retrieving the proper lod from atlas ???

Well, as the ss show, I don’t have obvious edge seams. In @Raggar’s, I set his texture atlas to nearest filtering and it did help solve his seams. Mine is similar. I haven’t optimized textures yet, its just 15 256px tex arranged in a 4 by 4 grid on a 1024 tex. I have albedo, normals, roughness, splatmap (all 1k) and a macro at 4k. Not using mipmaps or lod, my use case doesn’t require.

My best suggestion to you is to repro your codes in the PG, like what @Raggar did, then everyone can help. Hope it helps.