主頁 >  其他 > 復雜的光照與更復雜的陰影實作程序——ShaderCP9

復雜的光照與更復雜的陰影實作程序——ShaderCP9

2020-09-10 02:45:52 其他

 

——20.8.28

 

這章的內容看了很久,也有很多復雜的內容,中途還有事情耽擱了一會,開學后就繼續好好記錄努力,

我們在游戲中能看到的讓人覺得真實感的來源之一就是真實的光照以及光照所產生的陰影,下面的內容分為兩個部分一個是光照的部分一個是陰影的生成部分,

說到光照在Unity中渲染路徑就是決定光照是以何種方式應用到Shader中的,所以要通過指定Pass通道的渲染路徑型別 “LightMode” 來進行Shader的光照計算,簡單地說就是設定渲染路徑后Unity便會提供對應的光照資訊給用戶進行光照計算,

目前有三種渲染路徑 1)前向渲染 2)延遲渲染(有新的) 3)頂點照明渲染(被拋棄)

當GPU不支持所選擇的渲染路徑則會降級

設定渲染路徑便是在Tags設定 “LightMode” 有以下支持的的標簽 

如果沒有指定渲染路徑可能會出錯,因為此時當作為頂點照明渲染路徑,當中的一些光照變數可能就不會被賦值,

一、前向渲染路徑

每進行一次完整的前向渲染路徑1.我們需要渲染該物件的渲染圖元2.計算兩個緩沖區的資訊 a.深度緩沖區(決定是否可見)b.顏色緩沖區(若可見,更新顏色緩沖區)對燈光范圍內的物品每一個燈光處理一次執行一次Pass

三種處理光照的方式 1)逐頂點處理 2)逐像素處理 3)球諧函式(SH)

一種光源的處理方式由型別和渲染模式(是否重要的,RenderMode)渲染一個物體要對光源進行排序(對物體的影響程度)要遵循以下規則 1)場景中最亮的平行光總是按逐像素處理2)渲染模式被設定為Not Important按逐頂點或是SH 3)渲染模式被設定為Important按逐像素處理 4)如果按以上規則得到的逐像素光源數量小于Quality Setting(PixelLight Count)將會由更多的光源按照逐像素處理

 

 

 

 注意事項:1.BasePass支持的光照特性 2.BasePass渲染的平行光默認有燈光 AddtivePass渲染的光源默認情況下沒有陰影(即使設定了ShadowType)可以通過 #pragma multi_compile_fwdadd_fullshadows 代替 #pragma multi_compile_fwdadd 為點光源和聚光燈開啟陰影 3.環境光(環境光和平行光不同)和自發光在BasePass計算因為只計算一次在AdditivePass會導致多次疊加 4.AdditivePass還要開啟混合不然只有一個光源的影響 5.一個BassPass可定義多次(比如雙面渲染)但只運行一遍而AdditivePass會根據影響該物體的逐像素光源多次呼叫 

 

以上是一些內置的函式和變數

二、頂點照明渲染

頂點照明可在前向渲染中完成,一個頂點照明的Pass最多8個逐頂點光源

 

三、延遲渲染路徑

G緩沖 存盤了離攝像機最近的表面的其他資訊 包含兩個單元第一個Pass計算哪些片元可見,第二個Pass利用G緩沖區中的資訊光照計算,效率取決于場景的復雜度,而取決于螢屏空間大小,

優點 1)場景中的光源數目多,用前向渲染會造成性能瓶頸 2)每個光源采用逐像素處理 缺點 1)不支持抗鋸齒 2)不能處理半透明 3)對顯卡由需求

分析完渲染路徑之后我們簡單過一下基礎的燈光型別在unity中存在的燈光型別以及它所具有的特點以及屬性 1)平行光(不存在衰減 面向全域)2)點光源(邊緣的強度為0,中間的衰減值可以用函式表示)3)聚光燈(同上,衰減計算更加復雜)4)面光源(只有烘培有用) 燈光所具有的基本特性 1)位置 2)方向 3)顏色 4)強度 5)衰減(到某點的衰減與距離有關)

UnityShader這本書只有對前向渲染有具體的內容,這里留一個延遲渲染路徑的小坑(?)

主要就是注意要添加一個庫“AutoLight.cginc” 其中有對之前對應渲染路徑的內置變數定義,否則就找不到 比如_LightMatrix0之類

#ifdef USING_DIRECTIONAL_LIGHT
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos)); // normalize(_WorldSpaceLightPos0.xyz);
#else
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz);
#endif

  這部分是在AdditivePass中的中區分平行光以及其他光源的光源方向,

#ifdef USING_DIRECTIONAL_LIGHT
fixed atten = 1.0;
#else
float3 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1)).xyz;
fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
//atten = 1.0;
#endif

  這里部分是最重要的這部分是在AdditivePass中對衰減的定義,在BasePass因為主要逐像素處理一個最重要的平行光 而平行光不存在衰減所以atten為1 而在AdditivePass需要區分平行光和其他光源 點光源采用對應函式進行衰減,在Unity中為了方便使用一張衰減紋理_LightTexture0來為光源計算衰減,首先要把對應距離燈光的點通過坐標運算從世界到光源空間,然后通過點乘也就是頂點距離的平方來進行紋理取樣,來避免開方計算,上面的".rr"相當于是取x并定義float2(x,x)用于取樣,UNITY_ATTEN_CHANNEL是衰減值所在的衰減通道,我們不妨看一下這張_LightTexture0是什么樣的圖,就能理解為什么要平方之后再取樣,

 

 這張圖就是按照平方值設計的,可以放到畫圖工具中發現它不是線性的,實際相當于一維坐標,因為只有x,

實際上這么分其實是不夠的因為其他燈光的聚光燈的衰減是不一樣的,這里暫時留一下(?)

// Upgrade NOTE: replaced '_LightMatrix0' with 'unity_WorldToLight'

Shader "Unlit/9-1ForwardRendering"
{
    Properties
    {
		_Diffuse("Diffuse", Color)= (1,1,1,1)
		_Specular("Specular", Color)= (1,1,1,1)
		_Gloss("Gloss", Range(8.0, 256))= 8
    }
    SubShader
    {
        Pass
        {
			Tags { "LightMode"="ForwardBase" }
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fwdbase
			#include "Lighting.cginc"
            #include "UnityCG.cginc"

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

            struct v2f
            {
                float4 pos : SV_POSITION;
				float3 worldNormal : TEXCOORD0;
				float3 worldPos : TEXCOORD1;
            };

            fixed4 _Diffuse;
			fixed4 _Specular;
			float _Gloss;

            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
				o.worldPos = mul(unity_ObjectToWorld, v.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
				fixed3 worldNormal = normalize(i.worldNormal);
				fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
				fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
				fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLightDir));
				fixed3 halfDir = normalize(worldLightDir + viewDir);
				fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(worldNormal, halfDir)), _Gloss);
				fixed atten = 1.0;
				return fixed4(ambient + (diffuse + specular) * atten, 1.0);
            }
            ENDCG
        }

		Pass
		{
			Tags{ "LightMode"="ForwardAdd" }
			Blend One One
			CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fwdadd
			#include "Lighting.cginc"
            #include "UnityCG.cginc"
			#include "AutoLight.cginc"

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

            struct v2f
            {
                float4 pos : SV_POSITION;
				float3 worldNormal : TEXCOORD0;
				float3 worldPos : TEXCOORD1;
            };

            fixed4 _Diffuse;
			fixed4 _Specular;
			float _Gloss;

            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
				o.worldPos = mul(unity_ObjectToWorld, v.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
				fixed3 worldNormal = normalize(i.worldNormal);
				fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
				#ifdef USING_DIRECTIONAL_LIGHT
				fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
				#else
				fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz);
				#endif
				fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLightDir));
				fixed3 halfDir = normalize(worldLightDir + viewDir);
				fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(worldNormal, halfDir)), _Gloss);
				#ifdef USING_DIRECTIONAL_LIGHT
				fixed atten = 1.0;
				#else
				float3 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1)).xyz;
				fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
				//atten = 1.0;
				#endif
				return fixed4((diffuse + specular) * atten, 1.0);
            }
            ENDCG
		}
    }FallBack "Specular"
}

  主要就是在之前的光照模型上區分了BasePass以及AdditivePass,需要指定渲染路徑以及添加對應的#pragma,最后最主要的是增加燈光的衰減,我們可以看一下實際效果,通過改變點光源的atten,足以看出衰減的真實感,衰減也可以用公式不用取樣,一樣后面繼續研究(?)老留坑專家了,

 

 接下來便是最令人頭大的陰影了,但又是最不可獲取的部分,書中的理解部分會居多,

我們先看一個概念ShadowMap,就是把攝像機放到光源重合的位置然后場景中的陰影就是攝像機看不見的位置, (本質上是為了得到光源空間的深度圖)

在前向渲染中,平行光開啟陰影就會計算它的陰影映射紋理(shadowmap),實際上他是一張深度圖(mark一下后面的仔細研究一下深度的應用?)記錄了從光源位置出發能看到離他位置最近的表面位置也就是深度資訊,那具體是怎么判斷距離光源最近的表面呢?有以下兩種方法,1)就是用上面的這個ShadowMap方法,把攝像機放到光源位置然后通過前向渲染的BasePass/AdditivePass更新深度資訊,但是使用這種正常渲染方式其中涉及狠毒復雜的光照模型計算所以很浪費 2)使用額外的Pass “LightMode”=“ShadowCaster” 渲染目標是陰影映射紋理不是幀快取,首先一樣是把攝像機放到光源位置然后呼叫該Pass(此事獲得的深度資訊是光源空間,因為和光源重合),介紹了上述兩個獲得表面的方法,在unity中首先會a.找該Pass b.然后找FallBake(因為FallBack定義的默認Shader會有對陰影定義的ShadowCaster通道) c.如果都沒有就沒有陰影,

然后到了最后一步就是獲得了對應的深度怎么把它應用到陰影上,陰影映射技術就是我們需要看的 主要是由兩種方法 1.傳統方法,把正常的頂點坐標轉換到光源空間,然后用xy分量對陰影映射紋理取樣,如果深度小于改頂點的深度值也就是z分量則在陰影里, 2.螢屏空間的陰影投射技術,用陰影映射紋理以及攝像機(相機擺放位置即Game視圖)的深度紋理通過這兩張圖得到螢屏空間的陰影圖,攝像機記錄的表面深度深度>其轉換到陰影紋理的深度即為可見,但在該燈源的陰影中,然后對陰影圖采樣,

所以總結一下 兩個程序 1.我們想要讓物體接受其他物體的陰影我們就要對陰影圖采樣然后于光照結果相乘,2.我們想要一個物體向其他物體投射陰影則需要把該物體加入陰影映射紋理的計算中,我們下面進入實踐程序,

 

 

 

我們可以看到這張圖發現有一點奇怪,物品命名有陰影但是這個平面卻沒有,主要原因是平面在unity中只有一面渲染另一面不渲染,所以解決方法便是改變平面的MeshRenderer中的CastShadow為TwoSides才能得到正確的陰影,

 

 

我們看一下這張圖發現這個方塊沒有接受到平面的陰影但自己卻有陰影而且在Unity設定是正確的即有開啟CastShadow 實際上之所以方塊有陰影是因為采用了FallBack中的“ShadowCaster”的通道但是我們可以從上圖得知平面想要投射陰影需要加入陰影投射紋理,實際上是輸出片元的時候沒有采樣陰影映射紋理,我們可以通過FrameBugger觀察它的深度圖,

 

 上面兩張圖是一樣的陰影圖,但是在渲染方塊的時候卻不一樣,

 

 

SHADOW_COORDS(2)//在v2f中的定義
TRANSFER_SHADOW(o);//在vert中
//在frag中
fixed shadow = SHADOW_ATTENUATION(i);
return fixed4(ambient + (diffuse + specular) * atten * shadow, 1.0);

  首先SHADOW_COORDS(2)用于對陰影采樣紋理的坐標里面的索引值是2也就對應的是TEXCOORD2.在片元函式中的就是進行陰影映射技術把資訊存盤到_ShadowCrood,SHADOW_ATTENUATION對紋理進行采樣,要注意結構體的命名可能會導致定義的宏不可用,

// Upgrade NOTE: replaced '_LightMatrix0' with 'unity_WorldToLight'
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'

Shader "Unlit/9-2Shadow"
{
    Properties
    {
        _Diffuse ("Diffuse", Color) = (1, 1, 1, 1)
		_Specular ("Specular", Color) = (1, 1, 1, 1)
		_Gloss ("Gloss", Range(8.0, 256)) = 20
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }

        Pass
        {
			Tags { "LightMode"="ForwardBase" }
            CGPROGRAM
			#pragma multi_compile_fwdbase
            #pragma vertex vert
            #pragma fragment frag
            #include "AutoLight.cginc"
			#include "Lighting.cginc"
            #include "UnityCG.cginc"

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

            struct v2f
            {
                float4 pos : SV_POSITION;
				float3 worldNoraml : TEXCOORD0;
				float3 worldPos : TEXCOORD1;
				SHADOW_COORDS(2)
            };

            fixed4 _Specular;
			fixed4 _Diffuse;
			float _Gloss;

            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.worldNoraml = UnityObjectToWorldNormal(v.normal);
				o.worldPos = mul(unity_ObjectToWorld, v.vertex);
				TRANSFER_SHADOW(o);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed3 worldNoraml = normalize(i.worldNoraml);
				fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
				fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNoraml, worldLightDir));
				fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
				fixed3 halfDir = normalize(viewDir + worldLightDir);
				fixed3 specular = _LightColor0.rgb * _Specular * pow(saturate(dot(worldNoraml, halfDir)), _Gloss);
				fixed atten = 1.0;
				fixed shadow = SHADOW_ATTENUATION(i);
				return fixed4(ambient + (diffuse + specular) * atten * shadow, 1.0);
            }
            ENDCG
        }

		Pass
        {
			Tags { "LightMode"="ForwardAdd" }
			Blend One One
            CGPROGRAM
			#pragma multi_compile_fwdadd
			#pragma multi_compile_fwdadd_fullshadows
            #pragma vertex vert
            #pragma fragment frag
            #include "AutoLight.cginc"
			#include "Lighting.cginc"
            #include "UnityCG.cginc"

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

            struct v2f
            {
                float4 pos : SV_POSITION;
				float3 worldNoraml : TEXCOORD0;
				float3 worldPos : TEXCOORD1;
            };

            fixed4 _Specular;
			fixed4 _Diffuse;
			float _Gloss;

            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.worldNoraml = UnityObjectToWorldNormal(v.normal);
				o.worldPos = mul(unity_ObjectToWorld, v.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed3 worldNoraml = normalize(i.worldNoraml);
				#ifdef USING_DIRECTIONAL_LIGHT
				fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
				#else
				fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz);
				#endif
				fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNoraml, worldLightDir));
				fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
				fixed3 halfDir = normalize(viewDir + worldLightDir);
				fixed3 specular = _LightColor0.rgb * _Specular * pow(saturate(dot(worldNoraml, halfDir)), _Gloss);
				#ifdef USING_DIRECTIONAL_LIGHT
					fixed atten = 1.0;
				#else
					float3 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1)).xyz;
					fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
				#endif
				return fixed4((diffuse + specular) * atten , 1.0);
            }
            ENDCG
        }
    }FallBack "Specular"
}

 

現在我們就有平面的投影了,

 

UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);

  這個函式是可以直接統一管理衰減以及陰影,不需要定義atten可以直接用,

// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'

Shader "Unlit/9-3AttenuationAndShadowUseBuildInFunc"
{
    Properties
    {
        _Diffuse ("Diffuse", Color) = (1, 1, 1, 1)
		_Specular ("Specular", Color) = (1, 1, 1, 1)
		_Gloss ("Gloss", Range(8.0, 256)) = 20
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }

        Pass
        {
			Tags { "LightMode"="ForwardBase" }
            CGPROGRAM
			#pragma multi_compile_fwdbase
            #pragma vertex vert
            #pragma fragment frag
			#include "Lighting.cginc"
			#include "AutoLight.cginc"
            #include "UnityCG.cginc"

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

            struct v2f
            {
                float4 pos : SV_POSITION;
				float3 worldNormal : TEXCOORD0;
				float3 worldPos : TEXCOORD1;
				SHADOW_COORDS(2)
            };

			fixed4 _Diffuse;
			fixed4 _Specular;
			float _Gloss;

            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
				o.worldPos = mul(unity_ObjectToWorld, v.vertex);
				TRANSFER_SHADOW(o);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed3 worldNormal = normalize(i.worldNormal);
				fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
				fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
				fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLightDir));
				fixed3 halfDir = normalize(viewDir + worldLightDir);
				fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(worldNormal, halfDir)), _Gloss);
				UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
				return fixed4(ambient + (diffuse + specular) * atten, 1.0);
            }
            ENDCG
        }

		Pass
        {
			Tags { "LightMode"="ForwardAdd" }
            CGPROGRAM
			#pragma multi_compile_fwdadd
			#pragma multi_compile_fwdadd_fullshadows
            #pragma vertex vert
            #pragma fragment frag
			#include "Lighting.cginc"
			#include "AutoLight.cginc"
            #include "UnityCG.cginc"

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

            struct v2f
            {
                float4 pos : SV_POSITION;
				float3 worldNormal : TEXCOORD0;
				float3 worldPos : TEXCOORD1;
				SHADOW_COORDS(2)
            };

			fixed4 _Diffuse;
			fixed4 _Specular;
			float _Gloss;

            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
				o.worldPos = mul(unity_ObjectToWorld, v.vertex);
				TRANSFER_SHADOW(o);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed3 worldNormal = normalize(i.worldNormal);
				fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
				fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
				fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLightDir));
				fixed3 halfDir = normalize(viewDir + worldLightDir);
				fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(worldNormal, halfDir)), _Gloss);
				UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
				return fixed4((diffuse + specular) * atten, 1.0);
            }
            ENDCG
        }
    }
}

  這樣BasePass和AdditivePass就可以統一,

最后就是上一節的一個小坑也是填上了,就是半透明物體的陰影關系,

// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'

Shader "Unlit/9-4AlphaTestWithShadow"
{
    Properties
    {
        _Color("Color", Color) = (1,1,1,1)
        _MainTex ("Texture", 2D) = "white" {}
		_Cutoff ("Alpha Cutoff", Range(0, 1)) = 0.5
    }
    SubShader
    {
        Tags { "RenderType"="TransparentCutOut" "IgnoreProjector"="True" "Queue"="AlphaTest" }
        Pass
        {
			Tags{ "LightMode"="ForwardBase" }

			Cull Off

            CGPROGRAM
			#pragma multi_compile_fwdbase
            #pragma vertex vert
            #pragma fragment frag
            #include "Lighting.cginc"
			#include "AutoLight.cginc"
            #include "UnityCG.cginc"

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

            struct v2f
            {
				float4 pos : SV_POSITION;
				float3 worldNormal : TEXCOORD0;
				float3 worldPos : TEXCOORD1;
				float2 uv : TEXCOORD2;
				SHADOW_COORDS(3) //TEXCOORD3
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
			fixed4 _Color;
			fixed _Cutoff;

            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
				o.worldPos = mul(unity_ObjectToWorld, v.vertex);
				o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
				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);
				clip(texColor.a - _Cutoff);
				fixed3 albedo = texColor.rgb * _Color.rgb;
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb * albedo;
				fixed3 diffuse = _LightColor0.rgb * albedo * saturate(dot(worldNormal, worldLightDir));
				UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
				return fixed4(ambient + diffuse * atten, 1.0);
            }
            ENDCG
        }
    }
  //FallBack "VertexLit"
  FallBack "Transparent/Cutout/VertexLit" }

  首先是透明測驗的投影,效果圖如下,圖一是表示能夠正常的接受陰影,圖二圖三分別是采用不同的FallBack的效果后者相對于前者是比較正確的,最后一張圖是是否打開CastShadow中的TwoSides左邊是打開的可以看出正方形的內部投影是和左邊相比體現了處理,

 

 最后是透明度混合的陰影,同樣的增加FallBack

// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Unlit/9-5AlphaBlendWithShadow"
{
    	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
			
			#pragma multi_compile_fwdbase
			
			#pragma vertex vert
			#pragma fragment frag
			
			#include "Lighting.cginc"
			#include "AutoLight.cginc"
			
			fixed4 _Color;
			sampler2D _MainTex;
			float4 _MainTex_ST;
			fixed _AlphaScale;
			
			struct a2v {
				float4 vertex : POSITION;
				float3 normal : NORMAL;
				float4 texcoord : TEXCOORD0;
			};
			
			struct v2f {
				float4 pos : SV_POSITION;
				float3 worldNormal : TEXCOORD0;
				float3 worldPos : TEXCOORD1;
				float2 uv : TEXCOORD2;
				SHADOW_COORDS(3)
			};
			
			v2f vert(a2v v) {
			 	v2f o;
			 	o.pos = UnityObjectToClipPos(v.vertex);
			 	
			 	o.worldNormal = UnityObjectToWorldNormal(v.normal);
			 	
			 	o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;

			 	o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
			 	
			 	// Pass shadow coordinates to pixel shader
			 	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;
				
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
				
				fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal, worldLightDir));

			 	// UNITY_LIGHT_ATTENUATION not only compute attenuation, but also shadow infos
				UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
			 	
				return fixed4(ambient + diffuse * atten, texColor.a * _AlphaScale);
			}
			
			ENDCG
		}
	} 
	//FallBack "Transparent/VertexLit"
	// Or  force to apply shadow
	FallBack "VertexLit"
}

  采用FallBack "VertexLit"會強制投影同時接受陰影,"Transparent/VertexLit"兩者都不會,主要是半透明物體由于關閉了深度寫入也會影響對應陰影的生成,

 

這就是最后了,感謝您讀到這里,Cheers!

 PS:這章總算是看完了,還留了很多坑,慢慢補把,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/561.html

標籤:其他

上一篇:抖音短視頻決議去水印助手、批量采集無水印抖音快手短視頻

下一篇:openGL 學習筆記 (二) 使用GL API 繪制出屬于自己的矩形

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more