渲染管线——视图坐标与相机模型

3D游戏中的所有物体都是围绕着3D相机渲染的,这表明我们仅仅把物体转换到世界坐标系是不够的,还需要设定一个抽象的相机,来观察我们整个3D世界。

UVN相机模型

相机很像是模拟人的眼睛:

视空间

其中视平面就是类似人的视网膜,我们在现实生活中看到的物体最终会被我们的大脑“渲染”到我们的视网膜上面。
所有位于近裁剪面和远裁剪面这个椎体(称为视椎体,视椎体描述了视空间)内的物体可以被我们观察到,且距离我们越远看到的物体会更小。所有位于视椎体之外的物体,都用通过一定的算法才裁剪。

UVN坐标系统

UVN相机模型是使用三个向量来构建自身的一种模型,这种模型构建的相机非常便于实现跟随和漫游的功能。

U : 相机的右手边方向的向量
V : 相机的上方的向量
N : 相机注视的向量

这里写图片描述

其中注视点是某个相机被观察的对象,我们需要用这些信息来构建出视空间坐标系,在视空间坐标系中,相机位于原点,前方是Z轴的正方向,也就是上面的那张图。

原理如下 :

(1)model.position - camrea.postion = N N归一化后得到Z轴
(2)crossproduct(V,N) = U U归一化之后得到X轴
(3)crossproduct(N,U) = V V归一化之后得倒Y轴

要将标准XYZ坐标系下的(x,y,z)变换为UVN(视图坐标系)系统中的点,只需要分别计算(x,y,z)与u,v,n的点积即可,我们将三次点积运算并到一个矩阵中:

[ux vx nx 0]
[uy vy ny 0]
[uz vz nz 0]
[0 0 0 1]

Camrea的结构如下:

平移相机

上述的UVN坐标系的构建是不完整的,还差关键一步,将相机平移到(0,0,0)的位置。
这很简单,我们假设Camrea在世界坐标下的位置为(camreax,cameray,cameraz)
如果将相机移到世界坐标(0,0,0)处,要确保位于(worldx,worldy,worldz)的物体相对于相机的位置不变(这样才可以确保被观察到的物体在相机移动后没有发生改变),那么必须要移动物体。
实际上,只需要简单的将物体移到(worldx-camreax,worldy-cameray,worldz-cameraz),那么物体和相机的距离、大小等都没有发生改变。
(简单说明一下,Camrea被移动到(0,0,0)处即每个分量做简单的平移(-camerax,-carmeray,-camreaz)即可,那么物体也要做相应的平移变换)。

最后,根据上述理论,我们做一个基于UVN模型的Camrea类,它应当具备的功能:
(1)可以构建UVN坐标系
(2)能描述视椎体
(3)能够给出WorldToView的坐标变换矩阵

    public class Camera
    {
        public Vector3D pos;//相机位置
        public Vector3D lookAt;//相机注视的位置
        public Vector3D up;//视空间的Up方向

        public float fov;//field of view 视域
        public float aspect; //宽高比
        public float zn;//近平面
        public float zf;//远平面

        public static Matrix4x4 GetView(Vector3D pos, Vector3D lookAt, Vector3D up)
        {//获取WorldToVIew的变换矩阵

            //设定UVN系统的xyz轴
            Vector3D axisZ = (lookAt - pos).Normalize();
            Vector3D axisX = Vector3D.Cross(up, axisZ).Normalize();
            Vector3D axisY = Vector3D.Cross(axisZ, axisX).Normalize();

            Matrix4x4 r = new Matrix4x4(axisX.x, axisY.x, axisZ.x, 0,
                                        axisX.y, axisY.y, axisZ.y, 0,
                                        axisX.z, axisY.z, axisZ.z, 0,
                                        0, 0, 0, 1);
            Matrix4x4 t = MathUntil.GetTranslate(-pos.x, -pos.y, -pos.z);
            return t * r;
            /*
            这样计算出的UVN坐标是右手系的,没有问题,至于原因还要在齐次剪裁那里讲解
            */
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值