关于Unity中LOD和渲染队列----渲染通道通用指令(一)
每个shader里面有很多的subshader,如果所以的subshader都不执行的话就,就执行fallback。每个subshader都可以设置一个LOD,整个shader也有一个LOD。
系统就去找第一个LOD小于等于shader的LOD的subshader执行,其他的subshader就不会被执行。
LOD
1:LOD Level of Detail, 根据LOD来设置使用不同版本的Shader;
2:着色器中给SubShader一个LOD值,程序来设置这个shader的LOD值,只有第一个小于等于LOD值subShader才会被执行;
3: 每个shader最多只会有一个SubShader被使用;
4: 通过Shader maximumLOD来设置最大的LOD值;
5: 设置全局的LOD值,Shader.globalMaximumLOD;
6: Unity内置着色器分LOD等级:
(1)VertexLit kind of shaders 100
(2) Decal, Reflective VertexLit 150
(3)Diffuse 200
(4)Difuse Detail 250
(5) Bumped, Specular 300
(6) BumpedSpecular 400
(7) Parallax 500
(8) Parallax Specular 600
LOD案例
1.创建Unity工程目录
2.在resources文件夹下面创建一个shaders文件夹
3.在shaders里面创建一个create---->shader---->standard surface shader,重命名LODShader
4.打开LODShader:
Shader "Custom/LODShader" { Properties { _Color ("Color", Color) = (1,1,1,1) _MainTex ("Albedo (RGB)", 2D) = "white" {} _Glossiness ("Smoothness", Range(0,1)) = 0.5 _Metallic ("Metallic", Range(0,1)) = 0.0 } // 每次只会根据情况来选择一个可执行的SubShader // 找到第一个<= Shader.maximumLOD 这个subShader执行; SubShader { Tags { "RenderType"="Opaque" } LOD 600 // LOD-----------------这里设置为600 CGPROGRAM // Physically based Standard lighting model, and enable shadows on all light types #pragma surface surf Standard fullforwardshadows // Use shader model 3.0 target, to get nicer looking lighting #pragma target 3.0 sampler2D _MainTex; struct Input { float2 uv_MainTex; }; half _Glossiness; half _Metallic; fixed4 _Color; void surf (Input IN, inout SurfaceOutputStandard o) { o.Albedo = fixed3(1.0, 0.0, 0.0); } ENDCG } SubShader { Tags { "RenderType"="Opaque" } LOD 500 // LOD-----------------这里设置为500 CGPROGRAM // Physically based Standard lighting model, and enable shadows on all light types #pragma surface surf Standard fullforwardshadows // Use shader model 3.0 target, to get nicer looking lighting #pragma target 3.0 sampler2D _MainTex; struct Input { float2 uv_MainTex; }; half _Glossiness; half _Metallic; fixed4 _Color; void surf (Input IN, inout SurfaceOutputStandard o) { o.Albedo = fixed3(0.0, 1.0, 0.0); } ENDCG } SubShader { Tags { "RenderType"="Opaque" } LOD 400 // LOD-----------------这里设置为400 CGPROGRAM // Physically based Standard lighting model, and enable shadows on all light types #pragma surface surf Standard fullforwardshadows // Use shader model 3.0 target, to get nicer looking lighting #pragma target 3.0 sampler2D _MainTex; struct Input { float2 uv_MainTex; }; half _Glossiness; half _Metallic; fixed4 _Color; void surf (Input IN, inout SurfaceOutputStandard o) { o.Albedo = fixed3(0.0, 0.0, 1.0); } ENDCG } FallBack "Diffuse" }
5.创建一个cube立方体,创建一个材质球为LODShader,材质拖进cube材质属性
6.材质的shader选择custom---->LODShader
7.立方体变红
8.创建一个脚本LOD_ctrl来控制LOD
9.打开LOD_ctrl
using UnityEngine; using System.Collections; public class LOD_ctrl : MonoBehaviour { public Shader shader;//公开属性需要关联 public int LOD_value = 600;//外部来设置shader的LOD的值 // Use this for initialization void Start () { Debug.Log(this.shader.maximumLOD); } // Update is called once per frame void Update () { // 当前这个shader最大的LOD_value; this.shader.maximumLOD = this.LOD_value;//关联的节点可以直接使用和改变 } }
10.当我们改变的公开属性LOD_value的时候,如果是600则是红色,500是绿色,400是蓝色,小于400是fallback白色,如果小于100将不显示任何东西。
渲染队列
Unity的game视图的绘制顺序是先绘制前面的物体,再绘制后面的物体,因为如果是从后面开始绘制,那新的物体如果在前面把旧的物体挡住了,那旧的物体的绘制就是无效的,很浪费。不像2D是先绘制旧物体再和新物体叠加在一起。
Unity会把物体分成几个绘制的队列,属于哪种类型的就丢到哪个队列里面,可以使得绘制的时候最优化,
如果前面的物体是透明的,那后面它挡住的物体只能再绘制,如果前面的物体是不透明的,那后面它挡住的物体可以不绘制,所以要分好几类,减少不必要的绘制。它是基于Mesh绘制的。
所以我们遍历渲染管道来剔除遮挡关系是有意义的,遮挡剔除的运算很厉害。
1:渲染队列标签可选值:
(1)Background 背景,对应的值为1000;
(2)Geometry(default) 几何体对应的值为2000, 这个队列是默认的渲染队列,大多数不透明的物体;
(3)AlphaTest Alpha测试,对应值为2450, alpha测试的几何体使用这种队列,它是独立于 Geometry的队列,它可以在所有固体对象绘制后更有效的渲染采用Alpha测试的对象;
(4)Transparent:透明,对应值3000, 这个渲染队列在Geometry被渲染,采用从后向前的次序;
任何有alpha混合的对象都在这个队列里面渲染;
(5) Overlay 覆盖对应值为4000, 这个渲染队列是最后渲染的物体;
2: Unity 渲染模式: 普通物体从前向后, Alpha从后向前(这个没办法,要看到后面的东西);
2:渲染队列的数值决定了Unity在渲染场景物体时的先后顺序,关闭深度测试的情况下;
渲染队列案例
1:创建两个深度不同的求,配置不同的颜色前面是红,后面是绿;
2.在shaders里面创建一个create---->shader---->standard surface shader,重命名RenderQueue
3: 使后面的绿球使用这个RenderQueue的shader模式
4.打开RenderQueue
Shader "Custom/RenderQueue" { Properties { _Color ("Color", Color) = (1,1,1,1) _MainTex ("Albedo (RGB)", 2D) = "white" {} _Glossiness ("Smoothness", Range(0,1)) = 0.5 _Metallic ("Metallic", Range(0,1)) = 0.0 } SubShader { Tags { "RenderType"="Opaque" "Queue"="Geometry+100" }//设置渲染队列的值,+左右不能用空格,多个tag,不能用逗号; LOD 200 ZTest off//关闭深度测试 CGPROGRAM // Physically based Standard lighting model, and enable shadows on all light types #pragma surface surf Standard fullforwardshadows // Use shader model 3.0 target, to get nicer looking lighting #pragma target 3.0 sampler2D _MainTex; struct Input { float2 uv_MainTex; }; half _Glossiness; half _Metallic; fixed4 _Color; void surf (Input IN, inout SurfaceOutputStandard o) { // Albedo comes from a texture tinted by color o.Albedo = _Color.rgb; } ENDCG } FallBack "Diffuse" }
5.会发现绿色球显示在红色球前面,本来红色球会把绿色球挡住,但是我们修改了绿球渲染队列的值,又关闭了深度测试,使得绿色球先绘制,所以绿球显示在红色球前面。