- Home /
How to correctly shader vertices on a grid.
I have created a plane with a vertex grid on it using the code below. I am trying to set the colours of the grid to a random colour to test. The grid is 60x60 tiles but when I apply my random color array (colors[]) to mesh.colors I get a ton of overlapping. Using the code below, how can I colour each of my square tiles in my 60x60 grid a random colour of its own?
// This code was built as part of World of Zero: https://youtu.be/iwsZAg7dReM
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshFilter))]
public class GeneratePlaneMesh:MonoBehaviour {
public float size = 1;
public int gridSize = 16;
private MeshFilter filter;
Color[] colors;
// Use this for initialization
void Start() {
filter = GetComponent<MeshFilter>();
filter.mesh = GenerateMesh();
}
// Update is called once per frame
void Update() {
}
Mesh GenerateMesh() {
Mesh mesh = new Mesh();
var vertices = new List<Vector3>();
var normals = new List<Vector3>();
var uvs = new List<Vector2>();
for(int x = 0; x < gridSize + 1; ++x) {
for(int y = 0; y < gridSize + 1; ++y) {
vertices.Add(new Vector3(-size * 0.5f + size * (x / ((float)gridSize)),0,-size * 0.5f + size * (y / ((float)gridSize))));
normals.Add(Vector3.up);
uvs.Add(new Vector2(x / (float)gridSize,y / (float)gridSize));
}
}
var triangles = new List<int>();
var vertCount = gridSize + 1;
for(int i = 0; i < vertCount * vertCount - vertCount; ++i) {
if((i + 1) % vertCount == 0) {
continue;
}
triangles.AddRange(new List<int>()
{
i + 1 + vertCount, i + vertCount, i,
i, i + 1, i + vertCount + 1
});
}
Debug.Log(vertices.Count);
colors = new Color[vertices.Count];
for(int c = 0; c < vertices.Count; c++) {
int rand = Random.Range(0,5);
switch(rand) {
case 0:
colors[c] = Color.red;
break;
case 1:
colors[c] = Color.cyan;
break;
case 2:
colors[c] = Color.green;
break;
case 3:
colors[c] = Color.black;
break;
case 4:
colors[c] = Color.blue;
break;
case 5:
colors[c] = Color.white;
break;
}
}
mesh.SetVertices(vertices);
mesh.colors = colors;
Debug.Log(mesh.vertices.Length);
mesh.SetNormals(normals);
mesh.SetUVs(0,uvs);
mesh.SetTriangles(triangles,0);
return mesh;
}
}
Answer by ModLunar · Jun 26, 2018 at 01:30 PM
Side note: Haha yay! The World of Zero is awesome :D
With meshes, they automatically interpolate per-vertex attributes (normals, tangents, vertex colors, uvs (UV0, UV1, UV2, etc.) across triangles using barycentric coordinates on the GPU. Pretty much anything you'd see in a shader in the output struct of the vertex shader going to the fragment (pixel) shader (NORMAL, TANGENT, COLOR, TEXCOORD0, TEXCOORD1, etc.)
There are a couple of ways to stop this, and make it like flat shading. The first way I'll mention is very complicated if you're not used to shaders (but is awesome nonetheless) -- you can use a geometry shader to force all 3 vertices to have the same color, so on each triangle, they appear flat.
However, an easier approach for now you can do is, even though it feels wrong and inefficient, you can make each quad of 2 triangles use completely separate vertices from its neighboring quads. It'll stop them from blending across one another, as long as for each quad, all 4 vertex colors have the same value.
With the last option you stated. I am not sure how to get the triangles and then find the two matching ones. I figure once I have that I can just change the color[c] of the 4 points then do the mesh.colors = colors; line.
Well it should be obvious that you need roughly 4 times as many vertices (at least in the limit). Ins$$anonymous$$d of (tileWidth+1) * (tileHeight+1)
vertices you will need tileWidth*tileHeight*4
vertices. It doesn't really matter how you lay out your vertices in the vertices array. However for easy access i would recommend to simply group the 4 vertices of a single tile together. So imagine the array consists of single tile entries and each entry is made up by 4 values.
Here's a simple case with a 3x3 grid:
// T0 T1 T2
// T3 T4 T5
// T6 T7 T8
Imagine every tile here has 4 seperate vertices and we call them a,b,c and d in clockwise order. The layout in the array would be simply like this:
// a0,b0,c0,d0, a1,b1,c1,d1, a2,b2,c2,d2,
// a3,b3,c3,d3, a4,b4,c4,d4, a5,b5,c5,d5,
// a6,b6,c6,d6, a7,b7,c7,d7, a8,b8,c8,d8,
So always 4 consecutive vertices in the array make up one tile. To get the starting array index of a tile you just multiply the tile index by 4:
int firstIndex = 4*(x + y*gridWidth);
The triangles array will simply be filled with pairs of triangles using 4 consecutive indices.
// untested
int tileCount = gridSize * gridSize;
var vertices = new Vector3[tileCount*4];
var normals = new Vector3[vertices.Length];
var uvs = new Vector2[vertices.Length];
var colors = new Color[vertices.Length];
var triangles = new int[tileCount * 2 * 3];
Vector3 offset = new Vector3(-size*0.5f, 0, -size*0.5f);
for(int i = 0; i < tileCount; i++)
{
int x = i % gridSize;
int y = i / gridSize;
Vector2 uv = uvs[i*4 + 0] = new Vector2( x / (float)gridSize, y / (float)gridSize );
vertices[i*4 + 0] = offset + new Vector3(size * uv.x, 0f, size * uv.y);
y++;
uv = uvs[i*4 + 1] = new Vector2( x / (float)gridSize, y / (float)gridSize );
vertices[i*4 + 1] = offset + new Vector3(size * uv.x, 0f, size * uv.y);
x++;
uv = uvs[i*4 + 2] = new Vector2( x / (float)gridSize, y / (float)gridSize );
vertices[i*4 + 2] = offset + new Vector3(size * uv.x, 0f, size * uv.y);
y--;
uv = uvs[i*4 + 3] = new Vector2( x / (float)gridSize, y / (float)gridSize );
vertices[i*4 + 3] = offset + new Vector3(size * uv.x, 0f, size * uv.y);
normals[i*4 + 0] = normals[i*4 + 1] = normals[i*4 + 2] = normals[i*4 + 3] = Vector3.up;
triangles[i*6 + 0] = i*4;
triangles[i*6 + 1] = i*4 + 1;
triangles[i*6 + 2] = i*4 + 2;
triangles[i*6 + 3] = i*4;
triangles[i*6 + 4] = i*4 + 2;
triangles[i*6 + 5] = i*4 + 3;
Color c = GetRandomColor();
colors[i*4+0] = colors[i*4+1] = colors[i*4+2] = colors[i*4+3] = c;
}
Aha thank you Bunny, beat me to it! :) nice work!
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Animated Colorization of UITextMeshPro,Animated vertex color text mesh pro 1 Answer
Shader to change Vertex Colors 0 Answers
color won't change 2 Answers