Unity内置Shader解读8——Particles/Additive

1.Shader在什么情况下使用

Particles/Additive(粒子/叠加)到了粒子系列了,之所以先写前面几篇是因为本shader中都用到了,篇幅有限,因此分了几篇来写。本文注释中有关INSTANCE_ID和软粒子的深度计算方法都没有搞明白,不懂的部分只能后面再深入研究了不能阻挡学习的脚步。

2.Shader的价值(用的多不多),Shader的难度

Additive应该是用的非常多的,难度非常大,毕竟有些细节我还没搞明白。

3.代码详细注释

// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)

Shader "Legacy Shaders/Particles/Additive" {
    Properties {
        _TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5)//明调颜色
        _MainTex ("Particle Texture", 2D) = "white" {}//贴图
        _InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0//软粒子因子
    }

    Category {
        Tags { 
            "Queue"="Transparent" //申明渲染队列为透明(3000)
            "IgnoreProjector"="True"//忽略所有阴影
            "RenderType"="Transparent" //声明为透明物体
            "PreviewType"="Plane" //指示材质检视面板预览应如何显示材质。默认情况下,材质显示为球体,但也可以将 PreviewType 设置为“Plane”(将显示为 2D)或“Skybox”(将显示为天空盒)
        }
        // Blend SrcAlpha One//透明混合模式
        // ColorMask指定渲染结果的输出通道,而不是通常的 RGBA 四个通道都被写入
        // ColorMask RGB,RBA等,意思是输出颜色中RGB,RBA通道会被写入
        // ColorMask R,意思是输出颜色中只有R通道会被写入
        // ColorMask 0,意思是不会输出任何颜色
        // 默认值为RGBA,即四个通道都写入
        ColorMask RGB

        // //双面显示,关闭裁剪
        // Cull Off 
        // //关闭灯光影响
        // Lighting Off 
        // //关闭深度写入
        // ZWrite Off

        SubShader {
            Pass {

                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma target 2.0
                //使用您定义的一组关键字来编译多个实例。查看已编译的着色器,multi_compile_particles添加了SOFTPARTICLES_ON和SOFTPARTICLES_OFF,因此,这只是Unity自己的粒子关键字风格,包含该关键字。此外,您可以在质量设置中切换关键字。
                //简单说所有multi_compile开头的都是声明宏定义
                //之后就可以用#if xxxx #endif了
                //或者使用官方定义的宏定义如下,可以自动生成一些宏定义
                // #pragma multi_compile_particles表示允许使用官方的软阴影粒子SOFTPARTICLES_ON/SOFTPARTICLES_OFF的宏定义开关
                #pragma multi_compile_particles
                //雾效宏定义,不了解可以看雾效篇
                #pragma multi_compile_fog

                #include "UnityCG.cginc"

                sampler2D _MainTex;
                fixed4 _TintColor;

                struct appdata_t {
                    float4 vertex : POSITION;
                    fixed4 color : COLOR;
                    float2 texcoord : TEXCOORD0;
                    //在“顶点着色器输入/输出”结构中定义一个语义为SV_InstanceID的元素。一些要更改的属性,则可以根据ID进行更改,而无需为MaterialPropertyBlock设置其他属性。
                    //在UnityInstancing.cginc文件中可找到UNITY_VERTEX_INPUT_INSTANCE_ID的定义
                    //#define UNITY_VERTEX_INPUT_INSTANCE_ID uint instanceID : SV_InstanceID;
                    //通常用在GPU Instancing和VR中
                    //在VR中他们将实例ID和眼睛索引传递给片段着色器。这使您可以访问片段着色器中的实例化属性,以及进行可能需要的每眼唯一工作。例如,如果您使用任何视图矩阵或投影矩阵或片段着色器中的相机位置,则这些都需要眼图索引以提供正确的值,否则,您将始终访问左眼。
                    //这部分网上资料太少-。-搜不到,暂时不理解,就先这样吧
                    UNITY_VERTEX_INPUT_INSTANCE_ID
                };

                struct v2f {
                    float4 vertex : SV_POSITION;
                    fixed4 color : COLOR;
                    float2 texcoord : TEXCOORD0;
                    ////雾效,不了解可以看雾效篇
                    UNITY_FOG_COORDS(1)
                    //如果启用软粒子
                    #ifdef SOFTPARTICLES_ON
                        float4 projPos : TEXCOORD2;
                    #endif
                    UNITY_VERTEX_OUTPUT_STEREO
                };

                float4 _MainTex_ST;

                v2f vert (appdata_t v)
                {
                    v2f o;
                    //同UNITY_VERTEX_INPUT_INSTANCE_ID
                    //需要写在vert shader的最前面
                    UNITY_SETUP_INSTANCE_ID(v);
                    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
                    //取裁剪空间顶点位置
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    //如果软粒子系统打开,需要#pragma multi_compile_particles
                    //开关在质量设置里
                    #ifdef SOFTPARTICLES_ON
                        //ComputeScreenPos传入裁剪空间顶点坐标变换到齐次坐标系下的坐标
                        //齐次坐标就是将笛卡尔坐标转成矩阵,便于变换操作
                        o.projPos = ComputeScreenPos (o.vertex);
                        //计算顶点摄像机空间的深度:距离裁剪平面的距离,线性变化;
                        //在顶点着色器中取出深度信息储存到projPos,在片段着色器中使用
                        COMPUTE_EYEDEPTH(o.projPos.z);
                    #endif
                    //获取mesh顶点色
                    //一般情况下顶点色都是没有使用的默认为白色
                    o.color = v.color;
                    //将模型顶点的uv和Tiling、Offset两个变量进行运算,计算出实际显示用的顶点uv
                    //如果不需要Tiling、Offset可以移除
                    o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);
                    //雾效,不了解可以看雾效篇
                    UNITY_TRANSFER_FOG(o,o.vertex);
                    return o;
                }

                UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
                float _InvFade;

                fixed4 frag (v2f i) : SV_Target
                {

                    #ifdef SOFTPARTICLES_ON
                        //获得当前片元显示的深度
                        //LinearEyeDepth 负责把深度纹理的采样结果转换到视角空间下的深度值
                        float sceneZ = LinearEyeDepth (SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)));
                        //顶点计算出来的深度
                        float partZ = i.projPos.z;
                        //saturate将值限制到0-1
                        //使用混合度_InvFade乘以两个深度的差
                        //有关这两个深度查到的信息不多,暂时也搞不明白,先搁这后面明白了再更
                        float fade = saturate (_InvFade * (sceneZ-partZ));
                        //混合度影响一下透明度
                        i.color.a *= fade;
                    #endif

                    //最终颜色混合
                    // alpha should not have double-brightness applied to it, but we can't fix that legacy behavior without breaking everyone's effects, so instead clamp the output to get sensible HDR behavior (case 967476)alpha不应该应用双倍的亮度,但是我们不能在不破坏每个人的效果的情况下修复遗留行为,所以取而代之的是钳制输出以获得合理的HDR行为(案例967476)
                    fixed4 col = 2.0f * i.color * _TintColor * tex2D(_MainTex, i.texcoord);
                    //限制透明度区间
                    col.a = saturate(col.a); 

                    //雾效混合,不了解可以看雾效篇
                    UNITY_APPLY_FOG_COLOR(i.fogCoord, col, fixed4(0,0,0,0)); // fog towards black due to our blend mode由于我们的混合模式雾向黑色
                    return col;
                }
                ENDCG
            }
        }
    }
}

4.Shader编写思路,用到的知识点

粒子其实主要就是显示原本的颜色并且提亮,本Shader涵盖了很多如适配性代码,其中软粒子主要是指粒子图像边缘混合时柔化,具体可以自行百度,其他的知识点参考本系列前面几篇。
Legacy Shaders下的Particles系列基本与本文98%相似,各个不同仅修改了混合方式,至于透明混合方式写法都比较简单,本文不再讨论,读者自行研究(本系列的主要目的是梳理官方shader了解各种语法用法知识点,而非实现具体逻辑及shader效果)。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,335评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,895评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,766评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,918评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,042评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,169评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,219评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,976评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,393评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,711评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,876评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,562评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,193评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,903评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,699评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,764评论 2 351

推荐阅读更多精彩内容