【Unity】程序创建Mesh(二)MeshRenderer、光照、Probes探针、UV信息、法线信息

文章目录


接上文

前面一篇文章【Unity】程序创建Mesh(一)Mesh网格、代码创建模型、顶点信息、三角形信息、MeshFilter、MeshRenderer讲了一部分使用代码创建网格的内容,这一节针对渲染相关的内容再做详解。

MeshRenderer(网格渲染器)

MeshRenderer是Unity中的一个组件,属于UnityEngine命名空间下的一个类,它继承自Renderer类。MeshRenderer的主要作用是渲染由MeshFilter或TextMesh插入的网格。它根据物体的Transform组件的定义位置,从网格过滤器(Mesh Filter)获取几何形状,并在该位置进行渲染。

MeshRenderer还有一些重要的属性,例如Cast Shadows(投射阴影),当这个属性被启用时,如果场景中有创建光照阴影的光源,MeshRenderer将会使对应的Mesh产生阴影。下面简单说明一下MeshRenderer的各项属性。

Materials(材质)

Materials是MeshRenderer中最重要的属性,它控制了网格的材质表现。通过修改MeshRenderer的Materials属性,我们可以改变物体的外观,如颜色、纹理、光照反应等。

具体来说,MeshRenderer的Materials属性是一个Material数组,这意味着一个MeshRenderer可以拥有多个材质。每个材质可以独立地应用到网格的不同部分,从而实现复杂的视觉效果。例如,一个游戏角色的身体部分可能使用一种材质,而武器或服装则使用另一种材质。

在Unity的编辑器中,你可以通过MeshRenderer组件的Inspector窗口来查看和编辑Materials属性。你可以添加、删除或重新排序材质,还可以为每个材质设置不同的Shader和纹理。

在代码中,你也可以通过脚本来操作MeshRenderer的Materials属性。例如,你可以创建一个新的Material,并将其添加到MeshRenderer的Materials数组中,或者修改现有材质的属性来改变物体的外观。

需要注意的是,当你修改MeshRenderer的Materials属性时,你是在修改该MeshRenderer的本地材质副本。如果你希望多个MeshRenderer共享相同的材质,你应该使用Material的实例化(Instance)而不是复制(Clone)。这样,当你修改共享材质的属性时,所有使用该材质的MeshRenderer都会受到影响。

此外,MeshRenderer的Materials属性与MeshFilter的mesh属性是相辅相成的。MeshFilter定义了物体的形状和结构,而MeshRenderer则通过Materials属性定义了这些形状和结构如何被渲染和表现出来。通过合理使用这两个组件,你可以创建出丰富多样的游戏世界和角色。

Material和Mesh对应

在Unity中,当你为MeshRenderer组件分配多个材质时,你需要确保这些材质与你的Mesh的子网格(Submeshes)正确对应。Mesh可以由多个子网格组成,每个子网格可以独立地应用一个材质。

为了将多个材质与Mesh的子网格对应起来,你需要按照以下步骤操作:

  1. 创建子网格:在你的Mesh中,使用SetTriangles方法为不同的部分设置三角形索引,从而创建子网格。每个子网格应包含一组连续的三角形索引。
csharp 复制代码
int[] triangles0 = { /* 三角形索引数组,对应第一个子网格 */ };  
int[] triangles1 = { /* 三角形索引数组,对应第二个子网格 */ };  
// ...更多子网格  
  
mesh.SetTriangles(triangles0, 0); // 设置第一个子网格  
// 设置第二个子网格,注意第二个参数是上一个子网格的三角形数量  
// 第三个参数submeshIndex用于指定子网格的索引。索引从0开始,每个子网格的索引必须唯一。
mesh.SetTriangles(triangles1, triangles0.Length, submeshIndex: 1); 
// ...为更多子网格设置三角形
  1. 分配材质:在你的MeshRenderer组件中,为Materials属性分配一个与你的子网格数量相同的材质数组。
csharp 复制代码
Material[] materials = new Material[mesh.subMeshCount];  
materials[0] = new Material(Shader.Find("SomeShader")); // 为第一个子网格分配材质  
materials[1] = new Material(Shader.Find("AnotherShader")); // 为第二个子网格分配材质  
// ...为更多子网格分配材质  
  
meshRenderer.materials = materials; // 将材质数组分配给MeshRenderer

这里mesh.subMeshCount将返回你的Mesh中子网格的数量,你需要确保分配的材质数组长度与子网格数量相匹配。

  1. 确保索引对应:重要的是要确保你设置的三角形索引与子网格的材质分配正确对应。如果你错误地分配了材质,或者三角形索引与子网格不对应,渲染结果可能会出现问题。
  2. 更新Mesh:在修改了Mesh的结构或材质后,确保调用mesh.RecalculateBounds()来更新Mesh的边界信息,这对于正确的渲染和碰撞检测很重要。
csharp 复制代码
mesh.RecalculateBounds();

通过以上步骤,你可以将多个材质与你创建的Mesh的子网格对应起来,从而实现复杂的材质和渲染效果。这对于创建具有不同材质部分的物体(如角色模型的不同部位使用不同纹理)非常有用。

Lighting光照

MeshRenderer中提供了对于 Lighting(光照)的设置功能,它与场景中的光源(Lights)以及材质(Materials)相互作用,以产生光照效果。

材质定义了物体如何与光源进行交互。材质中的Shader决定了如何计算光照。例如,一个材质可能使用Phong Shading模型来计算光照,而另一个可能使用Lambert Shading。Shader代码决定了光照如何影响物体的颜色、亮度、高光等。

光照的设置内容如下:

Lightmapping

如果勾选了 Lighting 中的 Contribute Global Illuminatior 选项,MeshRenderer 中就会出现对于 Lightmapping 的相关设置内容。

Lightmapping设置内容如下:

材质中的光照

在材质中可以设置多种光照属性,如:

  • Albedo(反照率):物体的基础颜色。
  • Metallic(金属度):物体表面的金属程度,影响高光反射。
  • Smoothness(光滑度):影响高光的大小和强度。
  • Emissive(自发光):物体自身发出的颜色,不受光源影响。

这些属性在Shader中用于计算光照结果。

光源类型

Unity支持多种光源类型,每种类型都有其独特的光照属性:

  • Directional Light(方向光):模拟来自无限远处的光源,如太阳。它有一个方向和一个颜色。
  • Point Light(点光源):从一个点向所有方向发射光线的光源。它有一个位置、颜色和范围。
  • Spot Light(聚光灯):从一个点发射光线,但只在一个圆锥体内照亮物体。它有一个位置、颜色、范围和圆锥体的角度。
  • Area Light(区域光):模拟一个具有面积的光源,可以产生更柔和的阴影。

阴影

阴影是光照系统中的一个重要部分。在Unity中,你可以为光源启用阴影,并选择阴影的类型(如硬阴影或软阴影)。阴影的渲染质量和性能消耗取决于你选择的阴影设置。

MeshRenderer 会根据场景中的光源和物体的材质来计算阴影。如果物体的材质或光源没有启用阴影,那么该物体就不会产生或接收阴影。

全局光照

全局光照(Global Illumination, GI)考虑了场景中所有光源对物体的间接照明影响。在Unity中,你可以使用实时全局光照(Realtime GI)或烘焙全局光照(Baked GI)来模拟这种效果。MeshRenderer 会与这些全局光照系统相互作用,以产生更真实的光照效果。

Probes(探针)

在Unity中,MeshRenderer中的Probes主要指的是光照探针(Light Probes)反射探针(Reflection Probes),它们用于在场景中获取光照和反射信息,以增强渲染的真实感。

  • 光照探针用于在光照计算中获取场景中的光照信息。它们能够捕捉场景中的光照数据,并在运行时为物体提供光照信息。这样,即使物体在场景中移动,也能根据最近的光照探针进行光照计算,实现平滑的光照过渡。光照探针的设置可以在MeshRenderer组件中进行调整,默认情况下,所有游戏对象都会使用光照探针,并在场景中改变位置时在最近的探针之间进行混合。
  • 反射探针则用于在反射计算中获取场景中的反射信息。它们能够捕捉场景中的环境反射数据,使得物体能够呈现出更真实的反射效果。通过反射探针,游戏开发者可以在物体表面模拟出周围环境的倒影和反射,提升游戏画面的质感。

在使用光照探针和反射探针时,开发者需要注意正确设置MeshRenderer组件的相关参数,以确保探针能够正确工作。此外,根据场景的具体需求和性能考虑,开发者还需要合理选择探针的数量和分布,以达到最佳的光照和反射效果。

探针的设置内容如下:

Ray Tracing(光线追踪)

在使用High Definition Render Pipeline(HDRP)管线时,在MeshRenderer中可以设置光追模式,分别为:

  • Off:关闭;
  • Static:静态光追;
  • Dynamic Transform(默认):动态变换;
  • Dynamic Geometry:动态几何。

关于HDRP的详细内容,可以直接到 Unity 手册中去查看,内容还是比较全面的,这里附上链接:高清渲染管线 (High Definition Render Pipeline)用户手册

Additional Settings

额外属性设置:

UV信息

csharp 复制代码
// 设置网格的UV坐标(可选,但通常用于纹理映射)
Vector2[] uvs = new Vector2[]
{
    new Vector2(0, 0),
    new Vector2(1, 0),
    new Vector2(1, 1),
    new Vector2(0, 1)
};
mesh.uv = uvs;

设置Mesh的UV坐标的基本原理主要是为了实现纹理映射,确保纹理能够正确地贴合到三维模型的表面上。UV坐标是一个二维坐标系,其中U代表横向(水平)坐标,V代表纵向(垂直)坐标。在三维建模中,每个顶点都可以被赋予UV坐标,这些坐标用于将纹理映射到多边形表面上。

UV坐标的取值范围通常在0到1之间,包括0和1两个端点。这样无论图像的像素分辨率是多少,UV坐标都可以换算成贴图的像素坐标。通过将纹理图像的每个像素与模型表面的顶点进行对应,我们可以实现纹理的精确映射。

在设置UV坐标时,需要考虑到模型的几何形状和纹理的特点。不同的模型部分可能需要使用不同的UV坐标,以确保纹理能够正确地贴合到模型的各个表面上。同时,还需要注意UV坐标的连续性和平滑性,以避免在纹理映射时出现明显的接缝或拉伸现象。

除了基本的UV坐标设置外,还可以使用一些高级技术来优化纹理映射效果,比如UV展开和UV打包。UV展开是将三维模型的表面展开到二维平面上,以便更好地编辑和调整UV坐标。UV打包则是将多个模型的UV坐标合并到一个纹理图中,以提高纹理的利用效率和渲染性能。

总之,设置Mesh的UV坐标是实现纹理映射的关键步骤之一,需要根据模型的几何形状和纹理特点进行精确的设置和调整。

法线信息

csharp 复制代码
// 设置网格的法线(可选,但通常用于光照计算)
Vector3[] normals = new Vector3[]
{
    Vector3.up,
    Vector3.up,
    Vector3.up,
    Vector3.up
};
mesh.normals = normals;

在Unity中使用代码来创建Mesh并指定法线信息时,需要提供一个Vector3数组,数组中每个元素对应一个Mesh顶点(一一对应),用于指定每个顶点的法线方向。如果你的Mesh是由平滑的面组成,你可能还需要计算平滑法线,这通常涉及到对相邻面的法线进行平均。

最后

关于UV和法线相关的更细节的内容,我会在渲染章节再进行细致的学习和记录(详见文档下方的目录),欢迎大家一起学习。


更多内容请查看总目录【Unity】Unity学习笔记目录整理

相关推荐
躺下睡觉~6 小时前
Unity-Transform类-父子关系
java·unity·游戏引擎
躺下睡觉~6 小时前
Unity-Transform类-缩放和看向
unity·游戏引擎
君莫愁。8 小时前
【Unity】检测鼠标点击位置是否有2D对象
unity·c#·游戏引擎
咩咩觉主9 小时前
Unity实战案例全解析:PVZ 植物卡片状态分析
unity·c#·游戏引擎
蓝裕安12 小时前
伪工厂模式制造敌人
开发语言·unity·游戏引擎
谢泽浩16 小时前
Unity 给模型贴上照片
unity·游戏引擎
z2014z16 小时前
Unity Resource System 优化笔记
unity·游戏引擎
王维志16 小时前
Unity 高亮插件HighlightPlus介绍
unity·游戏引擎
zaizai100717 小时前
我的demo保卫萝卜中的技术要点
unity
菌菌巧乐兹19 小时前
Unity 百度AI实现无绿幕拍照抠像功能(详解版)
人工智能·百度·unity