使用MaterialPropertyBlock來(lái)替換Material屬性操作

在unite2017國(guó)外技術(shù)專場(chǎng)中Arturo Nú?ez在他的shader性能與優(yōu)化專題中提到了一個(gè)這樣的優(yōu)化建議那就是使用材質(zhì)屬性塊呻拌,其原話是Use MaterialPropertyBlock
Is faster to set properties using a MaterialPropertyBlock rather than
material.SetFloat(); Material.SetColor();

官網(wǎng)文檔

因此我特意查找了下關(guān)于MaterialPropertyBlock的官方文檔梆暖,文檔是這樣說的拢肆,材質(zhì)屬性塊被用于Graphics.DrawMesh 和 Renderer.SetPropertyBlock兩個(gè)API援制,當(dāng)我們想要繪制許多相同材質(zhì)但不同屬性的對(duì)象時(shí)可以使用它迄本。例如你想改變每個(gè)繪制網(wǎng)格的顏色爷辙,但是它卻不會(huì)改變渲染器的狀態(tài)

我們來(lái)看看Renderer這個(gè)類聘萨,它包含了material竹椒,sharedMaterial這兩個(gè)屬性;GetPropertyBlock米辐,SetPropertyBlock兩個(gè)函數(shù)胸完,其中兩個(gè)屬性是用來(lái)訪問和改變材質(zhì)的书释,而兩個(gè)函數(shù)是用來(lái)設(shè)置和獲取材質(zhì)屬性塊的,我們知道赊窥,當(dāng)我們操作材質(zhì)共性時(shí)爆惧,可以使用sharedMaterial屬性,改變這個(gè)屬性锨能,那么所有使用此材質(zhì)的物件都將會(huì)改變扯再,而我們需要改變單一材質(zhì)時(shí),需要使用material屬性址遇,而在第一次使用material時(shí)其實(shí)是會(huì)生成一份材質(zhì)拷貝的熄阻,即material(Instance)

實(shí)驗(yàn)

首先聲明兩個(gè)數(shù)組,一個(gè)用來(lái)保存用于操作材質(zhì)倔约,另一個(gè)用來(lái)保存操作材質(zhì)屬性塊

GameObject[] listObj = null;
GameObject[] listProp = null;

再次聲明一個(gè)公共變量秃殉,用來(lái)控制數(shù)組長(zhǎng)度,以及一個(gè)材質(zhì)屬性塊

public int objCount = 100;
MaterialPropertyBlock prop = null;

然后在Start函數(shù)中做初始化工作浸剩,我們?cè)谄聊蛔髠?cè)空間生成objCount個(gè)球體Sphere用來(lái)處理材質(zhì)材質(zhì)钾军,在屏幕右側(cè)空間生成objCount個(gè)球體Sphere用來(lái)處理材質(zhì)屬性塊

void Start () {
        colorID = Shader.PropertyToID("_Color");
        prop = new MaterialPropertyBlock();
        var obj = Resources.Load("Perfabs/Sphere") as GameObject;
        listObj = new GameObject[objCount];
        listProp = new GameObject[objCount];
        for (int i = 0; i < objCount; ++i)
        {
            int x = Random.Range(-6,-2);
            int y = Random.Range(-4, 4);
            int z = Random.Range(-4, 4);
            GameObject o = Instantiate(obj);
            o.name = i.ToString();
            o.transform.localPosition = new Vector3(x,y,z);
            listObj[i] = o;
        }
        for (int i = 0; i < objCount; ++i)
        {
            int x = Random.Range(2, 6);
            int y = Random.Range(-4, 4);
            int z = Random.Range(-4, 4);
            GameObject o = Instantiate(obj);
            o.name = (objCount + i).ToString();
            o.transform.localPosition = new Vector3(x, y, z);
            listProp[i] = o;
        }
    }

然后我們?cè)赨pdate函數(shù)中響應(yīng)我們的操作,這里我使用按鍵上下健位來(lái)操作

void Update () {
        if (Input.GetKeyDown(KeyCode.DownArrow))
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            for (int i = 0; i < objCount; ++i)
            {
                float r = Random.Range(0, 1f);
                float g = Random.Range(0, 1f);
                float b = Random.Range(0, 1f);
                listObj[i].GetComponent<Renderer>().material.SetColor("_Color", new Color(r, g, b, 1));
            }
            sw.Stop();     
            UnityEngine.Debug.Log(string.Format("material total: {0:F4} ms", (float)sw.ElapsedTicks *1000 / Stopwatch.Frequency));
        }
        if (Input.GetKeyDown(KeyCode.UpArrow))
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            for (int i = 0; i < objCount; ++i)
            {
                float r = Random.Range(0, 1f);
                float g = Random.Range(0, 1f);
                float b = Random.Range(0, 1f);
                listProp[i].GetComponent<Renderer>().GetPropertyBlock(prop);
                prop.SetColor(colorID, new Color(r, g, b, 1));
                listProp[i].GetComponent<Renderer>().SetPropertyBlock(prop);             
            }
            sw.Stop();
            UnityEngine.Debug.Log(string.Format("MaterialPropertyBlock total: {0:F4} ms", (float)sw.ElapsedTicks * 1000 / Stopwatch.Frequency));
        }
    }

結(jié)論

然后我們?cè)賮?lái)看一下對(duì)比數(shù)據(jù)


table.png

從結(jié)果對(duì)比來(lái)看乒省,確實(shí)使用材質(zhì)屬性塊要快于使用材質(zhì)巧颈,其消耗將近是操作材質(zhì)耗時(shí)的四分之一。同時(shí)不管是材質(zhì)還是材質(zhì)屬性塊袖扛,第一次操作比后面的操作耗時(shí)要大砸泛,尤其是材質(zhì),可見在第一次使用材質(zhì)改變屬性操作時(shí)蛆封,其拷貝操作消耗還是非常大的唇礁。同時(shí)我也通過profiler的memory模塊,切換進(jìn)Detailed選項(xiàng)惨篱,對(duì)其進(jìn)行采樣盏筐,可以發(fā)現(xiàn)在Sence Memory下面會(huì)有material的拷貝(材質(zhì)操作導(dǎo)致,而材質(zhì)屬性操作不會(huì))

游戲中處理

正如官方文檔介紹材質(zhì)屬性塊一樣砸讳,unity地型引擎正是使用材質(zhì)屬性塊來(lái)繪制樹的琢融,所有的樹使用的是相同的材質(zhì),但是每棵樹有不同的顏色簿寂,縮放和風(fēng)因子漾抬。對(duì)于大場(chǎng)景大世界來(lái)說,我們肯定是采取動(dòng)態(tài)加載來(lái)處理地圖的常遂,這個(gè)時(shí)候我們可以配合Gpu Instance來(lái)進(jìn)一步的提高性能纳令,使用Gpu Instance一是可以省去實(shí)體對(duì)象本身的開銷,二是能夠起到減少Drawcall的作用,同時(shí)還能減少動(dòng)態(tài)合批的cpu開銷平绩,靜態(tài)合批的內(nèi)存開銷圈匆;可謂一舉多得,遺憾的只能在ES3.0以上的設(shè)備上使用捏雌。對(duì)于一些游戲中存在自定義皮膚顏色玩法的跃赚,材質(zhì)屬性塊的優(yōu)勢(shì)就可以發(fā)揮出來(lái)了,你想當(dāng)你100個(gè)不同玩家同屏?xí)r腹忽,如果使用材質(zhì)操作顏色屬性的話来累,那么首先就存在100份材質(zhì)拷貝的實(shí)例,其次窘奏,材質(zhì)操作屬性本身就比材質(zhì)屬性塊操作要慢那么點(diǎn)嘹锁,在性能優(yōu)化中一毫秒的優(yōu)化就是勝利,這了一毫秒那里一毫秒加起來(lái)就不得了了着裹。

最后

這里給出下載地址
Arturo Nú?ez 的shader性能與優(yōu)化的工程下載地址
本次測(cè)試工程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末领猾,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子骇扇,更是在濱河造成了極大的恐慌摔竿,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件少孝,死亡現(xiàn)場(chǎng)離奇詭異继低,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)稍走,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門袁翁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人婿脸,你說我怎么就攤上這事粱胜。” “怎么了狐树?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵焙压,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我抑钟,道長(zhǎng)涯曲,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任在塔,我火速辦了婚禮幻件,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘心俗。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布城榛。 她就那樣靜靜地躺著揪利,像睡著了一般。 火紅的嫁衣襯著肌膚如雪狠持。 梳的紋絲不亂的頭發(fā)上疟位,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天,我揣著相機(jī)與錄音喘垂,去河邊找鬼甜刻。 笑死,一個(gè)胖子當(dāng)著我的面吹牛正勒,可吹牛的內(nèi)容都是我干的得院。 我是一名探鬼主播,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼章贞,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼祥绞!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起鸭限,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蜕径,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后败京,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體兜喻,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年赡麦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了朴皆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡隧甚,死狀恐怖车荔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情戚扳,我是刑警寧澤忧便,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站帽借,受9級(jí)特大地震影響珠增,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜砍艾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一蒂教、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧脆荷,春花似錦凝垛、人聲如沸懊悯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)炭分。三九已至,卻和暖如春剑肯,著一層夾襖步出監(jiān)牢的瞬間捧毛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工让网, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留呀忧,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓溃睹,卻偏偏與公主長(zhǎng)得像而账,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子丸凭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

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