首页 > Unity3D频道 > 【Unity3D研究院之游戏开发】 > Unity3D研究院之LightmapIndex、LightmapScaleOffset、UV2的关系(一百零六)
2019
08-21

Unity3D研究院之LightmapIndex、LightmapScaleOffset、UV2的关系(一百零六)

烘焙Lightmap以后unity会自动给参与烘焙的所有mesh添加uv2的属性,例如,三角形每个顶点都会有UV2它记录着这个每个顶点对应Lightmap图中的UV值,这样拥有3个顶点的三角形面就可以通过UV2在Lightmap中线性采样烘焙颜色了。

LightmapIndex:

所以每个MeshRenderer 需要传入一个LightmapIndex也就是采样哪张Lightmap烘焙图。

LightmapScaleOffset:

由于Mesh的位置摆放的不同,那么即使相同的Mesh的它们烘焙出来UV2肯定是不一样的。我们知道Unity是个大黑盒,我们是不能访问图形API的,渲染一个Mesh我们唯一能做的就是送入Mesh信息,如果相同的Mesh烘焙出来的UV2不一样,那么它将变成多个Mesh文件了,这样送到GPU中无疑是浪费资源(SET PASS CALL 包体大小都会有影响),所以Unity想了个非常好的办法就是LightmapScaleOffset。

 

如下图所示,我们可以看到每个MeshRenderer中都包含了Tiling x Tiling y Offset x Offset y。

Unity3D研究院之LightmapIndex、LightmapScaleOffset、UV2的关系(一百零六) - 雨松MOMO程序研究院 - 1

Offset x Offset y 表示Mesh每个顶点的UV从Lightmap图的Offset x Offset y 处开始采样,还没完上图中我们还可以设置Scale in Lightmap,也就是物体所占烘焙贴图的比例系数,这样光有 Offset x Offset y是不行的,还需要乘以Tiling x Tiling y 。

举个例子,比如现在场景里有两个Cube,由于它们需要共享mesh所以它们的UV2烘焙完以后也是一致的(相对的偏移),如果这两个Cube分别设置了不同的Scale in Lightmap系数,那么它们反应的烘焙贴图上的区域就不同的,那么相同UV2和Offset x Offset y 是无法计算出正确的采样偏移的,所以就需要乘以Tiling x Tiling y  。

如下图所示,FBX在导出的时候需要勾选Generate Lightmap UVs就是是否生成UV2了,换句话说UV2在模型导入的时候就已经设置好了,烘焙不烘焙是改变不了UV2的信息的。

Unity3D研究院之LightmapIndex、LightmapScaleOffset、UV2的关系(一百零六) - 雨松MOMO程序研究院 - 2

前几天我在看Mesh合并的时候,Mesh.CombineMeshes()第4个参数如果为true表示同时合并Lightmap,所以我就在想合并前每个MeshRender的LightmapScaleOffset都是不同的,但是合并完以后怎么给他设置正确的LightmapScaleOffset呢?后来发现根本不用设置LightmapScaleOffset只需要设置LightmapIndex就可以的,顺着这个问题我就在想Unity烘焙贴图的原理。

现在终于搞明白了,Unity会通过LightmapIndex、LightmapScaleOffset在图形API中修正正确的UV2,Mesh.CombineMeshes()之所以能做到这一点是因为提前把正确的UV2赋给Mesh了,既然已经合并Mesh其实也不存在多个共享的需求。

下面我们在代码中重现这个步骤。

先烘焙一下场景,如下图所示,请大家记住CUBE正确的烘焙信息。

Unity3D研究院之LightmapIndex、LightmapScaleOffset、UV2的关系(一百零六) - 雨松MOMO程序研究院 - 3

然后在Hierarchy中选择这个CUBE对象,然后执行Tools/SetUV2把烘焙过的LightmapScaleOffset重新对每个Mesh的UV2赋值,并且保存文件。

如下图所示,最正确的烘焙UV2已经保存在Mesh中了。

Unity3D研究院之LightmapIndex、LightmapScaleOffset、UV2的关系(一百零六) - 雨松MOMO程序研究院 - 4

 

如下图所示,我们创建一个新的CUBE,把MeshFilter中的mesh换成刚刚生成包含完整UV2的新Mesh。

Unity3D研究院之LightmapIndex、LightmapScaleOffset、UV2的关系(一百零六) - 雨松MOMO程序研究院 - 5

此时肯定是没有烘焙信息,因为我们还没有指定LightmapIndex,由于我这个例子只烘焙 出了一张烘焙贴图,所以代码我们这样写。

如下图所示,运行起来我们在看,不需要在设置LightmapScaleOffset依然显示了正确的Lightmap信息。

Unity3D研究院之LightmapIndex、LightmapScaleOffset、UV2的关系(一百零六) - 雨松MOMO程序研究院 - 6

知道了原理,我们还是要慎用,因为这样就无法共享mesh了,对应打包肯定会增加包体大小的。

最后编辑:
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!

留下一个回复

你的email不会被公开。