害,今天就把阴影看了吧,和上一篇的主题不太搭调,就新开了一个文章,哈哈哈哈

ShadowMap的原理

        突然翻上半年听games202课程闫老师讲的ShadowMap的知识点了。

        大致就是说从光源的方向看物体生成一张阴影映射纹理(shadowMap)

unity相机剔除阴影 unity物体阴影_Time

        差不多长这个样子 

unity相机剔除阴影 unity物体阴影_unity_02

然后捏,我们摄像机看到的一些物体在世界坐标下的位置在shadowmap中查找,如果深度大于shadowMap中的呢,那肯定就是在阴影中了啊!反正大概就是个这么意思了啦,可能不是很准确。

unity相机剔除阴影 unity物体阴影_unity_03

阴影在Unity中

        在unity中物体可以选择是否投射阴影或者是否接收阴影这种选择,如果你选择接收阴影,那你的物体就得采样shadowmap,如果你选择投射阴影,那你这个物体就要加入shadowmap的计算中去。

        投射阴影

        在unity中专门用了一个pass并且LightmModel 为ShadowCaster来投射阴影,当我们使用shadowMap的这个阴影技术的时候,就会启动这个pass。这个pass很多时候都在FallBack语句中,然后一直回调,直到调用到vertexLit。如果是透明物体的阴影,你就要使用Transparent/Cutout/VertexLit。当然你也可以自己在shader里面写这个pass。

        接收阴影

        阴影三剑客,放进shader里面就完事了,不用想那么多 

unity相机剔除阴影 unity物体阴影_unity_04

        打开帧调试器看看


unity相机剔除阴影 unity物体阴影_unity相机剔除阴影_05

从摄像机的deepthtexture

unity相机剔除阴影 unity物体阴影_unity相机剔除阴影_06

ShadowMap


unity相机剔除阴影 unity物体阴影_unity相机剔除阴影_07

Scene视角

补充,顶点动画下的投射阴影

        如果顶点动画的状态下投射阴影,阴影的形状是不会改变的,所以我们要自定义投射阴影的pass

        直接上《UnityShader入门精要的代码》

        

Shader "Unity Shaders Book/Chapter 11/Vertex Animation With Shadow" {
	Properties {
		_MainTex ("Main Tex", 2D) = "white" {}
		_Color ("Color Tint", Color) = (1, 1, 1, 1)
		_Magnitude ("Distortion Magnitude", Float) = 1
 		_Frequency ("Distortion Frequency", Float) = 1
 		_InvWaveLength ("Distortion Inverse Wave Length", Float) = 10
 		_Speed ("Speed", Float) = 0.5
	}
	SubShader {
		// Need to disable batching because of the vertex animation
		Tags {"DisableBatching"="True"}
		
		Pass {
			Tags { "LightMode"="ForwardBase" }
			
			Cull Off
			
			CGPROGRAM  
			#pragma vertex vert 
			#pragma fragment frag
			
			#include "UnityCG.cginc" 
			
			sampler2D _MainTex;
			float4 _MainTex_ST;
			fixed4 _Color;
			float _Magnitude;
			float _Frequency;
			float _InvWaveLength;
			float _Speed;
			
			struct a2v {
			    float4 vertex : POSITION;
			    float4 texcoord : TEXCOORD0;
			};
			
			struct v2f {
			    float4 pos : SV_POSITION;
			    float2 uv : TEXCOORD0;
			};
			
			v2f vert(a2v v) {
				v2f o;
				
				float4 offset;
				offset.yzw = float3(0.0, 0.0, 0.0);
				offset.x = sin(_Frequency * _Time.y + v.vertex.x * _InvWaveLength + v.vertex.y * _InvWaveLength + v.vertex.z * _InvWaveLength) * _Magnitude;
				o.pos = UnityObjectToClipPos(v.vertex + offset);
				
				o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
				o.uv +=  float2(0.0, _Time.y * _Speed);
				
				return o;
			}
			
			fixed4 frag(v2f i) : SV_Target {
				fixed4 c = tex2D(_MainTex, i.uv);
				c.rgb *= _Color.rgb;
				
				return c;
			} 
			
			ENDCG
		}
		
		// Pass to render object as a shadow caster
		Pass {
			Tags { "LightMode" = "ShadowCaster" }
			
			CGPROGRAM
			
			#pragma vertex vert
			#pragma fragment frag
			
			#pragma multi_compile_shadowcaster
			
			#include "UnityCG.cginc"
			
			float _Magnitude;
			float _Frequency;
			float _InvWaveLength;
			float _Speed;
			
			struct v2f { 
			    V2F_SHADOW_CASTER;
			};
			
			v2f vert(appdata_base v) {
				v2f o;
				
				float4 offset;
				offset.yzw = float3(0.0, 0.0, 0.0);
				offset.x = sin(_Frequency * _Time.y + v.vertex.x * _InvWaveLength + v.vertex.y * _InvWaveLength + v.vertex.z * _InvWaveLength) * _Magnitude;
				v.vertex = v.vertex + offset;

				TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
				
				return o;
			}
			
			fixed4 frag(v2f i) : SV_Target {
			    SHADOW_CASTER_FRAGMENT(i)
			}
			ENDCG
		}
	}
	FallBack "VertexLit"
}

可以看到,我们在BasePass中改变了顶点着色器中 面板点的位置,在ShadowCasterPass中也要自定义改变顶点的位置,并加上投射阴影所需要的宏,如果不自定义阴影的话,默认调用生成的阴影是不会动的。

不好搞视频啊

就这样,后续再补充