void GLRenderSystemCommon::_makeOrthoMatrix(const Radian& fovy, Real aspect,
                                               Real nearPlane, Real farPlane,
                                               Matrix4& dest, bool forGpuProgram)
    {
        Radian thetaY(fovy / 2.0f);
        Real tanThetaY = Math::Tan(thetaY);

        // Real thetaX = thetaY * aspect;
        Real tanThetaX = tanThetaY * aspect; // Math::Tan(thetaX);
        Real half_w = tanThetaX * nearPlane;
        Real half_h = tanThetaY * nearPlane;
        Real iw = 1.0f / half_w;
        Real ih = 1.0f / half_h;
        Real q;
        if (farPlane == 0)
        {
            q = 0;
        }
        else
        {
            q = 2.0f / (farPlane - nearPlane);
        }
        dest = Matrix4::ZERO;
        dest[0][0] = iw;
        dest[1][1] = ih;
        dest[2][2] = -q;
        dest[2][3] = -(farPlane + nearPlane) / (farPlane - nearPlane);
        dest[3][3] = 1;
    }
    void GLRenderSystemCommon::_makeProjectionMatrix(const Radian& fovy, Real aspect,
                                                    Real nearPlane, Real farPlane,
                                                    Matrix4& dest, bool forGpuProgram)
    {
        Radian thetaY(fovy / 2.0f);
        Real tanThetaY = Math::Tan(thetaY);

        // Calc matrix elements
        Real w = (1.0f / tanThetaY) / aspect;
        Real h = 1.0f / tanThetaY;
        Real q, qn;
        if (farPlane == 0)
        {
            // Infinite far plane
            q = Frustum::INFINITE_FAR_PLANE_ADJUST - 1;
            qn = nearPlane * (Frustum::INFINITE_FAR_PLANE_ADJUST - 2);
        }
        else
        {
            q = -(farPlane + nearPlane) / (farPlane - nearPlane);
            qn = -2 * (farPlane * nearPlane) / (farPlane - nearPlane);
        }

        // NB This creates Z in range [-1,1]
        //
        // [ w   0   0   0  ]
        // [ 0   h   0   0  ]
        // [ 0   0   q   qn ]
        // [ 0   0   -1  0  ]

        dest = Matrix4::ZERO;
        dest[0][0] = w;
        dest[1][1] = h;
        dest[2][2] = q;
        dest[2][3] = qn;
        dest[3][2] = -1;
    }
	//-----------------------------------------------------------------------
	void Frustum::calcProjectionParameters(Real& left, Real& right, Real& bottom, Real& top) const
	{
		if (mCustomProjMatrix)  //自定义投影矩阵
		{
			// 转换剪裁平面角到相机空间中
			Matrix4 invProj = mProjMatrix.inverse();   //对透视投影矩阵求逆得观察矩阵
			Vector3 topLeft(-0.5f, 0.5f, 0.0f);  //左上角
			Vector3 bottomRight(0.5f, -0.5f, 0.0f); //右下角

			topLeft = invProj * topLeft;
			bottomRight = invProj * bottomRight;

			left = topLeft.x;
			top = topLeft.y;
			right = bottomRight.x;
			bottom = bottomRight.y;

		}
		else
		{
			//视锥体手动扩展设置
			if (mFrustumExtentsManuallySet)
			{
				left = mLeft;
				right = mRight;
				top = mTop;
				bottom = mBottom;
			}
			// 计算通用的投影参数
			else if (mProjType == PT_PERSPECTIVE) //透视投影
			{
				Radian thetaY(mFOVy * 0.5f);  //thetaY= mFovy的一半
				Real tanThetaY = Math::Tan(thetaY);
				Real tanThetaX = tanThetaY * mAspect;
				//用于3d立体显示参数
				Real nearFocal = mNearDist / mFocalLength;
				Real nearOffsetX = mFrustumOffset.x * nearFocal;
				Real nearOffsetY = mFrustumOffset.y * nearFocal;
				Real half_w = tanThetaX * mNearDist;
				Real half_h = tanThetaY * mNearDist;

				left = -half_w + nearOffsetX;
				right = +half_w + nearOffsetX;
				bottom = -half_h + nearOffsetY;
				top = +half_h + nearOffsetY;

				mLeft = left;
				mRight = right;
				mTop = top;
				mBottom = bottom;
			}
			else
			{
				//正交投影
				// 不知道怎样应用视锥体偏移到正交投影相机,这里就无效化
				Real half_w = getOrthoWindowWidth() * 0.5f;
				Real half_h = getOrthoWindowHeight() * 0.5f;

				left = -half_w;
				right = +half_w;
				bottom = -half_h;
				top = +half_h;

				mLeft = left;
				mRight = right;
				mTop = top;
				mBottom = bottom;
			}

		}
	}