Skip to main content

3Dモデルの仕組み(その2)

模様を付けましょう:UV座標

今までのモデルはすべて白い色で表示してきたが、実際にゲームで使うものは一定色ではない。前回作成した「MyCube」をベースにし、複雑な模様(テクスチャ)を付けてみましょう。具体的に、以下のようなサイコロを作ってみましょう

image.png

この効果を再現するため、2次元の画像を3次元の立方体に貼らないといけないが、そのためなんとかして、「ペーパークラフト」のように3Dのオブジェクトを真っ平にし、2Dに展開しなければならない。

image.png

image.png

3Dモデルの場合、このプロセスは「UV展開」という。「UV」は「正規化した画像座標」のことである。「正規化」とは画像のサイズに関係なく、必ず0〜1の間にある座標系である。

image.png以下、TimmyがUV展開された画像である:

image.png

画像のサイズが異なっても、どちらとも同じUV座標系(0〜1)を持っているため、モデル自体はそのまま使える。

テクスチャサイズ:4096 x 4096

テクスチャサイズ:256 x 256

image.png

image.png

image.png

image.png

それぞれの画像のサイズが異なるが、どちらとも同じUV座標系(0〜1)を持っているため、モデル自体はそのまま使える。今回のサイコロのテクスチャは以下にある


image.png

これで、メッシュを作るときに、頂点ごとに「UV座標」を与え、それぞれの三角形は画像のどの部分を使えば良いか指定しなければならない。これおで、テクスチャを貼り付けるときに、正しく模様を表示される。

課題

「MyCube」を編集し、UV座標を追加してください。

    CreateUVsのメソッドを追加し、上に表示された画像に基づいて、メッシュにUV座標を追加してください たらしいマテリアルを作成し、Base Map をサイコロのテクスチャにし、結果を確認
    MyCube スクリプト(編集分)
    // UV座標
    private Vector2[] uvs;
    
    // Awake は Start よりも一歩速く実行する
    // 内部初期化(他のコンポーネントに依存しない)ときにはおすすめ
    private void Awake()
    {
        CreateVertices();
        CreateTriangles();
        CreateUVs();
    
        mesh = new Mesh();
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.uv = uvs;
        mesh.RecalculateNormals(); // 法線ベクトルを自動計算(※)
        
        // ゲームオブジェクトにMeshFilterを追加
        MeshFilter mf = gameObject.AddComponent<MeshFilter>();
        mf.mesh = mesh;
        
        // MeshRendererも追加
        MeshRenderer mr = gameObject.AddComponent<MeshRenderer>();
        mr.material = material;
    }
    
    // UV座標を作成する
    // 返す:UV座標(2D)の配列
    private void CreateUVs()
    {
        uvs = new Vector2[24];
    
        // 前 (1)
        uvs[0] = new Vector2(0.375f, 0.75f);
        uvs[1] = new Vector2(0.625f, 0.75f);
        uvs[2] = new Vector2(0.625f, 1.00f);
        uvs[3] = new Vector2(0.375f, 1.00f);
    
        // 上 (3)
        uvs[11] = new Vector2(0.375f, 0.50f);
        uvs[18] = new Vector2(0.625f, 0.50f);
        uvs[22] = new Vector2(0.625f, 0.75f);
        uvs[23] = new Vector2(0.375f, 0.75f);
    
        // 後ろ (6)
        uvs[12] = new Vector2(0.625f, 0.25f);
        uvs[13] = new Vector2(0.375f, 0.25f);
        uvs[14] = new Vector2(0.375f, 0.50f);
        uvs[15] = new Vector2(0.625f, 0.50f);
    
        // 下(4)
        uvs[16] = new Vector2(0.375f, 0.00f);
        uvs[17] = new Vector2(0.625f, 0.00f);
        uvs[21] = new Vector2(0.625f, 0.25f);
        uvs[20] = new Vector2(0.375f, 0.25f);
    
        // 右 (5)
        uvs[9] = new Vector2(0.625f, 0.50f);
        uvs[5] = new Vector2(0.875f, 0.50f);
        uvs[6] = new Vector2(0.875f, 0.75f);
        uvs[10] = new Vector2(0.625f, 0.75f);
    
        // 左 (2)
        uvs[8] = new Vector2(0.375f, 0.50f);
        uvs[4] = new Vector2(0.125f, 0.50f);
        uvs[7] = new Vector2(0.125f, 0.75f);
        uvs[19] = new Vector2(0.375f, 0.75f);
    }

    光の計算の入門:法線ベクトル

    3Dでの光の計算が大変複雑なテーマであるが、最も単純なケースから光の計算、および法線ベクトルについて理解していきましょう。まず、以下のようなシーンについて考えてみましょう。

    image.png

    image.png

    図:光源、光線と表面の関係。ここで一番単純な光源を使用(すべての光線は並行である)

    この場合は、光源からいくつかの光線が発射し、表面に当たる。ここで、平面の傾きにより、明るさがどう変わるのか解析してみましょう。表面が光源と真正面になるときに、一番明るく見えるが、表面が表面が光線と並行すると、光が当たらず、真っ黒になってしまう。

    image.png

    image.png

    loading.gif

    image.png