每个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.会发现绿色球显示在红色球前面,本来红色球会把绿色球挡住,但是我们修改了绿球渲染队列的值,又关闭了深度测试,使得绿色球先绘制,所以绿球显示在红色球前面。
混合模式 着色完成后,需要把颜色混合到帧缓冲区里面,涉及到源和目标。 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 第二步: - 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,变成一个大饼挡住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 - Shader "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显示白色。
|