GPU发热的元凶之一“带宽” 所以通常我们都会打开mipmap,如下图所示,在unity中可以拖动右上角的条来查看贴图每个等级的mipmap贴图。那么它的等级一共分成0级-9级, 0级表示最清楚,9级表示最模糊。 贴图分辨率是依次减半,如512 256 128 64 32 16 8 4 2 0
所以说如果带了mipmap的贴图在内存上就会多占33%左右,然而显存和纹理带宽就不一定了,如果摄像机离得比较远,就会采用更小的贴图渲染,贴图所占显存小了,那么对应纹理带宽也一并减小,从而性能就优化了。
也有团队为了减少内存,从而关闭了mipmap。这就会导致另一个问题,美术的贴图非常精细,在UI中近距离观察效果很好,可是一旦摄像机拉远,就会出现“噪点”很难看。 所以mipmap一定要打开。
总体来说mipmap是用内存换纹理带宽的一种优化方式。可是内存毕竟涨了33%,所以unity2018.2中提供了streaming流加载贴图mipmap,意思就是用到哪一级mipmap只加载这一级的,其他级的mipmap不加载。这将大量减少内存开销,如下图所示,unity提供了一个demo例子,内存大概减少25%-30%。
到这里大家应该都能很好理解流加载,其实本篇文章我想说的是利用流加载的特性来进一步优化纹理带宽。例如,
1.unity原本默认计算出需要加载第0级的mipmap贴图,我们能不能手动设置成别的级别mimap
2.比如打开非全屏界面,能不能强制将游戏里面所有3D物体的mipmap都降到最低
答案是可行的,有了这两个特性,我们就可以自己灵活控制mipmap按需加载了。
首先我们需要在unity中开启texture streaming,如下图所示,在Quality Setting面板中勾选Texture Streaming,请注意Max Level Reduction这个数值比较重要,它的意思就是mipmap最多可以减小几级,最大是7.默认是2,如果是2的话,那么代码里怎么设置最多只能减少2级.
Max Level Reduction代码中也可以动态修改。
1 2 3 4 |
//mipmap最多可以减少的等级, 默认是2 ,也可以在QualitySettings面板中设置 QualitySettings.streamingMipmapsMaxLevelReduction = 7; |
还需要在Editor Settings中勾选 Enable Texture Streaming,我的测试中即使勾选在编辑器下也未必能有正确的结果,所以大家一定要打出包在真机中查看。
如下代码所示,首先实例化一个Prefab,并且调用requestedmipmaplevel来设置默认加载mipmap的等级。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
void Start() { mr = Instantiate<GameObject>(prefab).GetComponent<MeshRenderer>(); t1 = mr.material.mainTexture as Texture2D; t1.requestedMipmapLevel = 5; //加载第5等级mipmap //t1.ClearRequestedMipmapLevel();可以清空加载mipmap的等级 } void OnGUI() { GUILayout.Label("<size=50>desiredMipmapLevel" + t1.desiredMipmapLevel + "</size>"); GUILayout.Label("<size=50>calculatedMipmapLevel" + t1.calculatedMipmapLevel + "</size>"); GUILayout.Label("<size=50>loadedMipmapLevel" + t1.loadedMipmapLevel + "</size>"); GUILayout.Label("<size=50>loadingMipmapLevel" + t1.loadingMipmapLevel + "</size>"); GUILayout.Label("<size=50>minimumMipmapLevel" + t1.minimumMipmapLevel + "</size>"); GUILayout.Label("<size=50>mipMapBias" + t1.mipMapBias + "</size>"); } |
如下图所示,我们可以看到贴图已经被加载到第5级的mipmap了。此时你可能会有个疑问,如果摄像机拉远拉近是否会影响mipmap,答案是肯定的,只是摄像机拉到最近mipmap也只能5,但是摄像机如果拉远超过了5,那么就会自动适应6 、7级。
这里有几个数值的含义我需要解释一下,
calculatedMipmapLevel:表示当前摄像机与物体的距离计算出需要加载的mipmap等级。
desiredMipmapLevel:表示当前实际加载的mipmap等级,因为我们可能强制设置了加载等级,那么实际加载的可能就和calculatedMipmapLevel不一致了。
mipMapBias:表示加载加载mipmap等级的偏移量,比如原本加载的是0级的mipmap,由于mipMapBias设置了2,所以实际加载的就是2级,这个数值也可以设置成负数,比如原本需要加载2级mipmap,由于设置了-1,所以实际加载1级的mipmap,这样无疑就更浪费性能。
下面我们在代码里动态修改mipmap的等级。
1 2 3 4 5 6 7 8 9 10 |
if (GUILayout.Button("<size=80>调整mipmap等级 +</size>")) { t1.mipMapBias += 1f; //更模糊 } if (GUILayout.Button("<size=80>调整mipmap等级 -</size>")) { t1.mipMapBias -= 1f; //更清楚 } |
unity还提供了streaming controller组件, 需要绑定在摄像机上,其实就是对摄像机所看到的所有物体的mipmap做偏移和上面的用法类似。
我们既然能修改单个物体的贴图的mipmap能否统一修改所有呢?比如现在打开了一个半屏界面,可以将背景中的3D物体的贴图mipmap全部降低。因为UI并不会开mipmap所以即使降低也不会受影响。
1 2 3 4 5 6 7 8 9 10 11 |
if (GUILayout.Button("<size=80>整体减低采样 -</size>")) { //0表示正常尺寸 //1表示降低1/2 //2表示降低1/4 //3表示降低1/8 //4表示降低1/16 QualitySettings.masterTextureLimit = 4; } |
- 本文固定链接: https://www.xuanyusong.com/archives/4699
- 转载请注明: 雨松MOMO 于 雨松MOMO程序研究院 发表
请假下。Texture2D.requestedMipmapLevel 这个参数我不关怎么修改 ,在真机上都是不起效, desiredMipmapLevel和requestedMipmapLevel 值都是-1?请问是什么情况?
想请教下 streaming controller 这个组件怎么应用 , 他不像 t1.mipMapBias +/- =1 这个加减都有效果 . 我默认设置为5,创建出来的物体贴图都是模糊的,然后减少streamingMipmapBias的数值,贴图逐渐清晰,但是再增加,贴图不会变回模糊的。如果默认设置为0,创建出来的物体都是清晰的,再修改streamingMipmapBias的数值,结果都没变化,修改数值后再创建物体还是清晰的。