https://gitee.com/yichichunshui/mvpmatrix.git
版本:
16358863357d41e6ba7e48d2b92c39bcb3110ba9
这个函数InitCascade是级联阴影的简化版本,只有一级。
near为摄像机的近平面,far为摄像机的远平面,ar为摄像机的宽高比,fov为摄像机的视口角度。
public void InitCascade(float near, float far, float ar, float fov)
{
//这两行代码是测试代码,看看由摄像机空间下,用摄像机的逆矩阵乘以vector4的点,是否可以得到正确的世界坐标下的点。
Vector4 v = new Vector4(0, 1, 0, 1);
Vector4 worldV = m_testCamera.worldToCameraMatrix.inverse * v;
m_cascadeEnd[0] = near;
m_cascadeEnd[1] = far;
m_ar = ar;
m_fov = fov;
float rad = m_fov / 2 * Mathf.Deg2Rad;
m_tanHalfVFov = Mathf.Tan(rad);
float yn = m_cascadeEnd[0] * m_tanHalfVFov;
float xn = yn * m_ar;
float yf = m_cascadeEnd[1] * m_tanHalfVFov;
float xf = yf * m_ar;
Vector4[] corners = new Vector4[8];
//near face
corners[0] = new Vector4(xn, yn, -m_cascadeEnd[0], 1); //右上
corners[1] = new Vector4(-xn, yn, -m_cascadeEnd[0], 1); //左上
corners[2] = new Vector4(xn, -yn, -m_cascadeEnd[0], 1); //右下
corners[3] = new Vector4(-xn, -yn, -m_cascadeEnd[0], 1); //左下
//Vector4 pw = m_camera.worldToCameraMatrix.inverse * corners[0];
//GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cube);
//go.transform.position = pw;
//far face
corners[4] = new Vector4(xf, yf, -m_cascadeEnd[1], 1); //右上
corners[5] = new Vector4(-xf, yf, -m_cascadeEnd[1], 1); //左上
corners[6] = new Vector4(xf, -yf, -m_cascadeEnd[1], 1); //右下
corners[7] = new Vector4(-xf, -yf, -m_cascadeEnd[1], 1); //左下
float minX = float.MaxValue;
float maxX = float.MinValue;
float minY = float.MaxValue;
float maxY = float.MinValue;
float minZ = float.MaxValue;
float maxZ = float.MinValue;
SetCamera(m_camera.transform.position, m_camera.transform.forward, m_camera.transform.up);
Matrix4x4 cam = GetViewTrans();
Matrix4x4 camInv = cam.inverse;
SetCamera(m_light.transform.position, m_light.transform.forward, m_light.transform.up);
Matrix4x4 lightM = GetViewTrans();
m_lightView = lightM;
Vector4[] corners2 = new Vector4[8];
for (int i = 0; i < 8; ++i)
{
Vector4 vW = camInv * corners[i];
corners2[i] = lightM * vW;
//Vector4 vW2 = m_camera.worldToCameraMatrix.inverse * corners[i];
if (m_points[i] == null)
{
m_points[i] = GameObject.CreatePrimitive(PrimitiveType.Cube);
m_points[i].transform.localScale = Vector3.one;
}
m_points[i].transform.position = vW;
minX = Mathf.Min(minX, corners2[i].x);
maxX = Mathf.Max(maxX, corners2[i].x);
minY = Mathf.Min(minY, corners2[i].y);
maxY = Mathf.Max(maxY, corners2[i].y);
minZ = Mathf.Min(minZ, corners2[i].z);
maxZ = Mathf.Max(maxZ, corners2[i].z);
}
m_minX = minX;
m_maxX = maxX;
m_minY = minY;
m_maxY = maxY;
m_minZ = minZ;
m_maxZ = maxZ;
//m_lightCamera.nearClipPlane = -maxZ;
//m_lightCamera.farClipPlane = -minZ;
//float halfX = (maxX - minX) / 2;
//float halfY = (maxY - minY) / 2;
//m_lightCamera.orthographicSize = (maxX - minX)/ 2;
//m_lightCamera.aspect = halfX / halfY;
//正交矩阵的推导:https://blog.csdn.net/wodownload2/article/details/85069240/
m_lightProj = Matrix4x4.identity;
m_info = new OrthoProjInfo();
m_info.r = maxX;
m_info.l = minX;
m_info.b = minY;
m_info.t = maxY;
m_info.n = minZ;
m_info.f = maxZ;
float dis = m_info.f - m_info.n;
m_lightProj = GetProj(m_info);
m_lightProj = GL.GetGPUProjectionMatrix(m_lightProj, false);
}
Matrix4x4 GetProj(OrthoProjInfo info)
{
Matrix4x4 proj = Matrix4x4.identity;
float l = info.l;
float r = info.r;
float b = info.b;
float t = info.t;
float n = info.n;
float f = info.f;
proj[0, 0] = 2.0f / (r - l); proj[0, 1] = 0.0f; proj[0, 2] = 0.0f; proj[0, 3] = -(r + l) / (r - l);
proj[1, 0] = 0.0f; proj[1, 1] = 2.0f / (t - b); proj[1, 2] = 0.0f; proj[1, 3] = -(t + b) / (t - b);
proj[2, 0] = 0.0f; proj[2, 1] = 0.0f; proj[2, 2] = -2.0f / (f - n); proj[2, 3] = -(f + n) / (f - n);
proj[3, 0] = 0.0f; proj[3, 1] = 0.0f; proj[3, 2] = 0.0f; proj[3, 3] = 1.0f;
return proj;
}
public void SetCamera(Vector3 pos, Vector3 target, Vector3 up)
{
this.pos = pos;
this.target = target;
this.up = up;
}
public Matrix4x4 GetViewTrans()
{
Matrix4x4 CameraTranslationTrans = InitTranslationTransform(-pos.x, -pos.y, -pos.z);
Matrix4x4 CameraRotateTrans = InitCameraTransform(target, up);
Matrix4x4 vTransform = CameraRotateTrans * CameraTranslationTrans;
return vTransform;
}
Matrix4x4 InitTranslationTransform(float x, float y, float z)
{
Matrix4x4 m = Matrix4x4.identity;
m[0, 0] = 1.0f; m[0, 1] = 0.0f; m[0, 2] = 0.0f; m[0, 3] = x;
m[1, 0] = 0.0f; m[1, 1] = 1.0f; m[1, 2] = 0.0f; m[1, 3] = y;
m[2, 0] = 0.0f; m[2, 1] = 0.0f; m[2, 2] = 1.0f; m[2, 3] = z;
m[3, 0] = 0.0f; m[3, 1] = 0.0f; m[3, 2] = 0.0f; m[3, 3] = 1.0f;
return m;
}
Matrix4x4 InitCameraTransform(Vector3 Target, Vector3 Up)
{
Matrix4x4 m = Matrix4x4.identity;
Vector3 N = Target;
N.Normalize();
Vector3 U = Up;
U = Vector3.Cross(U, N);// U.Cross(N);
U.Normalize();
Vector3 V = Vector3.Cross(N, U); //N.Cross(U);
m_lightU = U;
m_lightV = V.normalized;
m_lightN = -N;
m[0, 0] = U.x; m[0, 1] = U.y; m[0, 2] = U.z; m[0, 3] = 0.0f;
m[1, 0] = V.x; m[1, 1] = V.y; m[1, 2] = V.z; m[1, 3] = 0.0f;
m[2, 0] = -N.x; m[2, 1] = -N.y; m[2, 2] = -N.z; m[2, 3] = 0.0f;
m[3, 0] = 0.0f; m[3, 1] = 0.0f; m[3, 2] = 0.0f; m[3, 3] = 1.0f;
return m;
}