您的位置:首页 > 其它

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

2017-05-22 16:39 351 查看
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坐标是右手系的,没有问题,至于原因还要在齐次剪裁那里讲解
*/
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  3d 游戏 渲染管线