Shadow Mapping(阴影映射)
来自CgTutorial的Shadow Mapping实现的基本流程 : 1、首先将整个场景的深度值预先渲染到以光源位置为原点、光线发射方向为观察方向的投影坐标系中,形成深度纹理。 2、再次渲染场景的过程中,将每个片断(像素)变换到前述眼坐标系(观察空间)中,并缩放到[0,1]的范围内以便查询纹理。绘制每个片元时,根据深度纹理距离(ZA)和片元距光源的实际距离(ZB)比较。若ZB>ZA,则需要绘制的片元处于阴影中,采用阴影的颜色着色,否则此片元不在阴影中,进行既定的光照着色。
由于深度纹理尺寸的限制,会让形成的阴影边缘锯齿严重。需要进行模糊处理,甚至是半影处理。
Unity内置的方向光实时阴影技术是Cascaded Shadow Mapping(简称CSM)
Shadow Volume
模型顶点到光源的方向与法线求点积,小于0的挤出即为阴影体积。
上图来自GPU精粹1-第九章有效的阴影体渲染
Projector Shadow
添加Projector组件
[RequireComponent(typeof(Projector))]
public class ProjectorShadow : MonoBehaviour
{
public LayerMask shadowCasterLayer;
private RenderTexture _renderTex;
void Awake()
{
Projector projector = GetComponent<Projector>();
Camera camera = gameObject.AddComponent<Camera>();
camera.cullingMask = shadowCasterLayer;
camera.orthographic = true;
camera.orthographicSize = projector.orthographicSize;
camera.clearFlags = CameraClearFlags.SolidColor;
camera.backgroundColor = new Color(1.0f,1.0f,1.0f,0.0f);
_renderTex = new RenderTexture(512,512,0,RenderTextureFormat.R8);
_renderTex.antiAliasing = 1; // 关闭抗锯齿
_renderTex.filterMode = FilterMode.Bilinear;
_renderTex.wrapMode = TextureWrapMode.Clamp; // wrapmode要设置为Clamp
camera.targetTexture = _renderTex;
camera.SetReplacementShader(Shader.Find("Unlit/ProjectorShadow"),null);
projector.material.SetTexture("_ShadowTex",_renderTex);
}
#if UNITY_EDITOR
void OnApplicationQuit()
{
Projector projector = GetComponent<Projector>();
projector.material.SetTexture("_ShadowTex",null);
}
#endif
}
Shader "Projector/ProjectorShadow" {
Properties {
_ShadowTex ("ShadowTex", 2D) = "black"{}
_FalloffTex ("FallOff", 2D) = "white" {}
}
Subshader {
Tags {"Queue"="Transparent"}
Pass {
ZWrite Off
ColorMask RGB
Blend DstColor Zero
Offset -1, -1
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct v2f {
float4 uvShadow : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 pos : SV_POSITION;
};
float4x4 unity_Projector;
v2f vert (float4 vertex : POSITION)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, vertex);
o.uvShadow = mul (unity_Projector, vertex);
UNITY_TRANSFER_FOG(o,o.pos);
return o;
}
sampler2D _ShadowTex;
sampler2D _FalloffTex;
fixed4 frag (v2f i) : SV_Target
{
fixed4 shadowCol = tex2Dproj (_ShadowTex, UNITY_PROJ_COORD(i.uvShadow));
fixed4 maskCol = tex2Dproj (_FalloffTex, UNITY_PROJ_COORD(i.uvShadow));
fixed ratio = shadowCol.r * maskCol.r;
fixed4 col = fixed4(1,1,1,1) * (1 - ratio);
UNITY_APPLY_FOG_COLOR(i.fogCoord, col, fixed4(1,1,1,1));
return col;
}
ENDCG
}
}
}
参考资料: