GetGPUProjectionMatrix

http://richbabe.top/2018/06/27/%E7%94%A8Unity%E5%AE%9E%E7%8E%B0Shadow-Map/
https://blog.csdn.net/liuwumiyuhuiping/article/details/52524317

实验1:
proj = GL.GetGPUProjectionMatrix(proj2, true);
分别作了,不用gl;
用,第二个参数为true;
用,第一个参数为false;
结果如下:

在这里插入图片描述

第二个bug的解决:使用commandbuffer的时候,每帧设置rt,清除rt的颜色,绘制,清除命令四个步骤
这样在帧调试器下,就可以进行调试了,否则点不到正常绘制的物体。
具体如下:

m_cb.SetRenderTarget(m_selfShadowRT);
m_cb.ClearRenderTarget(true, true, Color.clear, 1.0f);
Graphics.ExecuteCommandBuffer(m_cb);
m_cb.Clear();

终于搞懂了这个函数的意思:

using UnityEngine;

public class GetGPUProjectionMatrix : MonoBehaviour
{
    private int w = 2;
    private int h = 2;
    private int n = 4;
    private int f = 60;
    private float z = -10;
    void Start()
    {
        Matrix4x4 m = Matrix4x4.Ortho(-w, w, -h, h, n, f);
        Debug.LogError(m);
        Vector3 p = m.MultiplyPoint3x4(new Vector3(0, 0, z));
        Debug.LogError(p);
        Matrix4x4 mm = GL.GetGPUProjectionMatrix(m, true);
        Debug.LogError(m.inverse * mm);
    }
}

在这里插入图片描述
那个GL.GetGPUProjectionMatrix函数,是对原始的opengl的p矩阵,做了红色矩阵的操作,然后转换到1到0的范围。
推导全靠猜测,用转换后的矩阵,然后得到其逆矩阵,最后加上拍脑袋,果然最后构建出了这个红色矩阵。经过验证是正确的。
并且是如果传入false的话,只是y不反转。传入true,则对y进行翻转操作。

我的验算过程:
在这里插入图片描述

下面我们再来验证下这个结论是否正确。
在这里插入图片描述
此时的宽高比为2:1,这里的size=2,表示view视口的高度一半为2,所以宽度一半为4。
摄像机是正交投影,按照opengl的透视矩阵公式得到的透视矩阵应该为:
在这里插入图片描述
这个计算处理的矩阵为:
在这里插入图片描述
此时,程序构建的正交矩阵为:

public class VerifyGL : MonoBehaviour
{
    private void Start()
    {
        int w = 4;
        int h = 2;
        int n = 1;
        int f = 100;
        Matrix4x4 m = Matrix4x4.Ortho(-w, w, -h, h, n, f);
        Debug.LogError(m);
    }
}

在这里插入图片描述
可见我们的推测是正确的。

我们在看看view矩阵是多少:

Matrix4x4 m2 = Camera.main.worldToCameraMatrix;
Debug.LogError(m2);

在这里插入图片描述
这个为啥是这样呢?因为摄像机的right=(1,0,0) up=(0,1,0),而forward是z的负方向,所以是(0,0,-1)。

我们自己尝试构建vp矩阵为:
在这里插入图片描述
我们看看这个和unity中的矩阵是否相同呢?
在这里插入图片描述
很遗憾,不相同,那么我们用之前的那个红色矩阵乘下之后呢?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class VerifyGL : MonoBehaviour
{
    private void Start()
    {
        int w = 4;
        int h = 2;
        int n = 1;
        int f = 100;
        Matrix4x4 m = Matrix4x4.Ortho(-w, w, -h, h, n, f);
        Debug.LogError(m);

        Matrix4x4 m2 = Camera.main.worldToCameraMatrix;
        Debug.LogError(m2);

        Matrix4x4 m3 = m * m2;
        Debug.LogError(m3);

        Matrix4x4 m4 = Matrix4x4.identity;
        m4[1, 1] = -1;
        m4[2, 2] = -0.5f;
        m4[2, 3] = -100 - 0.5f * 1; //-f-0.5n
        Matrix4x4 m5 = (m * m4) * m2; //m为原始透视矩阵,m4为红色矩阵,m2为view矩阵
        Debug.LogError(m5);
    }
}

在这里插入图片描述
可以看到,这个y是相反的,我们记得,使用GL.GetGPUProjectionMatrix(m, false);
第二个参数为false,则y不进行反转,所以此时红色的矩阵m[1,1]=1,不用等于-1即可。
即:

Matrix4x4 m4 = Matrix4x4.identity;
//m4[1, 1] = -1;
m4[2, 2] = -0.5f;
m4[2, 3] = -100 - 0.5f * 1; //-f-0.5n
Matrix4x4 m5 = (m * m4) * m2; //m为原始透视矩阵,m4为红色矩阵,m2为view矩阵
Debug.LogError(m5);

综上:
1、当 GL.GetGPUProjectionMatrix(m, false);则是相当于对m矩阵乘以下面矩阵的操作:
在这里插入图片描述
2、当 GL.GetGPUProjectionMatrix(m, true);则是相当于对m矩阵乘以下面矩阵的操作:
在这里插入图片描述
3、unity默认是GL.GetGPUProjectionMatrix(m, false);即,y不反正,但是z映射到了1到0范围。
这个红色矩阵就是将视空间的z,映射到屏幕空间的1到0范围。
如果不进行这个GetGPUProjectionMatrix操作,则对于opengl来说视空间的z映射到了-1到1之间。

下面讨论的一个问题是:片元着色器是否需要透视除法的操作。

// Tranforms position from object to homogenous space
inline float4 UnityObjectToClipPos(in float3 pos)
{
#if defined(STEREO_CUBEMAP_RENDER_ON)
    return UnityObjectToClipPosODS(pos);
#else
    // More efficient than computing M*VP matrix product
    return mul(UNITY_MATRIX_VP, mul(unity_ObjectToWorld, float4(pos, 1.0)));
#endif
}

由此可以看出UnityObjectToClipPos,之后,返回的坐标其w分量还是z,即在view空间的z值。
那么需要透视除法,之后才能得到NDC坐标。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值