害,今天就把阴影看了吧,和上一篇的主题不太搭调,就新开了一个文章,哈哈哈哈
ShadowMap的原理
突然翻上半年听games202课程闫老师讲的ShadowMap的知识点了。
大致就是说从光源的方向看物体生成一张阴影映射纹理(shadowMap)
差不多长这个样子
然后捏,我们摄像机看到的一些物体在世界坐标下的位置在shadowmap中查找,如果深度大于shadowMap中的呢,那肯定就是在阴影中了啊!反正大概就是个这么意思了啦,可能不是很准确。
阴影在Unity中
在unity中物体可以选择是否投射阴影或者是否接收阴影这种选择,如果你选择接收阴影,那你的物体就得采样shadowmap,如果你选择投射阴影,那你这个物体就要加入shadowmap的计算中去。
投射阴影
在unity中专门用了一个pass并且LightmModel 为ShadowCaster来投射阴影,当我们使用shadowMap的这个阴影技术的时候,就会启动这个pass。这个pass很多时候都在FallBack语句中,然后一直回调,直到调用到vertexLit。如果是透明物体的阴影,你就要使用Transparent/Cutout/VertexLit。当然你也可以自己在shader里面写这个pass。
接收阴影
阴影三剑客,放进shader里面就完事了,不用想那么多
打开帧调试器看看
从摄像机的deepthtexture
ShadowMap
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中也要自定义改变顶点的位置,并加上投射阴影所需要的宏,如果不自定义阴影的话,默认调用生成的阴影是不会动的。
不好搞视频啊
就这样,后续再补充