This IS probably my most copy-pasted answer around the entire forum but there is what I'm doing in Crafterria, and TileVox:
PASTE:You probably know that usually you can mix up to 4 materials per vertex in single pass.
Most old school terrain shaders then support 4 materials per pass with RGBA maps.
What if we can, however, have different set of materials
per triangle?
This is what I am doing in my projects.
4 Materials per triangle.Each triangle need to have its own ID. The ID must be same for all vertices by the triangle.
This ID is used to lookup actual Material Indices from a lookup texture that is using integer format, OR from vertex attributes (e.g. one UV channel with Material IDs, same for the triangle, and one with their splat percentage). I'm diong this in Unity by using Vertex Texture Fetch with vertex attributes in the texture to overcome Unity's limitations, but the example below will explain it with vertex attributes.
Triangle 1:
v1: pos, normal, tangent, color(blend factors RGBA), whatnot, uv2(1,2,5,6)
v2: pos, normal, tangent, color(blend factors RGBA), whatnot, uv2(1,2,5,6)
v3: pos, normal, tangent, color(blend factors RGBA), whatnot, uv2(1,2,5,6)
In this example, uv2 contains the material IDs to use for this single triangle.
Then, in the pixel shader, I'm doing the usual texture splatting and triplanar texturing,
just be sure the IDs are NOT interpolated.
the drawback is, that you must generate true, deoptimized triangle list, because a vertex in triangle 1 CAN and will most likely DO have different IDs that Triangle 2.
For best looking results like these in the Showcase/Crafterria thread, you should use Texture Array (sometimes they call them Array Samplers) - You load all your texture into a texture array with mipmaps, an you are ready to go - use Material IDs directly as Array Sample indices.
Just don't mistake a Texture Array with 3D Texture - with Texture Arrays you get correct mipmaps, they are basically wad of images but with third dimension to access the specific image, and they used to e not that popular at the time I manually had to issue a feature request to get them supported in Unity.
Of course such algorithm requires some preparations, and you will need to calculate your splatting ids on the CPU. And in case more than 5 materials want to contribute to single vertex.... Ignore the least contributor completely and use just the top 4 ranked contributing materials. Trilinear interpolation code is needed for this.
This algorithm also supports multiple material weights per voxel, e.g. you can have semi-grass-semi-dirt voxel, amd if you imlement Heightmap based blending, this will indeed look very, very cool.
This screenshot shows the idea. Notice that most of triangles have contributions set to (1,0,0,0) and only the Red channel contribution is used, however, the per-triangle-id table points to different texture id, the Red Channel texture is different.
In places where blending is needed, Red, Green and even Blue and Alpha channels are used to implement the splatting as and if needed.
This way you get the whole thing rendered in single pass, but it is quite expensive.
