zoukankan      html  css  js  c++  java
  • Unity3D学习笔记2——绘制一个带纹理的面

    1. 概述

    上一篇文章《Unity3D学习笔记1——绘制一个三角形》中介绍了Unity3D的HelloWorld——绘制一个简单的三角形。不过这个三角形太简单了,连材质都没有。那么这里就将三角形扩展为一个矩形的面,并且为这个面贴上纹理。

    2. 详论

    2.1. 网格(Mesh)

    前面说到网格是渲染物体的骨架,因此还是先要把渲染物体的架子搭好。改进一下上一篇文章中的创建Mesh的代码:

    Mesh mesh = new Mesh();
    mesh.name = name;
    
    Vector3[] vertices = new Vector3[4]
    {
        new Vector3(-5, -5, 0),
        new Vector3(-5, 5, 0),
        new Vector3(5, -5, 0),
        new Vector3(5, 5, 0),
    };
    mesh.vertices = vertices;
    
    Vector2[] uv = new Vector2[4]
    {
        new Vector2(0, 0),
        new Vector2(0, 1),
        new Vector2(1, 0),
        new Vector2(1, 1),
    };
    mesh.uv = uv;
    
    Vector3[] normals = new Vector3[4]
    {
        new Vector3(0, 0, -1),
        new Vector3(0, 0, -1),
        new Vector3(0, 0, -1),
        new Vector3(0, 0, -1),
    };
    mesh.normals = normals;
    //mesh.RecalculateNormals();
    
    int[] triangles = new int[6] { 0, 1, 2, 1, 3, 2 };
    mesh.triangles = triangles;
    
    GameObject newGameObject = new GameObject(name);
    MeshFilter mf = newGameObject.AddComponent<MeshFilter>();
    mf.sharedMesh = mesh;
    
    

    2.1.1. 顶点

    因为我们要创建一个矩形的面,所以需要创建四个顶点。仍然是像之前创建三角面的顶点一样,赋予顶点的空间位置属性xyz坐标。同时,我们还给Mesh赋予了4个uv坐标,4个法向量normal。uv坐标是用来计算纹理坐标的,也就是当物体贴上纹理之后的纹理坐标位置;法向量是用来参与光照计算的,如果缺少法向量,很多材质的效果不正确。可以通过mesh.RecalculateNormals()让Unity3D自己计算法向量。

    位置(position/vertice)、纹理坐标(uv/texCoord)、法向量(normal)是经常用到了三个顶点属性,但是顶点属性也不仅仅只有三个,甚至可以根据需要自定义。

    2.1.2. 顶点索引

    一个矩形面确定了四个顶点,但是需要划分成两个三角形,每个三角形引用3个顶点索引,也就是6个顶点索引。当然我们也可以使用6个顶点,按照自然顺序来确定顶点索引。但是这样一来,就浪费了空间存储。这也是使用顶点索引的好处,可以节省空间,毕竟Mesh中的很多顶点是共用的。

    2.2. 材质(Material)

    接下来我们在Unity3D编辑器中创建一个材质,并且在C#脚本中将这个材质给到我们创建的面上。

    2.2.1. 创建材质

    材质和纹理(图片)在Unity3D中被认为是一种资源,要加载他们需要特定的办法。一种比较简单的办法是使用Resources.Load。

    在Assets目录下创建一个名为Resources的文件夹,只有使用这个目录下的资源,使用Resources.Load才能找到。在Resources文件夹下新建一个材质,并把想使用的纹理图片文件移到这个文件夹下:
    imglink1

    点击新建的材质,在Inspector视图中,将纹理图片挂载到这个材质上:
    imglink2

    Unity3D新建的材质默认为标准,是一种PBR材质,由多种贴图混合而成。我们这里暂时只设置Albedo贴图,也就是基本颜色贴图。实际使用时,右边的颜色拾取也能影响到贴图效果,在有贴图时,可以将其拾取成白色。

    2.2.2. 使用材质

    在编辑器中把材质创建好之后,在脚本中就可以直接使用创建好的材质了:

    MeshRenderer meshRenderer = newGameObject.AddComponent<MeshRenderer>();                
    Material material = Resources.Load<Material>("MaterialDemo");   
    meshRenderer.material = material;
    

    2.3. 光照

    点击Play,会发现虽然显示了一个带纹理的面,但是面的颜色显得很暗:
    imglink3

    这是因为光照的位置不对,材质缺少对光照的影响。那么我们调整默认光照Directional Light的Transform,将其调整到和摄像机的位置一致:
    imglink4

    这个时候的光照正好对准了面的正中间:
    imglink5

    最终Game视图中的面也按照正常亮度显示了:
    imglink6

    3. 代码

    全部的C#脚本代码如下:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Main : MonoBehaviour
    {
        // Start is called before the first frame update
        void Start()
        {
            GameObject main = GameObject.Find("/Root");
            if (main == null)
            {
                return;
            }
    
            GameObject triangleGameObject = GreateQuad();
            triangleGameObject.transform.parent = main.transform;
        }
    
        GameObject GreateQuad()
        {
            string name = "quad";
    
            Mesh mesh = new Mesh();
            mesh.name = name;
    
            Vector3[] vertices = new Vector3[4]
            {
                new Vector3(-5, -5, 0),
                new Vector3(-5, 5, 0),
                new Vector3(5, -5, 0),
                new Vector3(5, 5, 0),
            };
            mesh.vertices = vertices;
    
            Vector2[] uv = new Vector2[4]
            {
                new Vector2(0, 0),
                new Vector2(0, 1),
                new Vector2(1, 0),
                new Vector2(1, 1),
            };
            mesh.uv = uv;
    
            Vector3[] normals = new Vector3[4]
            {
                new Vector3(0, 0, -1),
                new Vector3(0, 0, -1),
                new Vector3(0, 0, -1),
                new Vector3(0, 0, -1),
            };
            mesh.normals = normals;
            //mesh.RecalculateNormals();
    
            int[] triangles = new int[6] { 0, 1, 2, 1, 3, 2 };
            mesh.triangles = triangles;
                   
            GameObject newGameObject = new GameObject(name);
            MeshFilter mf = newGameObject.AddComponent<MeshFilter>();
            mf.sharedMesh = mesh;
    
            MeshRenderer meshRenderer = newGameObject.AddComponent<MeshRenderer>();                
            Material material = Resources.Load<Material>("MaterialDemo");   
            meshRenderer.material = material;
    
            return newGameObject;
        }
    
        // Update is called once per frame
        void Update()
        {
            
        }
    }
    
  • 相关阅读:
    51nod 1179 最大的最大公约数 (数论)
    POJ 3685 二分套二分
    POJ 3045 贪心
    LIC
    HDU 1029 Ignatius and the Princess IV
    HDU 1024 Max Sum Plus Plus
    HDU 2389 Rain on your Parade
    HDU 2819 Swap
    HDU 1281 棋盘游戏
    HDU 1083 Courses
  • 原文地址:https://www.cnblogs.com/charlee44/p/14976513.html
Copyright © 2011-2022 走看看