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文件夹下新建一个材质,并把想使用的纹理图片文件移到这个文件夹下:

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

Unity3D新建的材质默认为标准,是一种PBR材质,由多种贴图混合而成。我们这里暂时只设置Albedo贴图,也就是基本颜色贴图。实际使用时,右边的颜色拾取也能影响到贴图效果,在有贴图时,可以将其拾取成白色。
2.2.2. 使用材质
在编辑器中把材质创建好之后,在脚本中就可以直接使用创建好的材质了:
MeshRenderer meshRenderer = newGameObject.AddComponent<MeshRenderer>();
Material material = Resources.Load<Material>("MaterialDemo");
meshRenderer.material = material;
2.3. 光照
点击Play,会发现虽然显示了一个带纹理的面,但是面的颜色显得很暗:

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

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

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

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()
{
}
}
Unity3D学习笔记2——绘制一个带纹理的面的更多相关文章
- Unity3D学习笔记1——绘制一个三角形
目录 1. 绪论 2. 概述 3. 详论 3.1. 准备 3.2. 实现 3.3. 解析 3.3.1. 场景树对象 3.3.2. 绘制方法 4. 结果 1. 绪论 最近想学习一下Unity3d,无奈发 ...
- Unity3D学习笔记3——Unity Shader的初步使用
目录 1. 概述 2. 详论 2.1. 创建材质 2.2. 着色器 2.2.1. 名称 2.2.2. 属性 2.2.3. SubShader 2.2.3.1. 标签(Tags) 2.2.3.2. 渲染 ...
- Unity3D学习笔记4——创建Mesh高级接口
目录 1. 概述 2. 详论 3. 其他 4. 参考 1. 概述 在文章Unity3D学习笔记2--绘制一个带纹理的面中使用代码的方式创建了一个Mesh,不过这套接口在Unity中被称为简单接口.与其 ...
- Unity3D学习笔记12——渲染纹理
目录 1. 概述 2. 详论 3. 问题 1. 概述 在文章<Unity3D学习笔记11--后处理>中论述了后处理是帧缓存(Framebuffer)技术实现之一:而另外一个帧缓存技术实现就 ...
- Unity3D学习笔记8——GPU实例化(3)
目录 1. 概述 2. 详论 2.1. 自动实例化 2.2. MaterialPropertyBlock 3. 参考 1. 概述 在前两篇文章<Unity3D学习笔记6--GPU实例化(1)&g ...
- WebGL three.js学习笔记 6种类型的纹理介绍及应用
WebGL three.js学习笔记 6种类型的纹理介绍及应用 本文所使用到的demo演示: 高光贴图Demo演示 反光效果Demo演示(因为是加载的模型,所以速度会慢) (一)普通纹理 计算机图形学 ...
- Unity3D学习笔记6——GPU实例化(1)
目录 1. 概述 2. 详论 3. 参考 1. 概述 在之前的文章中说到,一种材质对应一次绘制调用的指令.即使是这种情况,两个三维物体使用同一种材质,但它们使用的材质参数不一样,那么最终仍然会造成两次 ...
- 【web开发学习笔记】Structs2 Result学习笔记(三)带參数的结果集
Result学习笔记(三)带參数的结果集 第一部分:代码 //前端 <head> <meta http-equiv="Content-Type" content= ...
- unity3d学习笔记(一) 第一人称视角实现和倒计时实现
unity3d学习笔记(一) 第一人称视角实现和倒计时实现 1. 第一人称视角 (1)让mainCamera和player(视角对象)同步在一起 因为我们的player是生成的,所以不能把mainCa ...
随机推荐
- [bug] docker:write /var/lib/docker/tmp/GetImageBlob613162680: no space left on device
原因 分区空间不够,无法安装镜像 参考 https://www.cnblogs.com/elizwy/p/7722898.html https://blog.csdn.net/TinyJian/art ...
- [刷题] 283 Move Zeros
要求 将所有的0,移动到vector的后面比如; [1,3,0,12,5] -> [1,3,12,5,0] 实现 第一版程序,时间.空间复杂度都是O(n) 1 #include<iostr ...
- 关于flume中涉及到时间戳的错误解决,Expected timestamp in the Flume even
在搭建flume集群收集日志写入hdfs时发生了下面的错误: java.lang.NullPointerException: Expected timestamp in the Flume event ...
- 国内Ubuntu16.04下载地址<其他系统可返回最首项>
ubuntu16.04下载地址: 中科大源 http://mirrors.ustc.edu.cn/ubuntu-releases/16.04/ 阿里云开源镜像站 http:/ ...
- localectl set-locale LANG=en_US.UTF-8
localectl set-locale LANG=en_US.UTF-8
- MySQL给某个用户给某个库表设置权限
-- 用root(最高权限的用户)进行以下操作-- 创建数据库:emc_power CREATE DATABASE emc_power DEFAULT CHARACTER SET utf8 COLLA ...
- Zabbix 自定义report
#!/bin/bash . /etc/profile logdir='/home/admin/zabbix/zabbix_log' mysql_host='localhost' mysql_user= ...
- Linux如何设置用户登录超时(闲置时间)vi /etc/profile ... export TMOUT=900
Linux如何设置用户登录超时(闲置时间) 转载莫负寒夏ai 最后发布于2019-08-08 15:04:22 阅读数 1897 收藏 展开 1. 针对所有用户 # vi /etc/profile ...
- linux进阶之计划任务及压缩归档
本节内容 1. at一次性计划任务(atd) at 时间点 command ctrl+d:保存 -l:查看计划任务 atrm:删除计划任务 atq:查看计划任务 2. crontab周期性计划任务(c ...
- Mybatis 逆向工程使用(Day_17)
有三个方法可以解决所有的问题:接受,改变,离开.不能接受那就改变,不能改变,那就离开. [何为逆向工程?] 众 所 周 知 ,正向工程就是通过JAVA类的设置来生成对应的数据库表. MyBatis逆向 ...