计算机图形学基础(四) 观察2
2016-06-11 09:16
441 查看
透视投影
上一小节 观察1 写的很多了,这节就省略了很多定义之类的东西。(1)简单的透视投影
后面和前面平行,这里主要讨论这一种情况,大多数物理成像设备都属于这一种情况,包括人类视觉系统和简单的照相机。更一般的情况是不平行的。
空间中的一点(x,y,z)沿着一条投影线被投影到(Xp,Yp,Zp)。所有的投影线都通过原点。因为投影平面和z轴垂直,所以Zp=d;因为照相机指向z轴负方向,所以投影平面位于z轴负方向一侧(可以看着观察1里的透视投影图加以理解)。
(a)三维视图;(b)俯视图;(c)侧视图
从b图可以看出
联系c图可以推导出
下面讨论简化这个变换(我就直接写结果了)
矩阵M把点
变换成
让q除以w分量(vec4的4个分量分别为xyzw)
就可以作为如下流水线
模–视变换—–投影变换——-透视除法
(2)OpengGL中的透视投影
视见体
前裁剪面和后裁剪面
COP位于照相机标架的原点。
下面的函数用于指定透视投影
mat4 Frustum( const GLfloat left, const GLfloat right, const GLfloat bottom, const GLfloat top, const GLfloat zNear, const GLfloat zFar )
该函数参数与Ortho的参数非常相似。
尽管在几乎所有的应用程序中都有far>near>0,但只要near!=far,由这些参数确定的投影变换矩阵就是有效的,不过在投影中心(原点)后面的对象所成的像将是倒立的,如果该对象位于近裁面和远裁面之间的话。
通过视角或者视域来指定视见体。
fovy是裁减体的底面和顶面之间的夹角。
aspect是投影平面的宽高比(w/h)。
用下面函数利用视域指定视见体:
mat4 Perspective( const GLfloat fovy, const GLfloat aspect, const GLfloat zNear, const GLfloat zFar)
(3)透视投影变换矩阵
对于透视投影,采用和平行投影相似的方法。
透视投影的规范化
这里同样直接写推理过程了。
考虑下面的矩阵
可以看出d=-1,z改变
它把
变换成
x’ = x;
y’ = y;
z’ = αz+β;
w’ = -z;
用w’去除得到
x” = -(x/z);
y” = -(y/z);
z” = -(α+β/z)
w” = 1;
由此,原来视见体的侧面变换为(参考前面的简单透视):
如果令
那么z=-near映射成z”=-1。
z=-far映射成z”=1。
矩阵N称为透视规范化变换矩阵
效果如上图。
z” = -(α+β/z)可知:它保持了深度的大小关系。
如果z1>z2那么z”1>z”2。
补充:在规范化视见体中仍然可以进行隐藏面消除,不过由于深度缓存的深度分辨率有限,透视规范化变换的非线性可能导致数值精度问题。虽然原来位于z=-1的投影平面被N变换成了平面z”=β-α,但这不会有什么不良后果,因为在N之后还要进行一个正投影。
OpenGL中的透视投影变换
Frustum函数没有限制视见体一定是对称的棱台。
这里首先要把上图所示的棱台视见体变换为上上图那样的视见体(对称视见体的侧面与投影平面的夹角为45度)。这和把斜平行投影转化为正交投影类似。
首先通过错切变换把不对称的棱台转化为对称棱台。
经过错切变换后,点( (left+right)/2, (top+bottom)/2, -near)应位于(0, 0, -near)。
错切后的棱台视见体由下面这几个平面围成
接下来通过缩放把这个棱台的侧面变为
但不改变前裁剪面和后裁剪面。
所需缩放矩阵为
S[-2*near/(right-left), -2*near/(top-bottom), 1]。
为了使裁剪面位于z=-1和z=1,应用上面说过的N。
最后得到的投影变换矩阵如下
由此看下面Frustum的代码
mat4 Frustum( const GLfloat left, const GLfloat right, const GLfloat bottom, const GLfloat top, const GLfloat zNear, const GLfloat zFar )
{
mat4 c;
c[0][0] = 2.0*zNear/(right - left);
c[0][2] = (right + left)/(right - left);
c[1][1] = 2.0*zNear/(top - bottom);
c[1][2] = (top + bottom)/(top - bottom);
c[2][2] = -(zFar + zNear)/(zFar - zNear);
c[2][3] = -2.0*zFar*zNear/(zFar - zNear);
c[3][2] = -1.0;
c[3][3] = 0.0;
return c;
}
为了得到另外一个透视观察函数Persective(fovy, aspect, near, far)的投影变换矩阵,我们首先利用矩阵P中的对称性得到
left = -right;
bottom = -top;
再利用简单三角学可以得到
top = near*tan(fovy);
right = top*aspect;
这样可以把矩阵p简化为:
下面是Perspective代码:
mat4 Perspective( const GLfloat fovy, const GLfloat aspect, const GLfloat zNear, const GLfloat zFar)
{
GLfloat top = tan(fovy*DegreesToRadians/2) * zNear;
GLfloat right = top * aspect;
mat4 c;
c[0][0] = zNear/right;
c[1][1] = zNear/top;
c[2][2] = -(zFar + zNear)/(zFar - zNear);
c[2][3] = -2.0*zFar*zNear/(zFar - zNear);
c[3][2] = -1.0;
c[3][3] = 0.0;
return c;
}
后面还有:
隐藏面消除
显示网格
多边形偏移
在场景中漫游
投影和阴影
这些都以后有空了就写。相关文章推荐
- 使用 Libki 来管理公共用户访问计算机
- 微型计算机的始祖:Altair 8800
- 通过手机、电脑远程开关机,Windows和linux机手机,电脑相互控制
- C#实现图形位置组合转换的方法
- php实现用手机关闭计算机(电脑)的方法
- C#实现判断图形文件格式的方法
- C#实现图形路径变换的方法
- 用IE重起计算机或者关机的示例代码
- 一张图告诉你计算机编程语言的发展历史
- php生成图形验证码几种方法小结
- CentOS的图形安装及初始环境设置教程
- 计算机科学中32个常用的基础算法
- C#实现图形区域组合操作的方法
- php实现图形显示Ip地址的代码及注释
- 不能在本地计算机启动 apache2.2解决方法
- Java Web开发之图形验证码的生成与使用方法
- 基于Echarts 3.19 制作常用的图形(非静态)
- android中图形图像处理之drawable用法分析
- Android编程开发之在Canvas中利用Path绘制基本图形(圆形,矩形,椭圆,三角形等)
- Android开发之图形图像与动画(五)LayoutAnimationController详解