Unity Shader 透明度混合物體的陰影

Unity Shader系列文章:Unity Shader目錄-初級篇

Unity Shader系列文章:Unity Shader目錄-中級篇

效果:
▲FallBack設(shè)置為Transparent/VertexLit,不會投射陰影鹦肿,也不會接收陰影
▲Fallback設(shè)為VertexLit來強制為半透明物體生成陰影
▲紋理圖
原理:

使用透明度混合的物體添加陰影是一件比較復(fù)雜的事情药磺。事實
上,所有內(nèi)置的透明度混合的Unity Shader,如Transparent/VertexLit等舟舒,都沒有包含陰影投射的Pass拉庶。這意味著,這些半透明物體不會參與深度圖和陰影映射紋理的計算秃励,也就是說氏仗,它們不會向其他物體投射陰影,同樣它們也不會接收來自其他物體的陰影夺鲜。

Unity會這樣處理半透明物體是有它的原因的皆尔。由于透明度混合需要關(guān)閉深度寫入,由此帶來的問題也影響了陰影的生成币励】度洌總體來說,要想為這些半透明物體產(chǎn)生正確的陰影食呻,需要在每個光源空間下仍然嚴(yán)格按照從后往前的順序進行渲染流炕,這會讓陰影處理變得非常復(fù)雜澎现,而且也會影響性能。因此每辟,在Unity中剑辫,所有內(nèi)置的半透明Shader 是不會產(chǎn)生任何陰影效果的。

當(dāng)然渠欺,我們可以強制為半透明物體生成陰影妹蔽,這可以通過把它們的Fallback設(shè)置為VertexLit、Diffuse 這些不透明物體使用的Unity Shader挠将,這樣Unity就會在它的Fallback找到一 個陰影投射的Pass讹开。

Shader代碼:

// 透明物體,陰影
Shader "Unlit/AlphaBlendWithShadow"
{
    Properties
    {
        _Color ("Color Tint", Color) = (1, 1, 1, 1)
        _MainTex ("Main Tex", 2D) = "white" { }// 主紋理
        _AlphaScale ("Alpha Scale", Range(0, 1)) = 1 // 透明度
    }
    SubShader
    {
        Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }

        pass
        {
            Tags { "LightMode" = "ForwardBase" }

            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha
            
            CGPROGRAM
            
            // 編譯指令,保證在pass中得到Pass中得到正確的光照變量
            #pragma multi_compile_fwdbase

            #pragma vertex vert
            #pragma fragment frag

            #include "Lighting.cginc"
            #include "AutoLight.cginc"

            fixed4 _Color;
            sampler2D _MainTex;
            // _MainTex_ST(聲明方式:name_ST): 聲明_MainTex是一張采樣圖,用于uv運算, 下面2個是等價的
            // o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
            // o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
            // 如果沒有聲明是不能進行TRANSFORM_TEX的運算的良蛮。_MainTex_ST.xy為紋理圖Tiling(縮放), zw為紋理中的offset(偏移)
            // 如果Tiling 和 Offset留的是默認值擎鸠,即Tiling為(1,1) Offset為(0安吁,0)的時候,可以不用TRANSFORM_TEX運算
            // 即:o.uv = v.texcoord
            fixed4 _MainTex_ST;
            fixed _AlphaScale;

            // 應(yīng)用傳遞給頂點著色器的數(shù)據(jù)
            struct a2v
            {
                float4 vertex: POSITION; // 語義: 頂點坐標(biāo)
                float3 normal: NORMAL; // 語義:法線
                float4 texcoord: TEXCOORD0; // 語義:第一組紋理的坐標(biāo)
            };

            // 頂點著色器傳遞給片元著色器的數(shù)據(jù)
            struct v2f
            {
                float4 pos: SV_POSITION; // 語義:裁剪空間的頂點坐標(biāo)
                float3 worldNormal: TEXCOORD0;
                float3 worldPos: TEXCOORD1;
                float2 uv: TEXCOORD2;
                SHADOW_COORDS(3) // 聲明一個用于對陰影紋理采樣的坐標(biāo) (這個宏參數(shù)需要是下一個可用的插值寄存器的索引值,這里是3)
            };

            // 頂點著色器
            v2f vert(a2v v)
            {
                v2f o;

                // 將頂點坐標(biāo)從模型空間變換到裁剪空間
                // 等價于o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                o.pos = UnityObjectToClipPos(v.vertex);

                // 將法線從模型空間變換到世界空間
                // 等價于o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject);
                o.worldNormal = UnityObjectToWorldNormal(v.normal);

                // 將頂點坐標(biāo)從模型空間變換到世界空間
                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;

                // 計算紋理坐標(biāo) (縮放和平移)
                // 等價于o.uv = v.texcoord * _MainTex_ST.xy + _MainTex_ST.zw;
                o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);

                // 計算聲明的陰影紋理坐標(biāo)
                TRANSFER_SHADOW(o);

                return o;
            }

            // 片元著色器
            fixed4 frag(v2f i): SV_TARGET
            {
                fixed3 worldNormal = normalize(i.worldNormal);

                // 世界空間光向量
                fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));

                // 對紋理進行采樣
                fixed4 texColor = tex2D(_MainTex, i.uv);

                fixed3 albedo = texColor.rgb * _Color.rgb;

                // 環(huán)境光
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;

                // 漫反射
                fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal, worldLightDir));

                // 計算陰影和光照衰減
                UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);

                return fixed4(ambient + diffuse * atten, texColor.a * _AlphaScale);
            }
            
            ENDCG
            
        }
    }

    FallBack "Transparent/VertexLit"
    // 或者強制投射陰影
    // FallBack "VertexLit"
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末淆两,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子拂酣,更是在濱河造成了極大的恐慌秋冰,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件婶熬,死亡現(xiàn)場離奇詭異剑勾,居然都是意外死亡,警方通過查閱死者的電腦和手機赵颅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門虽另,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人饺谬,你說我怎么就攤上這事捂刺。” “怎么了募寨?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵族展,是天一觀的道長。 經(jīng)常有香客問我拔鹰,道長仪缸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任格郁,我火速辦了婚禮腹殿,結(jié)果婚禮上独悴,老公的妹妹穿的比我還像新娘。我一直安慰自己锣尉,他們只是感情好刻炒,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著自沧,像睡著了一般坟奥。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上拇厢,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天爱谁,我揣著相機與錄音,去河邊找鬼孝偎。 笑死访敌,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的衣盾。 我是一名探鬼主播寺旺,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼势决!你這毒婦竟也來了阻塑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤果复,失蹤者是張志新(化名)和其女友劉穎陈莽,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體虽抄,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡走搁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了极颓。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片朱盐。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡群嗤,死狀恐怖菠隆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情狂秘,我是刑警寧澤骇径,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站者春,受9級特大地震影響破衔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜钱烟,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一晰筛、第九天 我趴在偏房一處隱蔽的房頂上張望嫡丙。 院中可真熱鬧,春花似錦读第、人聲如沸曙博。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽父泳。三九已至,卻和暖如春吴汪,著一層夾襖步出監(jiān)牢的瞬間惠窄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工漾橙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留杆融,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓霜运,卻偏偏與公主長得像擒贸,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子觉渴,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

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