unity-LOD优化
LOD, 也就是 Level of Detail
lod 主要是为了在 摄像机 离 物体 不同距离的情况, 显示 模型不同精细级别. 近距离 显示 丰富细节的模型, 远距离 显示 简单的模型. 可以有效减少绘制量, 减少模型顶点数量 (也就是可以减少 shader vertex 阶段的执行量). 缺点是 需要制作多个模型, 会增大包体.
前篇
- 官网文档 - https://docs.unity3d.com/Manual/LevelOfDetail.html
- Unity LOD-Level of Detail(多层次细节)用法教程 - https://blog.csdn.net/ChinarCSDN/article/details/80906038
使用
建一个 空对象a, 丢上需要显示不同级别的模型
对象a 上挂一个 LOD Group 组件, 然后把不同级别模型拖进去, 这里 我把两个 sphere 丢进 LOD0, 是为了体现这个级别需要两个dc.
调整 lod 百分比可以调整与 摄像机触发距离
然后拖动摄像机离 对象a 的距离, 就可以看到效果.
shader 中的 lod
相关资料
- Unity中Shader LOD控制 - https://zhuanlan.zhihu.com/p/21316674
- unity shader lod 使用 - https://blog.csdn.net/WPAPA/article/details/72721104
对于TA来说,Shader LOD其实就是根据设备性能的不同编译不同版本的Shader。
这种编译方式最早是为了适应不同时代的显卡而准备的。主机端本来就不存在这个问题,而现在在PC端上想找到上古级别的显卡也不太容易。所以目前这玩意儿最大的用途也就是为了适配高低配置不同的手机(以上为个人意见)。
使用Shader LOD,要编写多个SubShader,格式大致如下:
1 | Shader "YY/Cube" |
shader 的 lod 定义
Built-in shaders in Unity have their LODs set up this way:
- VertexLit kind of shaders = 100
- Decal, Reflective VertexLit = 150
- Diffuse = 200
- Diffuse Detail, Reflective Bumped Unlit, Reflective Bumped VertexLit = 250
- Bumped, Specular = 300
- Bumped Specular = 400
- Parallax = 500
- Parallax Specular = 600
shader 的 lod 设置
在脚本中,我们可以用 Shader.globalMaximumLOD = 100
来全局设置 lod 值,激活使用相对应的 SubShader。
我们也可以用 _shader.maximumLOD
来单独设置一个 shader 的 lod。
根据这个特性,我们就可以在一个 shader 里写一出组 SubShader ,分别设置不同的 lod ,lod 越大的对应性能越好,越低的性能越差。然后我们就可以用设置 lod 的方法来控制游戏画面的渲染质量。
在 Project Setting->QualitySettings 中的 Maximum LODLevel 可以设置最大LOD等级,Shader的LOD值是小于所设定的LOD值,才会被编译使用。Maximum LODLevel的等级可以设置7个级别,例如设置为1,则表示把最大LOD值设置为100,等级2,则最大LOD值为200,以此类推,若设置为0,则表示不进行LOD判断,任何LOD值的Shader都会被使用。
实际测试情况
参考: ShaderLod.cs
很重要 : shader 需要动态控制使用 subshader 的话, subshader 的顺序 从上到下 必须按 Lod 的 大到小 来写, 才可以动态控制. 如果 从小到大 来写, 只要命中了 小的, 就不会再变了
shader
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19Shader "test/testShaderLod" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" "IgnoreProjector"="True"}
LOD 600
UsePass "test/PassNameBase/PassNameBase02" // green
}
SubShader
{
Tags { "RenderType"="Opaque" "IgnoreProjector"="True"}
LOD 500
UsePass "test/PassNameBase/PassNameBase01" // red
}
}csharp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class testShaderLod : MonoBehaviour {
Material mat;
void Start() {
mat = transform.GetComponent<Renderer>().sharedMaterial;
}
void Update() {
if (Input.GetKeyDown(KeyCode.A)) {
mat.shader.maximumLOD = 500;
Debug.LogFormat("--- maximumLOD = 500");
}
if (Input.GetKeyDown(KeyCode.B)) {
mat.shader.maximumLOD = 600;
Debug.LogFormat("--- maximumLOD = 600");
}
}
}效果
插件 Simple LOD v1.6
- 测试工程 - https://gitee.com/yangxuan0261/Simple-LOD-v1.6
- SimpleLOD - https://www.youtube.com/watch?v=mlqFXnMACtA
看了下这个插件的使用, 貌似不能达到减少 dc 的效果, 因为生产 lod 时, 知识 把 mesh 合并了一下, 减少了顶点, 但是还是和原来一样的 材质数量,贴图数量, 没有减少 dc. 所以还是 unity 内置的中 lod 能达到减少 dc 的效果.