Unity如何实现材质按照实际比例覆盖/延伸
今天上司指派了一个新任务,要求材质按照实际比例覆盖上物体,即如果有一块10X10的玻璃,但是贴图是1X1,那么贴图则需要100份,如果贴图是10X10,那么只要贴图左下角的那一部分。
解决方法:
- 如果用的是Image组件 ,那么操作将会特别简单,只需要先将贴图的 Texture Type改为Sprite,然后把精灵作为Image的数据源,然后将Image组件的Image Type改为Tiled即可,此时自由改变Image组件的大小,发现变大时贴图增加渲染的部分,变小则减少渲染的部分;
变大时:
变小时: - 用的不是Image组件,而是其他组件,此时则需要通过material组件赋予其材质,material中有一个shader选择,我们选择Unlit/Texture,通过改变Tiling中的X数值和Y数值决定渲染的数量,其中X控制的是横向,Y轴控制的是纵向,值是多少,就代表渲染多少个贴图(材质);
这里我们拿Cube举例。
先将图片精灵给材质,然后将材质给Cube,效果如下:每个面只渲染了一个。
现在我们尝试改变一下material中的shader材质中的Tiling属性,将X改为2,Y改为0.5,效果如下:Y轴只显示一半没有问题,但是X轴应该显示两个,但是却只显示了一个。
这是因为我们没有将图片精灵的Wrap Mode改为Repeat,改完之后就显示就正常了
假设Cube每个面是10X10,但是贴图只有1X1,将Tiling的X和Y分别改为10,效果如下:
这种方法需要通过代码拿到需要渲染的物体与材质的宽高比,然后将比例给予Tiling,则可以正常显示,但是存在一个问题,如果多个物体同用一个材质,但是他们的尺寸又不一样,这就会导致数据混乱,接下来我们进入第三种方法,通过控制uv值一劳永逸。 - 通过提前设置好UV值,避免多个物体共用一个材质起冲突;
简单说一下我对UV的理解,U就是要渲染的横轴方向,V就是要渲染的纵轴方向,W是Z轴(这里暂不讨论),通常取值在0~1,设置好需要渲染物体的UV与材质的UV即可进行比对。
此时我们即可利用这一点,设置一个标准单位,此处拿米距离,需要渲染的物体UV都设置为10,代表十米,材质UV设置为1,代表一米,那么则需要一百个去覆盖(渲染)。
此时并没有改变material(材质)shader中的Tiling,而是unity编辑器自动进行匹配。
代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MeshUvTest : MonoBehaviour {
private List<Vector3> points = new List<Vector3>();
void Start () {
points.Add(new Vector3(0, 0, 0));
points.Add(new Vector3(0, 3, 0));
points.Add(new Vector3(3, 3, 0));
points.Add(new Vector3(3, 0, 0));
MeshDrawQuad();
}
void MeshDrawQuad()
{
//新建一个Mesh
Mesh quadMesh = new Mesh();
//把顶点的集合赋值给Mesh的顶点组
quadMesh.vertices = points.ToArray();
//设置quad顶点数量,画quad相当于画两个三角形
int[] quadPoints = new int[6];
quadPoints[0] = 0;
quadPoints[1] = 1;
quadPoints[2] = 3;
quadPoints[3] = 3;
quadPoints[4] = 1;
quadPoints[5] = 2;
//把Quad的数量(顺序)给Mesh的三角计数
quadMesh.triangles = quadPoints;
//添加uv的参数设置
Vector2[] uvs = new Vector2[points.Count];
uvs[0] = new Vector2(0, 0);
uvs[1] = new Vector2(0, 10);
uvs[2] = new Vector2(10, 10);
uvs[3] = new Vector2(10, 0);
//把uvs信息赋值给QuadMesh.uv
quadMesh.uv = uvs;
GetComponent<MeshRenderer>().material.SetTextureScale("_MainTex", new Vector2(1, 1));
//设置quad的相关参数
quadMesh.RecalculateBounds();
quadMesh.RecalculateNormals();
quadMesh.RecalculateTangents();
//把设置Quad的相关参数的Mesh赋值给MeshFilter组件
GetComponent<MeshFilter>().mesh = quadMesh;
}
}
到此即可完成上司交给我的要求。
关于画图的逻辑与UV的逻辑此处暂不讨论,刚入职对这些也不懂,暂时是和画图中XY的值设置为一样。
[Demo小案例] ()
ps:这里是刚入职的U3D萌新一只,日常中遇到问题记录一下解决方法,上述内容全是个人实践总结的经验,拿出来和大家分享一下,不一定对。如果有错还请多多指教。