详细论述了在Unity3D中建一个带纹理的面的过程。

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

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

  1. Mesh mesh = new Mesh();
  2. mesh.name = name;
  3. Vector3[] vertices = new Vector3[4]
  4. {
  5. new Vector3(-5, -5, 0),
  6. new Vector3(-5, 5, 0),
  7. new Vector3(5, -5, 0),
  8. new Vector3(5, 5, 0),
  9. };
  10. mesh.vertices = vertices;
  11. Vector2[] uv = new Vector2[4]
  12. {
  13. new Vector2(0, 0),
  14. new Vector2(0, 1),
  15. new Vector2(1, 0),
  16. new Vector2(1, 1),
  17. };
  18. mesh.uv = uv;
  19. Vector3[] normals = new Vector3[4]
  20. {
  21. new Vector3(0, 0, -1),
  22. new Vector3(0, 0, -1),
  23. new Vector3(0, 0, -1),
  24. new Vector3(0, 0, -1),
  25. };
  26. mesh.normals = normals;
  27. //mesh.RecalculateNormals();
  28. int[] triangles = new int[6] { 0, 1, 2, 1, 3, 2 };
  29. mesh.triangles = triangles;
  30. GameObject newGameObject = new GameObject(name);
  31. MeshFilter mf = newGameObject.AddComponent<MeshFilter>();
  32. mf.sharedMesh = mesh;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class Main : MonoBehaviour
  5. {
  6. // Start is called before the first frame update
  7. void Start()
  8. {
  9. GameObject main = GameObject.Find("/Root");
  10. if (main == null)
  11. {
  12. return;
  13. }
  14. GameObject triangleGameObject = GreateQuad();
  15. triangleGameObject.transform.parent = main.transform;
  16. }
  17. GameObject GreateQuad()
  18. {
  19. string name = "quad";
  20. Mesh mesh = new Mesh();
  21. mesh.name = name;
  22. Vector3[] vertices = new Vector3[4]
  23. {
  24. new Vector3(-5, -5, 0),
  25. new Vector3(-5, 5, 0),
  26. new Vector3(5, -5, 0),
  27. new Vector3(5, 5, 0),
  28. };
  29. mesh.vertices = vertices;
  30. Vector2[] uv = new Vector2[4]
  31. {
  32. new Vector2(0, 0),
  33. new Vector2(0, 1),
  34. new Vector2(1, 0),
  35. new Vector2(1, 1),
  36. };
  37. mesh.uv = uv;
  38. Vector3[] normals = new Vector3[4]
  39. {
  40. new Vector3(0, 0, -1),
  41. new Vector3(0, 0, -1),
  42. new Vector3(0, 0, -1),
  43. new Vector3(0, 0, -1),
  44. };
  45. mesh.normals = normals;
  46. //mesh.RecalculateNormals();
  47. int[] triangles = new int[6] { 0, 1, 2, 1, 3, 2 };
  48. mesh.triangles = triangles;
  49. GameObject newGameObject = new GameObject(name);
  50. MeshFilter mf = newGameObject.AddComponent<MeshFilter>();
  51. mf.sharedMesh = mesh;
  52. MeshRenderer meshRenderer = newGameObject.AddComponent<MeshRenderer>();
  53. Material material = Resources.Load<Material>("MaterialDemo");
  54. meshRenderer.material = material;
  55. return newGameObject;
  56. }
  57. // Update is called once per frame
  58. void Update()
  59. {
  60. }
  61. }

版权声明:本文为charlee44原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/charlee44/p/14976513.html