参考:
http://fabiensanglard.net/shadowmapping/index.php
https://learnopengl-cn.readthedocs.io/zh/latest/05 Advanced Lighting/03 Shadows/01 Shadow Mapping/
https://www.jianshu.com/p/17ccdd7c0888
不知为啥直接照抄代码实现不了 我用到unity版本是2018.4.1 不知道是不是版本的问题
先上个图吧
更具自己的理解加网上的代码,差不多是这种效果
生成深度图
存下深度数据
Shader "Shadow/DeapthTextureShader"
{
SubShader
{
Tags { "RenderType"="Opaque" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 depth : TEXCOORD1;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
// o.depth = o.vertex.zw;
o.depth = COMPUTE_DEPTH_01;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// float depth = i.depth.x / i.depth.y;
float depth = i.depth;
// fixed4 col = EncodeFloatRGBA(depth);
fixed4 col = EncodeFloatRGBA(min(depth, 0.9999991));
return col;
}
ENDCG
}
}
}
阴影贴图
Shader "Shadow/ShadowMapNormal"
{
Properties
{
_MainTex("Texture", 2D) = "white" {}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
struct v2f {
float4 pos: SV_POSITION;
float4 worldPos: TEXCOORD0;
float4 ShadowCoord : TEXCOORD3;
float2 depth : TEXCOORD4;
};
float4x4 _ProjectionMatrix;
sampler2D _DepthTexture;
float _ShadowBias;
v2f vert(appdata_full v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
// 通过投影矩阵变换到light空间(摄像机为原点)
o.ShadowCoord = mul(_ProjectionMatrix, mul(unity_ObjectToWorld, v.vertex));
// 这一步不太懂
o.ShadowCoord.z = -(mul(_WorldToViewMatrix, mul(unity_ObjectToWorld, v.vertex)).z * 1/200.0);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
fixed4 col = fixed4(1,1,1,1);
float planeDepth = i.ShadowCoord.z;
fixed4 dcol = tex2Dproj(_DepthTexture, i.ShadowCoord);
float boxDepth = DecodeFloatRGBA(dcol);
float shadow = planeDepth + 0.0025 > boxDepth ? 0.5 : 1.0;
return col * shadow;
}
ENDCG
}
}
}
用代码赋值 获取投影矩阵啥的
///
/// 创建depth相机
///
///
public class DepthTextureCamera : MonoBehaviour
{
Camera _camera;
RenderTexture _rt;
// 光照的角度
public Transform lightTrans;
Matrix4x4 bias = new Matrix4x4();
[Range(0, 0.1f)]
public float ShadowBias = 0.005f;
[Range(1, 2000)]
public int UVLightSize = 500;
[Range(1, 10)]
public float OrthographicSize = 10;
void Start()
{
_camera = new GameObject().AddComponent<Camera>();
_camera.name = "DepthCamera";
_camera.depth = 2;
_camera.clearFlags = CameraClearFlags.SolidColor;
_camera.backgroundColor = Color.white;
_camera.farClipPlane = 100;
_camera.cullingMask = LayerMask.GetMask("Player");
_camera.aspect = 1;
_camera.transform.position = this.transform.position;
_camera.transform.rotation = this.transform.rotation;
_camera.transform.parent = this.transform;
_camera.orthographic = true;
_camera.orthographicSize = OrthographicSize;
// 0.5 * x + 0.5 [-1, 1] => [0, 1]
bias.SetRow(0, new Vector4(0.5f, 0, 0, 0.5f));
bias.SetRow(1, new Vector4(0, 0.5f, 0, 0.5f));
bias.SetRow(2, new Vector4(0, 0, 0.5f, 0.5f));
bias.SetRow(3, new Vector4(0, 0, 0, 1));
_rt = new RenderTexture(1024, 1024, 0);
_rt.filterMode = FilterMode.Point;
_camera.targetTexture = _rt;
_camera.SetReplacementShader(Shader.Find("Shadow/DeapthTextureShader"), "RenderType");
}
void Update()
{
_camera.orthographicSize = OrthographicSize;
this.transform.eulerAngles = lightTrans.eulerAngles;
_camera.Render();
Matrix4x4 project = _camera.projectionMatrix;
Matrix4x4 worldToView = _camera.worldToCameraMatrix;
Matrix4x4 mtx = project * worldToView;
mtx = bias * mtx;
Shader.SetGlobalMatrix("_ProjectionMatrix", mtx);
Shader.SetGlobalMatrix("_WorldToViewMatrix", worldToView);
Shader.SetGlobalTexture("_DepthTexture", _rt);
Shader.SetGlobalFloat("_ShadowBias", ShadowBias);
Shader.SetGlobalFloat("UVLightSize", UVLightSize);
Shader.SetGlobalVector("_EyePos", new Vector4(
_camera.transform.position.x,
_camera.transform.position.y,
_camera.transform.position.z, 0));
}
}