Unity custom shader中調(diào)用內(nèi)置Lightmap和Light Probes

剛開(kāi)始接觸unity shader的時(shí)候發(fā)現(xiàn)自己寫(xiě)的unlit shader不支持烘焙場(chǎng)景中的光沾凄,無(wú)論烘焙場(chǎng)景什么樣,自己寫(xiě)的shader根本不接受烘焙的影響撒蟀,而unity自帶的standard shader及其他一系列都完美支持,那自己寫(xiě)的shader要如何像unity自帶shader那樣支持烘焙呢手负?
其實(shí)很簡(jiǎn)單姑尺,幾行代碼就能搞定。讓我們先來(lái)看一個(gè)場(chǎng)景

場(chǎng)景

這是我在unity中搭建了一個(gè)臨時(shí)場(chǎng)景并烘焙好(具體過(guò)程可看這個(gè)視頻)统捶,然后這個(gè)猴臉用了standard shader柄粹,現(xiàn)在我把他換成我自己寫(xiě)的一個(gè)最簡(jiǎn)單的diffuse shader,只輸出貼圖顏色驻右,然后就成了這樣
失敗的場(chǎng)景

貼圖丑了點(diǎn),大家無(wú)視好了兑凿。茵瘾。。
現(xiàn)在發(fā)現(xiàn)拗秘,咦,為什么不像剛剛那樣在猴臉的左側(cè)有橙黃色的光疊加而右側(cè)有藍(lán)光的疊加呢扮匠?這是因?yàn)槟菐仔猩衿娴拇a沒(méi)有加,我們現(xiàn)在來(lái)看要加什么棒搜。

Shader "Unlit/Monkey"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Color ("Main Color",Color) = (1,1,1,1)
        
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float2 uv1 : TEXCOORD1;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                #ifdef LIGHTMAP_ON
                    float2 uvLM : TEXCOORD1;
                #endif
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed4 _Color;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                #ifdef LIGHTMAP_ON
                    o.uvLM = v.uv1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
                #endif
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
                col *= _Color;
                #ifdef LIGHTMAP_ON
                    fixed3 lm = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap,i.uvLM));
                    col.rgb *= lm;
                #endif
                return col;
            }
            ENDCG
        }
    }
}

首先第一條要在CGPROGRAM后添加一行
#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
這樣shader就可以判斷l(xiāng)ightmap開(kāi)沒(méi)開(kāi)了力麸。

然后在vertex shader里添加

#ifdef LIGHTMAP_ON
    o.uvLM = v.uv1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
#endif

把lightmap的uv準(zhǔn)備好之后使用。
這里這樣寫(xiě)是和unity的源碼TRANSFORM_TEX一致

// Transforms 2D UV by scale/bias property
#define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)

不過(guò)不能直接調(diào)用TRANSFORM_TEX是因?yàn)?code>unity_LightmapST這個(gè)東西在ST之前沒(méi)有下劃線(xiàn)_闺鲸,所以沒(méi)法用現(xiàn)成的方法了埃叭。
再來(lái)到fragment shader里就和獲取主貼圖一樣操作了

#ifdef LIGHTMAP_ON
    fixed3 lm = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap,i.uvLM));
    col.rgb *= lm;
#endif

這里為什么要用DecodeLightmap又要用UNITY_SAMPLE_TEX2D來(lái)解讀ligtmap呢?實(shí)際上unity生成的lightmap的有兩種編碼格式:doubleLDR和RGBM立镶,根據(jù)馮樂(lè)樂(lè)前輩的考證

Unity使用了兩種編碼方式來(lái)存儲(chǔ)lightmap:
1类早、doubleLDR,需要一張rgb24貼圖
2莺奔、RGBM,需要一張rgba32貼圖
在移動(dòng)設(shè)備上使用doubleLDR格式令哟,可以獲得更快的計(jì)算速度。它只用到了lightmap的RGB通道晴竞。
PC上則使用RGBM格式狠半,可以獲得更廣的亮度范圍,而犧牲一點(diǎn)速度神年。它使用了貼圖的RGBA通道,而A通道是用來(lái)做乘法垛耳,所以稱(chēng)為RGBM格式。
這兩種格式的差異就是導(dǎo)致不同平臺(tái)下lightmap表現(xiàn)不同的原因堂鲜,當(dāng)然Unity會(huì)在切換平臺(tái)時(shí)幫我們對(duì)貼圖進(jìn)行轉(zhuǎn)換,而不需要太關(guān)心這個(gè)差異哥纫。

我們這樣解讀lightmap才能得到正確的顏色值而且不必?fù)?dān)心因?yàn)槠脚_(tái)不同造成的差異痴奏。

其實(shí)烘焙分為兩種模式,有向的和無(wú)向的抛虫,如下圖

上面的解析光照貼圖方式是針對(duì)無(wú)向模式简僧,有向模式應(yīng)該這樣解析

float4 lightmapDir = UNITY_SAMPLE_TEX2D_SAMPLER(unity_LightmapInd, unity_Lightmap, i.uvLM);
float3 lm = DecodeDirectionalLightmap(col,lightmapDir,normal);

unity_LightmapInd代表有向模式下烘焙出來(lái)的包含光照方向的光照貼圖(是的!有向模式會(huì)烘焙出兩張光照貼圖棉姐,一張里儲(chǔ)存顏色啦逆,一張里儲(chǔ)存方向),然后有個(gè)方法叫DecodeDirectionalLightmap夏志,需要傳入顏色(比如說(shuō)物體貼圖的顏色,或者自定義的顏色湿诊,看最終想要的效果來(lái)決定)瘦材,解析出來(lái)的光照貼圖顏色以及世界坐標(biāo)下的法線(xiàn),這樣出來(lái)的最終結(jié)果就是有向烘焙模式下光照貼圖的信息了食棕。

最終,我們自己寫(xiě)的shader也能支持烘焙了眶拉。


成功的場(chǎng)景

說(shuō)完如何支持lightmap憔儿,我們?cè)賮?lái)看看如何支持light probes。我們?cè)诤姹簣?chǎng)景的時(shí)候,有時(shí)候場(chǎng)景中的某些東西不是static吴侦,也就是不是固定不動(dòng)的坞古,這樣烘焙好的結(jié)果無(wú)法應(yīng)用到這種在場(chǎng)景中動(dòng)來(lái)動(dòng)去的物件,而我們希望這樣的物件依然受到烘焙的影響痪枫,那么這個(gè)時(shí)候就需要light probes了。
由于弄light probes挺麻煩的易阳,所以我直接使用了這篇博客中的場(chǎng)景吃粒,然后加上了幾行代碼來(lái)支持light probes。我們先來(lái)看結(jié)果(這次我會(huì)做動(dòng)圖了P觳)


這個(gè)方塊在動(dòng)到黃色區(qū)域的時(shí)候呈現(xiàn)偏黃的顏色,而到了藍(lán)色區(qū)域就會(huì)偏藍(lán)肖爵。這其實(shí)就是在利用unity shader中自帶的一個(gè)方法ShadeSH9來(lái)實(shí)現(xiàn)的臀脏,具體代碼如下

Shader "Unlit/LightProbes"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Color ("Main Color",Color) = (1,1,1,1)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" "LightMode" = "ForwardBase" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                fixed3 SHLighting : COLOR;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed4 _Color;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                float3 worldNormal = UnityObjectToWorldNormal(v.normal);
                o.SHLighting = ShadeSH9(float4(worldNormal,1));
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
                col *= _Color;
                col.rgb *= i.SHLighting;
                return col;
            }
            ENDCG
        }
    }
}

這里有一點(diǎn)要記住揉稚,自定義的shader一定要寫(xiě)上Tags{"LightMode" = "ForwardBase"},即是說(shuō)要指定好LightMode窃植,不指定的話(huà)ShadeSH9會(huì)返回黑色(全黑的那種),你完全不會(huì)想看到的顏色巷怜。

項(xiàng)目地址

參考
UnityShader實(shí)例07:在shader調(diào)用unity內(nèi)置lightmap和light Probes

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末延塑,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子关带,更是在濱河造成了極大的恐慌沼撕,老刑警劉巖芜飘,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異笼沥,居然都是意外死亡娶牌,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)诗良,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人舞骆,你說(shuō)我怎么就攤上這事壹罚∈傩撸” “怎么了猖凛?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵辨泳,是天一觀的道長(zhǎng)玖院。 經(jīng)常有香客問(wèn)我,道長(zhǎng)难菌,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任遇绞,我火速辦了婚禮燎窘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘褐健。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布俊抵。 她就那樣靜靜地躺著纽匙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪烛缔。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,764評(píng)論 1 290
  • 那天院喜,我揣著相機(jī)與錄音晕翠,去河邊找鬼。 笑死淋肾,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的拿愧。 我是一名探鬼主播碌尔,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼唾戚!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起熊镣,我...
    開(kāi)封第一講書(shū)人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤募书,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后锐膜,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡而柑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了粹排。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涩澡。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖妙同,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情胰耗,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布柴灯,位于F島的核電站费尽,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏旱幼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一叹誉、第九天 我趴在偏房一處隱蔽的房頂上張望闷旧。 院中可真熱鬧钧唐,春花似錦忙灼、人聲如沸钝侠。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)忽舟。三九已至双妨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間泣特,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工状您, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留兜挨,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓骆莹,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親幕垦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子傅联,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

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

  • 0. 寫(xiě)在之前 其實(shí)針對(duì)這個(gè)問(wèn)題已經(jīng)寫(xiě)了一篇很簡(jiǎn)單的填坑筆記了,但是UWA說(shuō)希望那篇文章稍微擴(kuò)充一下放到USpar...
    董夕閱讀 3,625評(píng)論 9 13
  • 前言:最近在做一個(gè)美術(shù)館的場(chǎng)景仇奶,對(duì)于燈光的要求非常高比驻,經(jīng)過(guò)幾天的調(diào)試和在網(wǎng)上查閱一些資料,總結(jié)一下别惦。全局光照,簡(jiǎn)稱(chēng)...
    Tang7閱讀 2,404評(píng)論 0 9
  • 原文地址 http://www.fx114.net/qa-75-172454.aspx 使用Profiler工具...
    IongX閱讀 5,833評(píng)論 1 11
  • 感謝 不敢相信氯庆,距離90天踐行已經(jīng)接近尾聲扰付。得知要寫(xiě)畢業(yè)總結(jié),一股不舍之情油然而生羽莺。 首先特別想感謝一些人。 感謝...
    莫曉騫閱讀 327評(píng)論 0 2
  • "這種果子到底在哪里……"沈鈺翻來(lái)覆去地查看師父留給他的圖鑒荒给。說(shuō)是圖鑒族跛,只不過(guò)是一張畫(huà)著粗劣圖案的紙張锐墙。 沈鈺已經(jīng)...
    自食苦閱讀 311評(píng)論 0 3