资源大湿 发表于 2018-8-21 17:18

关于unity shaderlab 中LOD详细度、渲染队列RenderType、混合模式、alpha测试等jie...

每个shader里面有很多的subshader,如果所以的subshader都不执行的话就,就执行fallback。每个subshader都可以设置一个LOD,整个shader也有一个LOD。系统就去找第一个LOD小于等于shader的LOD的subshader执行,其他的subshader就不会被执行。
LOD1、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,重命名LODShader4.打开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---->LODShader7.立方体变红8.创建一个脚本LOD_ctrl来控制LOD9.打开LOD_ctrlusing 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,重命名RenderQueue3: 使后面的绿球使用这个RenderQueue的shader模式4.打开RenderQueueShader "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.会发现绿色球显示在红色球前面,本来红色球会把绿色球挡住,但是我们修改了绿球渲染队列的值,又关闭了深度测试,使得绿色球先绘制,所以绿球显示在红色球前面。


混合模式着色完成后,需要把颜色混合到帧缓冲区里面,涉及到源和目标。1:在所有计算完成后,决定当前的计算结果输出到帧缓冲区时,如何混合源和目标,通常用来绘制半透明的物体;
2: Blend Off 关闭混合
3: Blend 源因子,目标因子: 配置并开启混合,产生的颜色和因子相乘,然后两个颜色相加
4: Blend 源因子,目标因子, 源因子A,目标因子A: 源因子与目标因子用户混合颜色值,源因子A,与目标因子A,用于混合alpha
5: BlendOp操作命令: 不是将颜色混合在一起,而是对他们进行操作,主要有:
Min, Max, Sub, RevSub
6:混合因子的类型:
One 使用源或目标色完全显示出来; OneMinusSrcColor 阶段值 * (1-源颜色的值)
Zero 删除源颜色或目标颜色; OneMinusSrcAlpha 阶段值 * (1-源颜色的Alpha值)
SrcColor 这个阶段的值*源颜色值; OneMinusDstColor 阶段值 * (1-目标颜色的值);
DstColor 这个阶段的值* 帧缓冲颜色值; OneMinusDstAlha 阶段值 * (1-目标颜色Alpha值)
DstAlpha这个阶段的值 * 帧缓冲源Alpha值 SrcAlpha这个阶段的值 * 源颜色Alpha值
6:一般放在放在Pass通道里面,不能放在cgprogram的begin和end里面

Alpha测试1:Alpha测试: 阻止片元被写到屏幕的最后机会, 最终渲染出来的颜色计算出来后可通过透明度和最后一个固定值比较,如果通过测试则绘制次片元,否则丢弃此片元;
2: AlphaTest Off/On: 开启/关闭Alpha测试,默认是关闭的;
3:比较测试值的模式:
Greater >, GEqual >=, Less <, LEqual <=, Equal ==, NotEqual !=,
Always (永远渲染), Never(从不渲染);
4: AlphaTest 条件 [变量] / 常数, 一般放在放在Pass通道里面;

深度测试1:为了使近距离的物体挡住远距离的物体,当片元写入到缓冲的时候,需要将片元的深度值与缓冲区的深度值进行比较,测试成功写入帧缓冲区;
2: ZWrite 深度写开关, 控制是否将深度Z的片元写入缓冲区中,如果不绘制透明物体设置为On, 否则的话设置为Off,默认为On;
3: ZTest 深度测试模式: 设置深度测试的执行方式,默认为LEqual,深度测试的模式:
Less <, Greater >, LEqual <= , GEqual >=, Equal ==, NotEqual !=, Always 总是绘制,关闭深度测试;
4: ZTest 条件
5: 一般放在放在Pass通道里面;

通道遮罩1:通道遮罩可以是开发人员指定渲染结果输出的通道,而不是通常情况下的RGBA四个通道;
2:可选的是RGBA的任意组合以及0,如果为0意味着不会写入到任何通道;
3: ColorMask RG ... ColorMask 0

面剔除1:通过不渲染背对摄像机的几何体的面来提高性能优化错误,所有的几何体都包含正面和反面
2: 面剔除操作,大多数都是封闭的物体,所以不需要绘制背面;
3: 面剔除操作:
Cull Back: 不绘制背对摄像机的面,默认项
Cull Front, 不绘制面向摄像机的面,
Cull Off, 关闭面剔除操作

混合模式案例1.创建Unity工程目录2.在resources文件夹下面创建shaders文件夹3.打开shaders文件夹,创建一个用于顶点片元着色的shader,create---->shader---->unlit shader,重命名为BlendShader4.打开BlendShader第一步:先把第一行改成Shader "Custom/BlendShader",这样才能在编辑器里面显示这个shader第二步:Shader "Custom/BlendShader"
{
    Properties
    {
      _MainTex ("Texture", 2D) = "white" {}
      _Color ("Color", Color) = (1.0, 0.0, 0.0, 1.0)
    }
    SubShader
    {
      Tags { "RenderType"="Opaque" "Queue"="Transparent+10" }//设置渲染通道为透明,这样就可以看见后面的物体了
      LOD 100
      

      Pass
      {
            Blend SrcAlpha OneMinusSrcAlpha//设置混合模式,SrcAlpha是源因子,OneMinusSrcAlpha是目标因子,产生的各个颜色和各个因子相乘,然后两个颜色相加

            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            fixed4 _Color;
            struct appdata
            float _Alpha;

            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                // fixed4 col = tex2D(_MainTex, i.uv);
                fixed4 col = _Color;
                return col;
            }
            ENDCG      
      }
    }
}5.创建一个sphere,创建一个cube,拉伸cube,变成一个大饼挡住sphere6.创建一个材质BlendShader,设置它的shader为custom/BlendShader7.修改材质球颜色为红色,拉透明度条到一半,透明度条在color里面的最后一栏,把材质球拖进cube8.发现颜色变透明且可以看见后面的白球sphere
通道遮罩案例1.在shaders里面创建一个create---->shader---->standard surface shader,重命名ColorMaskShader2.创建一个材质ColorMask,设置它的shader为custom/ColorMaskShader3.创建一个cube,把材质球ColorMask拖进cube4.打开ColorMaskShaderShader "Custom/ColorMaskShader" {

    SubShader {
      pass {
            ColorMask R//最多RGBA,这里只显示红色
            Color(1.0, 1.0, 1.0, 1.0)
      }
    }
    FallBack "Diffuse"
}5.发现为ColorMask R的时候,cube只显示红色,ColorMask G的时候,cube只显示绿色,ColorMask B的时候,cube只显示蓝色。ColorMask RGBA的时候,cube显示白色。

甲子 发表于 2018-9-17 10:03

很不错

甲子 发表于 2018-9-17 09:46

真心顶

pengtaida 发表于 2018-9-17 09:44

难得一见的好帖

sx142601 发表于 2018-9-17 10:00

说的非常好

sx142601 发表于 2018-9-17 10:25

不错不错

fulaobao 发表于 2019-3-10 08:43

很不错

13421805085 发表于 2019-3-10 09:00

楼主是超人

kaojian1989 发表于 2019-3-10 09:12

顶顶多好

CloudySkyRiver 发表于 2019-3-10 08:44

说的非常好
页: [1] 2
查看完整版本: 关于unity shaderlab 中LOD详细度、渲染队列RenderType、混合模式、alpha测试等jie...