I generate a cube procedurally through C#, now I want to paint to top of that cube green, and the sides brown. As far as I understand it I have 2 options, either:
- Paint it using vertex colors through script.
- Paint it based on normals direction via shader
I am fine using either method, but know very little about both and can’t find anything to get me started. I would very much prefer doing it via vertex color, since I want to paint individual faces of a larger mesh in the future.
I have managed to set a single color using vertex colors via script, but that is about as far as I get:
void SetColors()
{
Color[] colors = new Color[mesh.vertices.Length];
for (int i = 0; i < mesh.vertices.Length; i++)
{
Debug.Log(mesh.vertices[i]);
colors[i] = Color.green;
}
mesh.colors = colors;
}
if I print a list of my vertices I have 24 verts, all at different comcinations of (0.5, 0.5, 0.5) - (-0.5, -0.5, -0.5). This makes sence since there are 6 faces, and each face has 4 verts. But how do I know which verts are part of the top face?
Need some help painting a cube 2 different colors based on face direction (horizontal = grass, vertical = dirt).
EDIT full code:
Mesh generation of landscape of cubes:
using UnityEngine;
using System.Collections.Generic;
public class VoxelMeshGenerator : MonoBehaviour
{
const int VERT_LIMIT = 60000;
const float SCALE = .5f;
Mesh mesh;
List<Vector3> vertices;
List<int> triangles;
List<int> test = new List<int>();
public GameObject chunkPrefab;
private GameObject activeChunk;
public void GenerateVoxelMesh(VoxelMapGenerator mapGen)
{
InitChunk();
for (int z = 0; z < mapGen.GetWidth() * mapGen.scale; z += mapGen.scale)
{
for (int x = 0; x < mapGen.GetDepth() * mapGen.scale; x+=mapGen.scale)
{
if (mapGen.GetCell(x, z) == 1)
continue;
MakeCube(mapGen.scale, new Vector3(x, 0, z), x ,z, mapGen);
if(vertices.Count >= VERT_LIMIT)
{
UpdateMesh();
InitChunk();
}
}
}
UpdateMesh();
}
void SetColors()
{
Color[] colors = new Color[mesh.vertices.Length];
for (int i = 0; i < mesh.vertices.Length; i++)
{
Debug.Log(mesh.vertices[i]);
colors[i] = Color.green;
}
mesh.colors = colors;
}
void InitChunk()
{
vertices = new List<Vector3>();
triangles = new List<int>();
activeChunk = Instantiate(chunkPrefab, transform);
mesh = activeChunk.GetComponent<MeshFilter>().mesh;
}
void MakeCube(float cubeScale, Vector3 cubePos, int x, int z, VoxelMapGenerator mapGen)
{
for (int i = 0; i < 6; i++)
{
if (mapGen.GetNeighbor(x,z, (Direction)i) == 1)
MakeFace((Direction)i, cubeScale, cubePos);
}
}
void MakeFace(Direction dir, float faceScale, Vector3 facePos)
{
vertices.AddRange(CubeMeshData.FaceVertices(dir, faceScale, facePos));
int vCount = vertices.Count;
triangles.Add(vCount - 4);
triangles.Add(vCount - 4 + 1);
triangles.Add(vCount - 4 + 2);
triangles.Add(vCount - 4);
triangles.Add(vCount - 4 + 2);
triangles.Add(vCount - 4 + 3);
}
void UpdateMesh()
{
mesh.Clear();
mesh.vertices = vertices.ToArray();
mesh.triangles = triangles.ToArray();
mesh.RecalculateNormals();
activeChunk.GetComponent<MeshCollider>().sharedMesh = mesh;
}
}
CubeMeshData:
using UnityEngine;
public static class CubeMeshData
{
public static Vector3[] vertices = {
new Vector3( 1, 1, 1),
new Vector3(-1, 1, 1),
new Vector3(-1, -1, 1),
new Vector3( 1, -1, 1),
new Vector3(-1, 1, -1),
new Vector3( 1, 1, -1),
new Vector3( 1, -1, -1),
new Vector3(-1, -1, -1)
};
public static int[][] faceTriangles = {
new int[] { 0, 1, 2, 3 },
new int[] { 5, 0, 3, 6 },
new int[] { 4, 5, 6, 7 },
new int[] { 1, 4, 7, 2 },
new int[] { 5, 4, 1, 0 },
new int[] { 3, 2, 7, 6 }
};
public static Vector3[] FaceVertices(int dir, float scale, Vector3 pos)
{
Vector3[] fv = new Vector3[4];
for (int i = 0; i < fv.Length; i++)
{
fv[i] = (new Vector3(vertices[faceTriangles[dir][i]].x * scale, vertices[faceTriangles[dir][i]].y, vertices[faceTriangles[dir][i]].z * scale)) + pos;
}
return fv;
}
public static Vector3[] FaceVertices(Direction dir, float scale, Vector3 pos)
{
return FaceVertices((int)dir, scale, pos);
}
}