一篇雨滴效果實(shí)現(xiàn)的學(xué)習(xí)筆記

前兩天看到一篇關(guān)于雨滴效果制作的文章,學(xué)習(xí)實(shí)踐了一下递胧。這里貼一下涉及到的知識點(diǎn)碑韵。

1.CommandBuffer

用來存儲一系列渲染指令,可以通過Camera(Camera.AddCommandBuffer)
,Light( Light.AddCommandBuffer
)及Graphics(Graphics.ExecuteCommandBuffer
)來調(diào)用執(zhí)行缎脾。

2.ComputeShader

ComputeShader運(yùn)行在GPU上祝闻,可以執(zhí)行大量并行算法,或者用來加速游戲渲染遗菠。為了更高效的使用Compute Shader治筒,需要額外了解GPU的架構(gòu)及常見并行算法。
使用ComputerShader之前需要先使用SystemInfo.supportsComputeShaders測試可用性舷蒲。下面是基本的ComputeShader格式

// test.compute
// 一個(gè)Compute Shader必須至少有一個(gè) kernel耸袜, #pragma kernel后可添加額外的宏,如OTHER_DEFINE
#pragma kernel FillWithRed OTHER_DEFINE

RWTexture2D<float4> res;

[numthreads(100,1,1)]
void FillWithRed (uint3 dtid : SV_DispatchThreadID)
{
    res[dtid.xy] = float4(1,0,0,1);
}

之后可以通過 ComputeShader.Dispatch來執(zhí)行shader牲平。方式如下:

ComputeShader shader;
int kernal = shader.FindKernel("CSMain");

shader.Dispatch(kernal, 100, 1, 1);

3. ComputeBuffer

GPU數(shù)據(jù)緩存堤框,通常是在ComputeShader中使用,可以填充數(shù)據(jù)纵柿,也可以獲取數(shù)據(jù)蜈抓。
在HLSL格式里,使用StructuredBuffer<T>或者 RWStructuredBuffer<T>來聲明ComputeBuffer昂儒。

4. GPU Instance

GPU Instance是一種將相同Mesh的多個(gè)拷貝在少量的draw call中完成繪制的技術(shù)沟使。經(jīng)常在繪制建筑,樹木渊跋,草木或者其他一些在場景中重復(fù)出現(xiàn)的物件中使用腊嗡。可以明顯的提升渲染性能拾酝。
GPU Instance在每個(gè)draw call中繪制的必須是完全相同的mesh,但是每個(gè)mesh可以擁有不同的參數(shù)(形如顏色燕少,縮放值)。
為了使用GPU Instance蒿囤,需要開啟材質(zhì)的 Enable Instancing選項(xiàng)客们。


Enable Instancing

除了以上方式,也可以在腳本中調(diào)用Graphics.DrawMeshInstanced 或者 Graphics.DrawMeshInstancedIndirect執(zhí)行GPU Instance材诽。

通常底挫,Unity只會對僅有Transform變化的GameObject做批處理,為了為每個(gè)實(shí)例添加更多的變體脸侥,需要在Shader中添加per-instance 屬性建邓,示例如下:

Shader "SimplestInstancedShader"
{
    Properties
    {
        _Color ("Color", Color) = (1, 1, 1, 1)
    }

    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_instancing
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                UNITY_VERTEX_INPUT_INSTANCE_ID // necessary only if you want to access instanced properties in __fragment Shader__.
            };

            //聲明實(shí)例屬性_Color
            UNITY_INSTANCING_BUFFER_START(Props)
                UNITY_DEFINE_INSTANCED_PROP(float4, _Color)
            UNITY_INSTANCING_BUFFER_END(Props)
           
            v2f vert(appdata v)
            {
                v2f o;

                UNITY_SETUP_INSTANCE_ID(v);
                UNITY_TRANSFER_INSTANCE_ID(v, o); // necessary only if you want to access instanced properties in the fragment Shader.

                o.vertex = UnityObjectToClipPos(v.vertex);
                return o;
            }
           
            fixed4 frag(v2f i) : SV_Target
            {
                UNITY_SETUP_INSTANCE_ID(i); // necessary only if any instanced properties are going to be accessed in the fragment Shader.
                return UNITY_ACCESS_INSTANCED_PROP(Props, _Color);
            }
            ENDCG
        }
    }
}

上面聲明了_Color屬性,Unity會從MaterialPropertyBlock中采集_Color屬性湿痢,設(shè)置到GameObject的Shader中涝缝,并將GameObject合并在一個(gè)DrawCall中

MaterialPropertyBlock props = new MaterialPropertyBlock();
MeshRenderer renderer;

foreach (GameObject obj in objects)
{
   float r = Random.Range(0.0f, 1.0f);
   float g = Random.Range(0.0f, 1.0f);
   float b = Random.Range(0.0f, 1.0f);
   props.SetColor("_Color", new Color(r, g, b));
   
   renderer = obj.GetComponent<MeshRenderer>();
   renderer.SetPropertyBlock(props);
}

一些高級Tips
1.當(dāng)Unity進(jìn)行batch的時(shí)候,Static batching
優(yōu)先級要比instancing高譬重,也就是說拒逮,如果將某個(gè)GameObject設(shè)置為static batching,Unity 會禁掉instancing,即使使用了instancing的shader,但是會完成static batching。這時(shí)臀规,Inspector窗口會顯示警告提示關(guān)閉static batch滩援。
GPU Instancing的優(yōu)先級會比dynamic batching高,當(dāng)執(zhí)行instancing的時(shí)候塔嬉,dynamic batching會被禁用玩徊。
2.某些情況如材質(zhì)改變或者深度排序會導(dǎo)致阻止Unity進(jìn)行自動的instancing,這是可以調(diào)用Graphics.DrawMeshInstanced
強(qiáng)制執(zhí)行GPU instancing谨究。
3.從Unity2018.1開始恩袱,Unity支持GI 渲染時(shí),在GPU Instancing使用光照探針及occlusion探針胶哲∨纤可以在MaterialPropertyBlock中提供 light probe 及 occlusion probe數(shù)據(jù)(LightProbeUsage
參數(shù)中設(shè)置).
4.使用UnityObjectToClipPos(v.vertex) 而不是 mul(UNITY_MATRIX_MVP,v.vertex),前者更高效鸯屿。

其他需要注意的地方:
1.SurfaceShader默認(rèn)會生成示例變量澈吨,但是可以用#pragma noinstancing禁止這一行為。
2.Graphics.DrawMeshInstanced需要在材質(zhì)設(shè)置中開啟GPU Instancing設(shè)定寄摆,但是Graphics.DrawMeshInstancedIndirect不需要谅辣。
3.instanced draw call在Frame Debugger中以 Draw Mesh (instanced)形式出現(xiàn)。
4.在前向渲染的時(shí)候婶恼,只有base pass會執(zhí)行instancing桑阶,add pass不會
5.如果有兩個(gè)以上的pass,只有第一個(gè)pass會被instanced勾邦,因?yàn)楹竺娴膒ass需要強(qiáng)制在一起渲染联逻,這個(gè)操作會是材質(zhì)發(fā)生變化.

5.Draw call batching

Dynamic batching:通常用于特別小的mesh,在cpu層面做頂點(diǎn)變換检痰,之后將相似的頂點(diǎn)合批在一個(gè)draw call中繪制包归。會耗費(fèi)大量cpu時(shí)間。
Static batching: 將靜態(tài)的GameObject合并成一個(gè)大的mesh铅歼,從而提高渲染的速度公壤。缺點(diǎn)是會耗費(fèi)大量內(nèi)存和硬盤空間。

只有使用相同的材質(zhì)的GameObjects才會被合批處理椎椰。
1.如果除了紋理厦幅,兩個(gè)材質(zhì)完全相同,可以將兩個(gè)紋理合在一張大的紋理中慨飘。
2.Renderer.material會創(chuàng)建一份材質(zhì)的拷貝确憨,而不是共享译荞。需要調(diào)用Renderer.sharedMaterial共享材質(zhì)
3.Shadow casters在材質(zhì)不同的情況下也會被合批處理,只要供Shadow casters使用的材質(zhì)參數(shù)一樣即可休弃。

4.一次動態(tài)合批不能超過900個(gè)頂點(diǎn)屬性吞歼,不能超過300個(gè)頂點(diǎn)。
5.鏡面GameObject(scale = -1)不能被合批
6.除了Shadow casters外塔猾,使用不同material的實(shí)例的對象不能被合批
7.動態(tài)合批需要將頂點(diǎn)全部轉(zhuǎn)化為世界坐標(biāo)篙骡,所以只有當(dāng)這項(xiàng)消耗低于合批的時(shí)候才值得做動態(tài)合批。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末丈甸,一起剝皮案震驚了整個(gè)濱河市糯俗,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌睦擂,老刑警劉巖得湘,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異顿仇,居然都是意外死亡忽刽,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進(jìn)店門夺欲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來跪帝,“玉大人,你說我怎么就攤上這事些阅∩〗#” “怎么了?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵市埋,是天一觀的道長黎泣。 經(jīng)常有香客問我,道長缤谎,這世上最難降的妖魔是什么抒倚? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮坷澡,結(jié)果婚禮上托呕,老公的妹妹穿的比我還像新娘。我一直安慰自己频敛,他們只是感情好项郊,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著斟赚,像睡著了一般着降。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上拗军,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天任洞,我揣著相機(jī)與錄音蓄喇,去河邊找鬼。 笑死交掏,一個(gè)胖子當(dāng)著我的面吹牛妆偏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播耀销,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼铲汪!你這毒婦竟也來了熊尉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤掌腰,失蹤者是張志新(化名)和其女友劉穎狰住,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體齿梁,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡催植,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了勺择。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片创南。...
    茶點(diǎn)故事閱讀 39,919評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖省核,靈堂內(nèi)的尸體忽然破棺而出稿辙,到底是詐尸還是另有隱情,我是刑警寧澤气忠,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布邻储,位于F島的核電站,受9級特大地震影響旧噪,放射性物質(zhì)發(fā)生泄漏吨娜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一淘钟、第九天 我趴在偏房一處隱蔽的房頂上張望宦赠。 院中可真熱鬧,春花似錦米母、人聲如沸袱瓮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽尺借。三九已至,卻和暖如春精拟,著一層夾襖步出監(jiān)牢的瞬間燎斩,已是汗流浹背虱歪。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留栅表,地道東北人笋鄙。 一個(gè)月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像怪瓶,于是被迫代替她去往敵國和親萧落。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內(nèi)容