找回密码
 立即注册
查看: 2292|回复: 21

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

[复制链接]
发表于 2018-8-21 17:18 | 显示全部楼层 |阅读模式
资源信息 Tutorial Information
教程名称: 关于unity shaderlab 中LOD详细度、渲染队列RenderType、混合模式、alpha测试等(发帖教程)
适用引擎: Unity3D  (适用引擎,为空默认为Unity)
教程语种: 中文
教程等级: 1
教程格式: 图文(请用IE9以上浏览器访问本版块)
教程作者: 转载自互联网 (如有问题请短消息联系作者或发表回复)
下载地址: (兑换积分)
点击查看原图
美丽分割线
每个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:
  1. Shader "Custom/LODShader" {
  2.     Properties {
  3.         _Color ("Color", Color) = (1,1,1,1)
  4.         _MainTex ("Albedo (RGB)", 2D) = "white" {}
  5.         _Glossiness ("Smoothness", Range(0,1)) = 0.5
  6.         _Metallic ("Metallic", Range(0,1)) = 0.0
  7.     }
  8.     // 每次只会根据情况来选择一个可执行的SubShader
  9.     // 找到第一个<= Shader.maximumLOD 这个subShader执行;
  10.     SubShader {
  11.         Tags { "RenderType"="Opaque" }
  12.         LOD 600 // LOD-----------------这里设置为600
  13.         
  14.         CGPROGRAM
  15.         // Physically based Standard lighting model, and enable shadows on all light types
  16.         #pragma surface surf Standard fullforwardshadows

  17.         // Use shader model 3.0 target, to get nicer looking lighting
  18.         #pragma target 3.0

  19.         sampler2D _MainTex;

  20.         struct Input {
  21.             float2 uv_MainTex;
  22.         };

  23.         half _Glossiness;
  24.         half _Metallic;
  25.         fixed4 _Color;

  26.         void surf (Input IN, inout SurfaceOutputStandard o) {
  27.             o.Albedo = fixed3(1.0, 0.0, 0.0);
  28.         }
  29.         ENDCG
  30.     }
  31.     SubShader {
  32.         Tags { "RenderType"="Opaque" }
  33.         LOD 500 // LOD-----------------这里设置为500
  34.         
  35.         CGPROGRAM
  36.         // Physically based Standard lighting model, and enable shadows on all light types
  37.         #pragma surface surf Standard fullforwardshadows

  38.         // Use shader model 3.0 target, to get nicer looking lighting
  39.         #pragma target 3.0

  40.         sampler2D _MainTex;

  41.         struct Input {
  42.             float2 uv_MainTex;
  43.         };

  44.         half _Glossiness;
  45.         half _Metallic;
  46.         fixed4 _Color;

  47.         void surf (Input IN, inout SurfaceOutputStandard o) {
  48.             o.Albedo = fixed3(0.0, 1.0, 0.0);
  49.         }
  50.         ENDCG
  51.     }
  52.     SubShader {
  53.         Tags { "RenderType"="Opaque" }
  54.         LOD 400 // LOD-----------------这里设置为400
  55.         
  56.         CGPROGRAM
  57.         // Physically based Standard lighting model, and enable shadows on all light types
  58.         #pragma surface surf Standard fullforwardshadows

  59.         // Use shader model 3.0 target, to get nicer looking lighting
  60.         #pragma target 3.0

  61.         sampler2D _MainTex;

  62.         struct Input {
  63.             float2 uv_MainTex;
  64.         };

  65.         half _Glossiness;
  66.         half _Metallic;
  67.         fixed4 _Color;

  68.         void surf (Input IN, inout SurfaceOutputStandard o) {
  69.             o.Albedo = fixed3(0.0, 0.0, 1.0);
  70.         }
  71.         ENDCG
  72.     }
  73.     FallBack "Diffuse"
  74. }
复制代码
5.创建一个cube立方体,创建一个材质球为LODShader,材质拖进cube材质属性
6.材质的shader选择custom---->LODShader
7.立方体变红
8.创建一个脚本LOD_ctrl来控制LOD
9.打开LOD_ctrl
  1. using UnityEngine;
  2. using System.Collections;

  3. public class LOD_ctrl : MonoBehaviour {
  4.     public Shader shader;//公开属性需要关联
  5.     public int LOD_value = 600;//外部来设置shader的LOD的值
  6.     // Use this for initialization
  7.     void Start () {
  8.         Debug.Log(this.shader.maximumLOD);
  9.     }
  10.    
  11.     // Update is called once per frame
  12.     void Update () {
  13.         // 当前这个shader最大的LOD_value;
  14.         this.shader.maximumLOD = this.LOD_value;//关联的节点可以直接使用和改变
  15.     }
  16. }
复制代码
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
  1. Shader "Custom/RenderQueue" {
  2.     Properties {
  3.         _Color ("Color", Color) = (1,1,1,1)
  4.         _MainTex ("Albedo (RGB)", 2D) = "white" {}
  5.         _Glossiness ("Smoothness", Range(0,1)) = 0.5
  6.         _Metallic ("Metallic", Range(0,1)) = 0.0
  7.     }
  8.     SubShader {
  9.         Tags { "RenderType"="Opaque" "Queue"="Geometry+100" }//设置渲染队列的值,+左右不能用空格,多个tag,不能用逗号;
  10.         LOD 200
  11.         ZTest off//关闭深度测试

  12.         CGPROGRAM
  13.         // Physically based Standard lighting model, and enable shadows on all light types
  14.         #pragma surface surf Standard fullforwardshadows

  15.         // Use shader model 3.0 target, to get nicer looking lighting
  16.         #pragma target 3.0

  17.         sampler2D _MainTex;

  18.         struct Input {
  19.             float2 uv_MainTex;
  20.         };

  21.         half _Glossiness;
  22.         half _Metallic;
  23.         fixed4 _Color;

  24.         void surf (Input IN, inout SurfaceOutputStandard o) {
  25.             // Albedo comes from a texture tinted by color
  26.             o.Albedo = _Color.rgb;
  27.             
  28.         }
  29.         ENDCG
  30.     }
  31.     FallBack "Diffuse"
  32. }
复制代码
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,重命名为BlendShader
4.打开BlendShader
第一步:先把第一行改成Shader "Custom/BlendShader",这样才能在编辑器里面显示这个shader
第二步:
  1. Shader "Custom/BlendShader"
  2. {
  3.     Properties
  4.     {
  5.         _MainTex ("Texture", 2D) = "white" {}
  6.         _Color ("Color", Color) = (1.0, 0.0, 0.0, 1.0)
  7.     }
  8.     SubShader
  9.     {
  10.         Tags { "RenderType"="Opaque" "Queue"="Transparent+10" }//设置渲染通道为透明,这样就可以看见后面的物体了
  11.         LOD 100
  12.         

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

  16.             #pragma vertex vert
  17.             #pragma fragment frag

  18.             #include "UnityCG.cginc"

  19.             fixed4 _Color;
  20.             struct appdata
  21.             float _Alpha;

  22.             {
  23.                 float4 vertex : POSITION;
  24.                 float2 uv : TEXCOORD0;
  25.             };

  26.             struct v2f
  27.             {
  28.                 float2 uv : TEXCOORD0;
  29.                 float4 vertex : SV_POSITION;
  30.             };

  31.             sampler2D _MainTex;
  32.             float4 _MainTex_ST;
  33.             
  34.             v2f vert (appdata v)
  35.             {
  36.                 v2f o;
  37.                 o.vertex = UnityObjectToClipPos(v.vertex);
  38.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
  39.                 return o;
  40.             }
  41.             
  42.             fixed4 frag (v2f i) : SV_Target
  43.             {
  44.                 // sample the texture
  45.                 // fixed4 col = tex2D(_MainTex, i.uv);
  46.                 fixed4 col = _Color;
  47.                 return col;
  48.             }
  49.             ENDCG        
  50.         }
  51.     }
  52. }
复制代码
5.创建一个sphere,创建一个cube,拉伸cube,变成一个大饼挡住sphere
6.创建一个材质BlendShader,设置它的shader为custom/BlendShader
7.修改材质球颜色为红色,拉透明度条到一半,透明度条在color里面的最后一栏,把材质球拖进cube
8.发现颜色变透明且可以看见后面的白球sphere

通道遮罩案例
1.在shaders里面创建一个create---->shader---->standard surface shader,重命名ColorMaskShader
2.创建一个材质ColorMask,设置它的shader为custom/ColorMaskShader
3.创建一个cube,把材质球ColorMask拖进cube
4.打开ColorMaskShader
  1. Shader "Custom/ColorMaskShader" {

  2.     SubShader {
  3.         pass {
  4.             ColorMask R//最多RGBA,这里只显示红色
  5.             Color(1.0, 1.0, 1.0, 1.0)
  6.         }
  7.     }
  8.     FallBack "Diffuse"
  9. }
复制代码
5.发现为ColorMask R的时候,cube只显示红色,ColorMask G的时候,cube只显示绿色,ColorMask B的时候,cube只显示蓝色。ColorMask RGBA的时候,cube显示白色。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
发表于 2018-9-17 10:03 | 显示全部楼层
很不错
发表于 2018-9-17 09:46 | 显示全部楼层
真心顶
发表于 2018-9-17 09:44 | 显示全部楼层
难得一见的好帖
发表于 2018-9-17 10:00 | 显示全部楼层
说的非常好
发表于 2018-9-17 10:25 | 显示全部楼层
不错不错
发表于 2019-3-10 08:43 | 显示全部楼层
很不错
发表于 2019-3-10 09:00 | 显示全部楼层
楼主是超人
发表于 2019-3-10 09:12 | 显示全部楼层
顶顶多好
发表于 2019-3-10 08:44 | 显示全部楼层
说的非常好
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-4-19 04:45 , Processed in 0.109948 second(s), 32 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表