平行光阴影中的view和project矩阵的推导

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;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值