日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

unity shader 变种(多重编译 multi_compile)

發(fā)布時(shí)間:2023/12/13 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 unity shader 变种(多重编译 multi_compile) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、定義

在unity中我們可以通過(guò)使用#pragma multi_compile或#pragma shader_feature指令來(lái)為shader創(chuàng)建多個(gè)稍微有點(diǎn)區(qū)別的shader變體。這個(gè)Shader被稱為宏著色器(mega shader)或者超著色器(uber shader)。實(shí)現(xiàn)原理:根據(jù)不同的情況,使用不同的預(yù)處理器指令,來(lái)多次編譯Shader代碼。
在運(yùn)行時(shí),Unity從Material宏Material.EnableKeyword和Shader.DisableKeyword或全局著色器宏Shader.EnableKeyword和Shader.DisableKeyword中選擇適當(dāng)?shù)闹髯凅w。如果這兩個(gè)宏都未啟用,則Unity使用第一個(gè)宏。

二、使用

//定義兩個(gè)TEST_1,TEST_2兩個(gè)宏 #pragma multi_compile TEST_1 TEST_2 //在shader中使用 #ifdef TEST_1//Todo #endif #ifdef TEST_2//Todo #endif

上面這個(gè)命令會(huì)產(chǎn)生2種著色器變種:TEST_1,TEST_2。
要生成未定義預(yù)處理器宏的著色器變體,請(qǐng)?zhí)砑右粋€(gè)僅為下劃線(__)的名稱。這是避免使用兩個(gè)宏的常用技術(shù),因?yàn)閷?duì)項(xiàng)目中可以使用的宏數(shù)量有限制,例如:

#pragma multi_compile __ TEST_1

在腳本中控制使用:

//使用TEST_1變種 Shader.EnableKeyword ("TEST_1"); Shader.DisableKeyword ("TEST_2");

三、組合

#pragma multi_compile TEST_1 TEST_2 #pragma multi_compile TEST_3 TEST_4 TEST_5

它產(chǎn)生總共六個(gè)著色器變體(TEST_1_TEST_3,TEST_1_TEST_4,TEST_1_TEST_5,TEST_2_TEST_3,TEST_2_TEST_4,TEST_2_TEST_5)。
所以如果有10行multi_compile,每行2個(gè)選項(xiàng),那么將一共產(chǎn)生1024個(gè)著色器變體。
請(qǐng)記住,著色器變體數(shù)量將以這種方式瘋狂增長(zhǎng)。

四、pragma shader_feature

shader_feature非常相似multi_compile。唯一的區(qū)別是Unity shader_feature在最終版本中不包含未使用的著色器變體。所以shader_feature適用于在我們?cè)诰庉嬈髦?#xff0c;選中材質(zhì),設(shè)置它使用的shader的宏,如果在程序中動(dòng)態(tài)的去設(shè)置可能無(wú)效(原因下面說(shuō)明)。而對(duì)于multi_compile,會(huì)把所有的變體都編譯進(jìn)程序里,所以適合需要在程序運(yùn)行中動(dòng)態(tài)改變狀態(tài)的宏,適合全局設(shè)置 。
材質(zhì)中設(shè)置位置截圖:

五、宏限制

在unity中限制了全局的宏個(gè)數(shù)為265個(gè),而unity內(nèi)部使用了大約60個(gè),所以在多個(gè)不同的著色器中定義全局宏時(shí)需要注意宏數(shù)量不要超過(guò)限制。
使用本地宏替代一部分全局宏:使用shader_feature_local和multi_compile_local。
shader_feature_local:類似于shader_feature,但枚舉宏是本地的。
multi_compile_local:類似于multi_compile,但枚舉宏是本地的。
在項(xiàng)目中除非是希望通過(guò)全局API啟用的那些特定宏,否則應(yīng)盡量使用本地宏,
使用更多本地宏和更少的全局宏,以減少每個(gè)著色器的宏總計(jì)數(shù)。如果存在具有相同名稱的全局和本地宏,則Unity會(huì)優(yōu)先使用local宏。
注意:
(1)不能將本地宏與進(jìn)行全局宏更改的API一起使用(例如Shader.EnableKeyword或CommandBuffer.EnableShaderKeyword)。
(2)每個(gè)著色器最多有64個(gè)唯一的本地宏。
(3)如果Material啟用了本地宏,并且其著色器更改為不再聲明的宏,則Unity會(huì)創(chuàng)建一個(gè)新的全局宏。

六、內(nèi)置multi_compile快捷方式

unity中提供一些內(nèi)置的宏用于編譯多個(gè)著色器變體。這些主要用于處理Unity中不同的光照,陰影和光照貼圖類型。
multi_compile_fwdbase:編譯PassType.ForwardBase所需的所有變體。變體處理不同的光照貼圖類型,并啟用或禁用主方向光的陰影。
multi_compile_fwdadd:為PassType.ForwardAdd編譯變體。這將編譯變體以處理Directional,Spot或Point Light類型及其變體與Cookie紋理。
multi_compile_fwdadd_fullshadows:同樣multi_compile_fwdadd,但也包括燈具有實(shí)時(shí)陰影的能力。
multi_compile_fog:擴(kuò)展為多個(gè)變體以處理不同的霧類型(off / linear / exp / exp2)。

大多數(shù)內(nèi)置快捷方式都會(huì)產(chǎn)生許多著色器變體。如果您知道項(xiàng)目不需要它們,您可以使用#pragma skip_variants跳過(guò)編譯它們中的一些。例如:

#pragma multi_compile_fwdadd #pragma skip_variants POINT POINT_COOKIE

該指令跳過(guò)包含POINT或POINT_COOKIE的所有變體。

七、查看shader變種數(shù)量

#pragma multi_compile TEST_1 TEST_2 TEST_3 #pragma multi_compile TEST_4 TEST_5 #pragma multi_compile TEST_6 TEST_7

查看變體數(shù)量.png

?

上面的組合會(huì)產(chǎn)生3x2x2=12種變體,我們可以點(diǎn)擊show查看具體的變體組合名稱。

// Total snippets: 1 // ----------------------------------------- // Snippet #0 platforms ffffffff: Keywords always included into build: TEST_1 TEST_2 TEST_3 TEST_4 TEST_5 TEST_6 TEST_712 keyword variants used in scene:TEST_1 TEST_4 TEST_6 TEST_1 TEST_4 TEST_7 TEST_1 TEST_5 TEST_6 TEST_1 TEST_5 TEST_7 TEST_2 TEST_4 TEST_6 TEST_2 TEST_4 TEST_7 TEST_2 TEST_5 TEST_6 TEST_2 TEST_5 TEST_7 TEST_3 TEST_4 TEST_6 TEST_3 TEST_4 TEST_7 TEST_3 TEST_5 TEST_6 TEST_3 TEST_5 TEST_7

這里查看的是所有會(huì)被編譯的變體的數(shù)量,也就是#pragma multi_compile聲明的宏的全部組合。

#pragma multi_compile TEST_1 TEST_2 TEST_3 #pragma multi_compile TEST_4 TEST_5 #pragma shader_feature TEST_6 TEST_7

查看變種數(shù)量.png

// Total snippets: 1 // ----------------------------------------- // Snippet #0 platforms ffffffff: Keywords stripped away when not used: TEST_6 TEST_7 Keywords always included into build: TEST_1 TEST_2 TEST_3 TEST_4 TEST_56 keyword variants used in scene:TEST_1 TEST_4 TEST_6 TEST_1 TEST_5 TEST_6 TEST_2 TEST_4 TEST_6 TEST_2 TEST_5 TEST_6 TEST_3 TEST_4 TEST_6 TEST_3 TEST_5 TEST_6

上面的組合會(huì)產(chǎn)生3x2x1=6種變體,#pragma shader_feature沒(méi)有特別處理的話只有會(huì)默認(rèn)包括第一個(gè)宏。

八、編譯

(1)material的ShaderKeywords

Material所包含的Shader Keywords表示啟用shader中對(duì)應(yīng)的宏,Unity會(huì)調(diào)用當(dāng)前宏組合所對(duì)應(yīng)的變體來(lái)為Material進(jìn)行渲染。在Editor下,可以通過(guò)將material的inspector調(diào)成Debug模式來(lái)查看當(dāng)前material定義的Keywords,也可在此模式下直接定義Keywords,用空格分隔Keyword。

?

設(shè)置ShaderKeywords.png

?

優(yōu)點(diǎn):根據(jù)material中的ShaderKeywords自動(dòng)生成變體。無(wú)需額外設(shè)置
缺點(diǎn):多個(gè)不同的material包中可能存在相同的shader變體,造成資源冗余。若在程序運(yùn)行時(shí)動(dòng)態(tài)改變material的keyword其變體可能并沒(méi)有被生成
如上圖設(shè)置:如果ShaderKeywords中沒(méi)有設(shè)置TEST_6,這是如果我們想在程序中通過(guò)代碼動(dòng)態(tài)使用TEST_6這個(gè)宏(Shader.EnableKeyword("TEST_6"))。可能不能得到想要的效果,因?yàn)門EST_6這個(gè)變種沒(méi)有生成。

(2)把Shader加入到Always Include Shaders列表里

找到ProjectSetting->Graphics->Always Include Shaders列表,將我們需要的shader添加到里面,這樣unity將會(huì)把這個(gè)shader的所有的變種都生成出來(lái)。

?

AlwaysIncludeShaders.png

優(yōu)點(diǎn):我們不用擔(dān)心項(xiàng)目發(fā)布出去以后有些變種沒(méi)有生成,不能在程序中動(dòng)態(tài)的去控制我們的宏。
缺點(diǎn):生成的變體數(shù)量龐大,導(dǎo)致發(fā)布時(shí)間變長(zhǎng),游戲包體過(guò)大。比如你把standardShader放進(jìn)去,由于它有大量的keyword,全部變種都生成的話大概有幾百兆。

(3)使用ShaderVariantCollection是生成指定變體

ShaderVariantCollection是unity5.x以后用來(lái)記錄shader的哪些變體需要被生成。這樣做的好處就是在shader_feature與multi_compile結(jié)合使用時(shí),能夠設(shè)置生成何種變體,從而避免生成不必要的變體;shader不必和material打在一個(gè)包中,避免了多個(gè)包中存在相同的變體資源;明確直觀的顯示了哪些變體是需要生成的。

生成方式:

(1)通過(guò)Create->Shader-> Shader Variant Collection,就可以新建一個(gè)shader variant collection文件,手動(dòng)添加需要編譯的變種

?

ShaderVariantCollection.png

?

選擇需要生成的變種.png

?

(2)通過(guò)Edit->Project Settings->Graphics中的save to asst...按鈕,生成unity幫我們自動(dòng)收集的,使用到的變種信息。

?

自動(dòng)生成.png

這時(shí)候只需要先Clear一下,然后依次打開我們的所有場(chǎng)景,把需要的物體都顯示一遍,Unity就會(huì)自動(dòng)記錄下來(lái)哪些著色器的哪些著色器變體已經(jīng)被使用到。統(tǒng)計(jì)完后只需點(diǎn)擊下面的保存按鈕就可以生成我們所需要的ShaderVariantCollection資源。當(dāng)然你也可以為你的每一個(gè)場(chǎng)景或者按需生成足夠多的ShaderVariantCollection資源。自動(dòng)收集的功能不一定百分百可靠,最好事后多檢查。

ShaderVariantCollection加載:

啟動(dòng)時(shí)預(yù)加載:

?

最簡(jiǎn)單最粗暴的使用方式就是在游戲啟動(dòng)的瞬間就直接加載ShaderVariantCollection資源并編譯里面的著色器變體,Unity已經(jīng)為我們做好這一步了,依然還是在圖形設(shè)置面板里,只需把需要啟動(dòng)是就編譯的ShaderVariantCollection添加在Preloaded Shaders里面

預(yù)加載.png


代碼加載:

由于ShaderVariantCollection也是一種資源,可以跟紋理、模型等等資源一起打包和加載等,只需在加載之后調(diào)用一句WarmUp。

ShaderVariantCollection shaderVariantCollection = Resources.Load <ShaderVariantCollection>( "MainShaderVariant"); if (shaderVariantCollection )shaderVariantCollection.WarmUp ();

也可以把ShaderVariantCollection放在Resources目錄下,好像會(huì)被自動(dòng)加載。



?

總結(jié)

以上是生活随笔為你收集整理的unity shader 变种(多重编译 multi_compile)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。