前提・実現したいこと
メッシュに適応しているテクスチャをブレンドするシェーダーを作り、自然な見た目の地形表現をしたい。
該当のソースコード
C#
1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class World : MonoBehaviour 6{ 7 8 public int width; 9 public int height; 10 11 public Tile[,] tiles; 12 13 public Material material; 14 15 Mesh mesh; 16 17 public string seed; 18 public bool randomSeed; 19 20 public float frequency; 21 public float amplitude; 22 23 public float lacunarity; 24 public float persistance; 25 26 public int octaves; 27 28 Noise noise; 29 30 private void Awake() 31 { 32 if(randomSeed == true) 33 { 34 int value = Random.Range(-1000, 10000); 35 seed = value.ToString(); 36 } 37 38 noise = new Noise(seed.GetHashCode(), frequency, amplitude, lacunarity, persistance, octaves); 39 } 40 41 // Use this for initialization 42 void Start() 43 { 44 CreateTiles(); 45 GenerateMesh(); 46 } 47 48 // Update is called once per frame 49 void Update() 50 { 51 Graphics.DrawMesh(mesh, Vector3.zero, Quaternion.identity, material, 0); 52 } 53 54 void CreateTiles() 55 { 56 tiles = new Tile[width, height]; 57 58 float[,] noiseValues = noise.GetNoiseValues(width, height); 59 60 for (int i = 0; i < width; i++) 61 { 62 for (int j = 0; j < height; j++) 63 { 64 if(noiseValues[i,j] > 0.5f) 65 { 66 tiles[i, j] = new Tile(Tile.Type.Grass); 67 } 68 else 69 { 70 tiles[i, j] = new Tile(Tile.Type.Dirt); 71 } 72 } 73 } 74 } 75 76 void GenerateMesh() 77 { 78 MeshData data = new MeshData(tiles); 79 mesh = new Mesh(); 80 81 // 頂点インデックスのフォーマットを32ビット整数に変更する 82 mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; 83 84 mesh.vertices = data.vertices.ToArray(); 85 mesh.triangles = data.triangles.ToArray(); 86 mesh.uv = data.UVs.ToArray(); 87 mesh.RecalculateNormals(); 88 mesh.RecalculateBounds(); 89 } 90}
C#
1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class MeshData{ 6 7 public List<Vector3> vertices; 8 public List<int> triangles; 9 public List<Vector2> UVs; 10 11 public MeshData(Tile[,] data) 12 { 13 vertices = new List<Vector3>(); 14 triangles = new List<int>(); 15 UVs = new List<Vector2>(); 16 17 for(int i = 0; i < data.GetLength(0); i++) 18 { 19 for(int j = 0;j < data.GetLength(1); j++) 20 { 21 CreateSquare(data[i, j], i, j); 22 } 23 } 24 } 25 26 void CreateSquare(Tile tile,int x,int y) 27 { 28 vertices.Add(new Vector3(x + 0, y + 0)); 29 vertices.Add(new Vector3(x + 1, y + 0)); 30 vertices.Add(new Vector3(x + 0, y + 1)); 31 vertices.Add(new Vector3(x + 1, y + 1)); 32 33 triangles.Add(vertices.Count - 1); 34 triangles.Add(vertices.Count - 3); 35 triangles.Add(vertices.Count - 4); 36 37 triangles.Add(vertices.Count - 2); 38 triangles.Add(vertices.Count - 1); 39 triangles.Add(vertices.Count - 4); 40 41 UVs.AddRange(SpriteLoader.instance.GetTileUVs(tile)); 42 } 43 44} 45
C#
1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class Tile{ 6 7 public enum Type { Dirt,Grass } 8 public Type type; 9 10 public Tile(Type type) 11 { 12 this.type = type; 13 } 14} 15
C#
1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class Noise { 6 7 int seed; 8 9 float frequency; 10 float amplitude; 11 12 float lacunarity; 13 float persistance; 14 15 int octaves; 16 17 public Noise(int seed,float frequency,float amplitude,float lacunarity,float persistance,int octaves) 18 { 19 this.seed = seed; 20 this.frequency = frequency; 21 this.amplitude = amplitude; 22 this.lacunarity = lacunarity; 23 this.persistance = persistance; 24 this.octaves = octaves; 25 } 26 27 public float [,] GetNoiseValues(int width,int height) 28 { 29 float[,] noiseValues = new float[width, height]; 30 31 float max = 0f; 32 float min = float.MaxValue; 33 34 for(int i = 0; i < width; i++) 35 { 36 for(int j =0; j < height; j++) 37 { 38 noiseValues[i, j] = 0f; 39 40 float tempA = amplitude; 41 float tempF = frequency; 42 43 for(int k = 0;k < octaves; k++) 44 { 45 noiseValues[i, j] += Mathf.PerlinNoise((i + seed) / (float)width * frequency, j / (float)height * frequency) * amplitude; 46 frequency *= lacunarity; 47 amplitude *= persistance; 48 } 49 50 amplitude = tempA; 51 frequency = tempF; 52 53 if(noiseValues[i,j] > max) 54 { 55 max = noiseValues[i, j]; 56 } 57 58 if(noiseValues[i,j] < min) 59 { 60 min = noiseValues[i, j]; 61 } 62 } 63 } 64 65 for (int i = 0; i < width; i++) 66 { 67 for (int j = 0; j < height; j++) 68 { 69 70 noiseValues[i, j] = Mathf.InverseLerp(max, min, noiseValues[i, j]); 71 } 72 } 73 74 return noiseValues; 75 } 76} 77
C#
1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using System.Linq; 5 6public class SpriteLoader : MonoBehaviour 7{ 8 9 public static SpriteLoader instance; 10 11 Dictionary<string, Vector2[]> tileUVMap; 12 13 // Use this for initialization 14 void Awake() 15 { 16 17 instance = this; 18 19 tileUVMap = new Dictionary<string, Vector2[]>(); 20 21 Sprite[] sprites = Resources.LoadAll<Sprite>("World Tiles"); 22 23 float imageWidth = 0f; 24 float imageHeight = 0f; 25 26 foreach (Sprite s in sprites) 27 { 28 29 if (s.rect.x + s.rect.width > imageWidth) 30 imageWidth = s.rect.x + s.rect.width; 31 32 if (s.rect.y + s.rect.height > imageHeight) 33 imageHeight = s.rect.y + s.rect.height; 34 } 35 36 foreach (Sprite s in sprites) 37 { 38 39 Vector2[] uvs = new Vector2[4]; 40 41 uvs[0] = new Vector2(s.rect.x / imageWidth, s.rect.y / imageHeight); 42 uvs[1] = new Vector2((s.rect.x + s.rect.width) / imageWidth, s.rect.y / imageHeight); 43 uvs[2] = new Vector2(s.rect.x / imageWidth, (s.rect.y + s.rect.height) / imageHeight); 44 uvs[3] = new Vector2((s.rect.x + s.rect.width) / imageWidth, (s.rect.y + s.rect.height) / imageHeight); 45 46 tileUVMap.Add(s.name, uvs); 47 48 //Debug.Log(s.name + " :" + uvs[0] + "," + uvs[1] + "," + uvs[2] + "," + uvs[3]); 49 } 50 51 } 52 53 // Update is called once per frame 54 void Update() 55 { 56 57 } 58 59 public Vector2[] GetTileUVs(Tile tile) 60 { 61 62 string key = tile.type.ToString(); 63 64 if (tileUVMap.ContainsKey(key) == true) 65 { 66 67 return tileUVMap[key]; 68 } 69 else 70 { 71 72 Debug.LogError("There is no UV map for tile type: " + key); 73 return tileUVMap["Void"]; 74 } 75 } 76} 77
試したこと
テクスチャのあるメッシュを生成しましたが、どうやれば目的のシェーダーを作れるのかが分かりませんでした。
回答お願いします。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2019/04/13 12:16
退会済みユーザー
2019/04/15 12:20
2019/04/15 21:39
2019/04/15 21:44