- Home /
How can I create a grid/tile based shader supporting multiple textures?
See here: https://vid.me/nVlf
Is it possible to achieve something similar to this video with a shader?
I'm creating an in-game level editor and have generated a grid-based mesh to work with. Currently I'm using an alpha blend shader (found at the Unity forums) to blend between two textures at a vertex point, though I'd like to create something like Warcraft 3's World Editor which supports multiple textures. Blending/alpha isn't necessary.
If possible, could somebody point me in the right direction?
Answer by zach-r-d · Jul 16, 2015 at 10:14 AM
An easy and efficient way to do this is to have texture atlas (all of the tile textures are combined into one actual texture, like a sprite sheet) of all the possible tiles, and then handle all of the texture selection with UV coordinates. Normal UV coordinates (Mesh.uv) could be used as the opaque "base" texture, and a second set of UV coordinates (Mesh.uv2) could be used for overlays. Then, all the shader has to do is sample the texture twice and combine the two samples using alpha blending. For tiles that do not have an overlay, it's a simple matter of setting the UV coordinates to a transparent section of the atlas.
It's worth noting that Mesh supports up to four UV sets, so theoretically up to four textures could be overlaid on the same tile in this manner.
I'm having some trouble wrapping my head around shaders & meshes, first time I've worked with either =\
I have a square grid based mesh generated, each grid position should represent a single tile. I'm assu$$anonymous$$g because there's no vertex in the center of a grid position I'll need to snap to a corner and apply a tile texture there ins$$anonymous$$d. http://puu.sh/j2fes/757bada495.png
Here's the code which creates vertices, tangents, uv, and color:
for(int i = 0, y = 0; y <= grid.Rows; y++)
{
for (int x = 0; x <= grid.Columns; x++, i++)
{
VerticeIndex idx = new VerticeIndex();
idx.index = i;
idx.posX = x;
idx.posY = y;
vIndex.Add(idx);
vertices[i] = new Vector3(x * grid.NodeWidth, y * grid.NodeHeight);
uvs[i] = new Vector2((float)x / grid.Rows / 2, (float)y / grid.Columns / 2);
tangents[i] = new Vector4(1, 0, 0, -1);
colors[i] = new Color(255, 255, 255, 255);
}
}
And here's my simple shader: http://pastebin.com/mt$$anonymous$$7UbQ6
With this setup would it be possible to overlay tiles at individual vertex points on the grid? Would I map out a tile from the atlas from within the shader?
edit: Here's my tile sheet as well: http://puu.sh/j2fvN/aeef12e687.png
I'd like to be able to apply a single tile from the atlas to every vertex and maybe have the remaining tiles indexed to be able to easily apply any tile from the atlas to a vertex via code
Oh, with the method described above each square would need to have its own four vertices; sharing wouldn't be possible. Then, each of the uv coordinates at those four vertices (upper left, lower left, upper right, lower right) would need to be set appropriately based on where the UL, LL, UR, and LR coordinates of the tile are in the sheet.
To make math (and life) easier it's a good idea to keep the texture square.
Thanks for the answers, I'll go ahead and mark this as correct. One last question if you don't $$anonymous$$d, what method were you thinking of before, sharing vertices? It looks like Warcraft 3's editor grid snaps to the corner of grid points or individual vertices rather then utilizing the full square, which may be the better option?
I came across an issue doing it this way, setting UV coordinates to (0, 0), (1, 0), (0, 1), (1, 1) for the four vertices making up a square causes the uv mapping to extend into the neighbor triangles, see here: http://puu.sh/j3ky9/7d47358adb.png
Thanks! That screenshot is exactly why it'll be necessary for each square to have its own four vertices (in other words, each square in the mesh is technically unconnected to the others, even though their vertices will sometimes occupy the same space). Otherwise, squares will affect each other, which can possibly work in certain cases but would be very difficult.
The nice thing about editing vertices a la Warcraft 3 is that smooth transitions between terrain types can be generated automatically. Say there's a level that has a section of sand and an adjacent section of grass. If the editor only supports assigning individual tiles to squares, it's up to the level designer to manually set tiles along the border of the two sections to be grass-sand transition tiles (putting a tile of sand right next to a tile of grass creates a hard edge). With vertex-based editing, the designer would simply set a bunch of vertices as sand and a bunch of adjacent ones as grass, then the map editor could figure out which tiles to assign to each square based on the material in each of the square's four vertices.
However, that's ultimately a question of frontend/UI/presentation, which can be implemented independently of how the mesh is generated and rendered.
Your answer
Follow this Question
Related Questions
How do I remove terrain texure blending? 1 Answer
How does the unity terrain shader handle an arbitrary amount of textures ? 1 Answer
Unity Terrain - shader for custom post-splat? 0 Answers
How to automatically apply different textures on terrain based on height? 5 Answers
Strange shading on procedural mesh 0 Answers