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 ...
随机推荐
- 神奇的不可见空格<200b>导致代码异常
故事是这样发生的,在做一个JSON对象转化的时候,出现了转化异常:刚开始还是以为是格式错误,后来一步步排除,才发现是不可见空格<200b>导致的解析异常 出现 使用Typora编写文字时, ...
- calico NetworkPolicy on kubernetes
什么是网络策略 在Kubernetes平台中,要实现零信任网络的安全架构,Calico与istio是在Kubernetes集群中构建零信任网络必不可少的组件. 而建立和维护整个集群中的"零信 ...
- 删除所有空白列 cat yum.log | awk '{$1=$2=$3=$4=null;print $0}'>>yum.log1 sed ‘s/[ \t]*$//g' 删除所有空格 sed -i s/[[:space:]]//g yum.log
2.删除行末空格 代码如下: 删除所有空白列 cat yum.log | awk '{$1=$2=$3=$4=null;print $0}'>>yum.log1 sed 's/[ \t]* ...
- VMware虚拟机性能优化
一.ESX及vCenter服务器的优化 检查ESX物理服务器是否在兼容列表中,特别是BIOS的版本是否符合ESX版本的要求 开启ESX物理服务器硬件虚拟化技术VT-X,AMD-V 关闭BIOS中的英特 ...
- linux进阶之网络技术管理
本节内容 1. 网络七层模型 物理层 数据链路层 网络层 传输层 会话层 表示层 应用层 2. TCP/UDP (1)TCP面向连接,可靠传输,消耗系统资源比较多,传输速度较慢,但是数据传 ...
- Lua中的基本函数库--(转自忧郁的加菲猫)
基本函数库为Lua内置的函数库,不需要额外装载assert (v [, message])功能:相当于C的断言,参数:v:当表达式v为nil或false将触发错误,message:发生错误时返回的信息 ...
- MyBaits 全局配置文件(mybatis-config.xml)
什么是 MyBatis 全局配置文件 MyBatis 全局配置文件包含影响 MyBatis 框架正常使用的功能设置和属性信息. 它的作用好比手机里的设置图标,点击这个图标就可以帮助我们查看手机的属性信 ...
- java 文件上传下载
翻新十年前的老项目,文件上传改为调用接口方式,记录一下子~~~ java后台代码: //取配置文件中的上传目录 @Value("${uploadPath}") String pat ...
- Gorm入门使用
Gorm GORM CRUD 数据库的增删改查 go get -u github.com/jinzhu/gorm go get -u github.com/jinzhu/gorm/dialects/m ...
- [leetcode] 75. 分类颜色(常数空间且只扫描一次算法)
75. 分类颜色 我们直接按难度最高的要求做:你能想出一个仅使用常数空间的一趟扫描算法吗? 常数空间 只能扫描一趟.注意,是一趟,而不是O(n) 题中只会出现3个数字:0,1,2.换句话说,0肯定在最 ...