笔者:i_dovelemon

资源:CSDN

日期:2014 / 9 / 30

主题:View Frustum, Plane, View Matrix, Perspective Projection Matrix

引言

在3D图形学中,一种优化的手法,叫做物体剔除(Object Culling)。

这种技术的提出是基于这种策略:我们不希望将不存在View Frustum里面的物体送往流水线中进行处理。

尽管,你可能会说,如今的图形卡都已近支持了三角形剔除的技术。可是,不要忘了流水线的步骤。

我们是先进行Vertex Processing。然后才进行Geometry Processing。

而图形卡对三角形的剔除是在Geometry
Processing这个阶段进行的。

也就是说,即使可以剔除它们,我们依旧要在Vertex Processing中对这些将来须要丢弃的顶点进行Vertex Processing处理。而我们知道。Vertex Processing这个阶段往往会进行坐标变换,光照计算等等费时的操作。所以,假设可以在Vertex Processing之前。也就是在Application阶段,在我们的CPU中将这些根本不须要处理的物体剔除的话。会大大的提高程序的效率。而想要将物体剔除,我们就须要知道这个物体是否在View Frustum中。

而为了推断这个条件,我们就须要确定构成View
Frustum的6个平面的方程。

所以。本篇文章,就向大家讲述,怎样获取View Frustum的6个平面方程。

推理过程

想要获取View Frustum的6个面的方程。那么我们就须要知道,我们是怎么定义View Frustum的。

在我的博客栏目中。有一篇文章基本3D变换。在这篇文章中,我们知道,我们使用NearZ。 FarZ, Fov和Aspect这几个值来定义了View
Frustum。

而这些值都保存在Projection Matrix中。所以,突破口就在这个Projection Matrix里面。

我们来回想下上面的文章。

基本3D变换这篇文章中讲述了主要的3D变换之World Transform, View Transform和Projection Transform。而且费了非常大的篇幅证明了Projection Matrix的作用以及它的推导过程。从中我们知道,Projection
Matrix的作用是将View Frustum中的顶点。变换到一个Cubic空间中去。

这个空间的X的范围为[-1,1],Y轴的范围为[-1,1]。Z轴的范围为[0,1]。

那么,也就是说。原来View Frustum的6个平面,在经过了变换之后。变成了Cubic的6个面。

那么,我们是否能通过这6个面,来获取还原原来的View Frustum的6个面了。

答案是肯定的。可是我们并非直接获取到6个平面的方程。而是使用一种等价的方式推导出这6个面的。以下我们来看下。

我们知道,在世界坐标空间View Frustum中的一个点S,经过了M = ViewMatrix * ProjMatrix变换之后,就变换到了Cubic的空间中去了。所以。我们能够得到例如以下的结论:

T = S * M   (1)

变换后的T是一个齐次坐标。它的w分量不再是1,我们来看下T.w究竟等于什么。

在世界坐标空间中。顶点的w值都为1。所以与View Matrix相乘之后。它的w变成了 :

w' = [x,y,z,w] * [ViewM.03, ViewM.13, ViewM.23, ViewM.33] = [x,y,z,w] * [0, 0, 0, 1] = w = 1 (2)

再与Proj Matrix相乘之后,w‘变成了:

w'' = [x',y',z',w'] * [ProjM.03, ProjM.13, ProjM.23, ProjM.33] = [x, y, z , w'] * [ 0, 0, 1, 0] = z' (3)

也就是说,顶点在经过了View Transform 和 Projection Transform之后,它的w分量变成了顶点在相机空间中的z值。

我们将T化成U。当中U.w = 1。而如今的U就处在Cubic空间中。

我们知道Cubic空间的X范围为[-1,1],那么就是说:

-1 <= U.x <= T.x / T.w (4)

通过公式(3),我们知道T.w = z'。即等于在相机空间中的z值。

而View Frustum中的顶点在相机坐标空间中的z值都是大于0的。所以又能够得到例如以下的公式:

T.x + T.w >= 0 (5)

通过公式(1),我们能够知道例如以下:

T.x = S * Mcol0 , T.w = S * Mcol3 (6)

将公式(6)带入公式(5)。得到例如以下:

S*Mcol0 + S*Mcol3 >= 0  ==>  S * (Mcol0 + Mcol3) >= 0 (7)

因为Mcol0和Mcol3都是一个向量,他们的和也能够用一个向量N来表示,所以就变成了

S * N >= 0  ==> S.x * N.x + S.y * N.y + S.z * N.z + S.w * N.w >= 0 ==> S.x*N.x + S.y*N.y + S.z*N.z + N.w >= 0 (8)

我们来回忆下,在DirectX中,平面是怎样保存的。在DirectX中,D3DXPLANE中有两个属性来唯一确定。它们各自是平面的法向向量N'。以及原点到这个平面的有向距离d来表示。

假设一个点S’在平面的正半空间中,那么我们将这个点带入到DirectX的平面方程中:

S' * N' + d > 0 ==> S'.x*N'.x + S'.y*N'.y + S'.z*N‘.z + d >= 0 (9)

读者自己比对下公式(8)和公式(9)。就会发现,它们是惊人的相似。仅仅只是这里的d,变成了N.w而已。所以。我们全然能够将公式(8)中的N和N.w抽取出来。作为D3DXPLNE中的N和d,来构成一个平面。而这个平面就是View Frustum的Left平面。在上面,我们已经如果了U.x>=-1。也就是说,这里的情况下,得到的Left平面,它的法向向量是指向View Frustum里面的。如果想要指向外面仅仅要将公式(8)中的N反向就可以。

相同的方法,我们能够推导出其它几个面的方程。

总结

通过上面的推导,我们就能够得到例如以下的结论:

Left平面: 0 =( Mcol3 + Mcol0) * [x,y,z,w]

Right平面: 0 = (Mcol3 - Mcol0) * [x,y,z,w]

NearZ平面: 0 = Mcol2 * [x,y,z,w]

FarZ平面: 0 = (Mcol3 - Mcol2) * [x,y,z,w]

Top平面: 0 = (Mcol3 - Mcol1) * [x,y,z,w]

Bottom平面:  0 = (Mcol3 + Mcol1) * [x,y,z,w]

只是注意,上面的平面都是没有进行归一化的平面。使用的时候。最好使用D3DXNormalizePlane进行归一化操作。

好了,今天就到这里。

下一篇文章,会向大家讲述。怎样进行检測,推关闭对象是否View Frustum外用。

版权声明:本文博主原创文章,博客,未经同意不得转载。

得到View Frustum的6飞机的更多相关文章

  1. 【翻译】View Frustum Culling --3 Clip Space Approach – Extracting the Planes

    3.使用裁剪空间的方法提取平面 上一篇中,我们讨论了通过几何的方法提取视锥体的六个片面.在这一篇中,我们继续讨论通过裁剪空间的方法来提取视锥体的平面. 假设现在在世界坐标系中有一点p=(x,yz,1) ...

  2. 【翻译】View Frustum Culling --2 Geometric Approach – Extracting the Planes

    在上一篇中,我们知道了视锥体的形状,并且也确定了我们进行裁剪时的步骤.那我们接下来要走的就是确定视锥体的六个平面: near, far, top, bottom, left and right 2.计 ...

  3. 【翻译】 View Frustum Culling --1 View Frustum’s Shape

    这是一些列来自lighthouse3d的视锥体裁剪教程.旨在学习总结,及便于查阅. 1.视锥体的形状 在OpenGL中,透视投影是由两个函数定义的gluPerspective和gluLookAt.我们 ...

  4. 简单的Viewing Frustum Culling

    Viewing Frustum Culling是图形绘制流水线中,将不可见物体(即不在视锥体内的物体)提前剔除的操作. 在实践中,精确判断物体的可见性开销较大,因而通常用物体包围球或包围盒与视锥体(平 ...

  5. JavaScript—飞机大战2版

    前面的思路对了  BUG 出在了计时器和没有加判断页面是否存在元素 <!DOCTYPE html> <html lang="en"> <head> ...

  6. JavaScript—飞机大战

    今天来写个游戏,飞机大战 1,布局 2,思路 1,动态创建自己的飞机 让它在规定的区域,跟着鼠标运动. 2,在自己飞机的上方,间隔1s生成子弹.子弹往上移动 当top:0 子弹消失 3,每隔1s 产生 ...

  7. Forward+ Rendering Framework

    近几天啃各种新技术时又一个蛋疼的副产品...额,算是把AMD的Forward+ Sample抄了一遍吧. 其实个人感觉这个AMD大肆宣传的Forward+跟Intel很早之前提的Tiled-Based ...

  8. [比较老的文章]三维渲染引擎 OGRE 与 OSG 的比较综述

    1 .引言随着计算机可视化.虚拟现实技术的飞速发展,人们对实时真实感渲染以及场景复杂度提出了更高的要求.传统的直接使用底层图形接口如OpenGL.DirectX开发图形应用的模式越来越暴露出开发复杂性 ...

  9. 【OPENGL】第三篇 着色器基础(一)

    在这一章,我们会学习什么是着色器(Shader),什么是着色器语言(OpenGL Shading Language-GLSL),以及着色器怎么和OpenGL程序交互. 首先我们先来看看什么叫着色器. ...

随机推荐

  1. hdu1267(递推)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1267 题意:假定一个字符串由m个H和n个D组成,从左到右扫描该串,如果字符H的累计数总是不小于字符D的 ...

  2. Eclipse中的Maven项目报Unbound classpath variable错误

    今天更新了最新版的Eclipse luna 4.4版本号,svn更新了项目后,系统一直报错,经查看在Problems窗体中发现一堆错误.提演示样例如以下:     Unbound classpath ...

  3. 简单的java mail发送邮件实例

    mail.jar ,commons-email-X.X.jar ,activation.jar ,log4j.jar  这四个jar,放进项目里 下载地址 http://www.oracle.com/ ...

  4. XSS学习笔记(一个)-点击劫持

    所谓XSS这个场景被触发XSS地方,在大多数情况下,攻击者被嵌入在网页中(问题)该恶意脚本(Cross site Scripting),这里的攻击始终触发浏览器端,攻击的者的目的.一般都是获取用户的C ...

  5. Windows phone 8 学习笔记(4) 应用的启动

    原文:Windows phone 8 学习笔记(4) 应用的启动 Windows phone 8 的应用除了可以直接从开始菜单以及应用列表中打开外,还可以通过其他的方式打开.照片中心.音乐+视频中心提 ...

  6. 强大的PropertyGrid

    PropertyGrid, 做工具一定要用这东西..... 把要编辑的对象看成类的话, 全部要编辑的属性就是成员 嗯嗯, 近期看了几眼Ogitor, 它对于PropertyGrid的使用就非常不错 全 ...

  7. poj3694(动态询问割桥的数目)

    给我们一个图,然后有q次加边的操作,问每次加完边之后有多少个桥存在 首先用dfs求出所有的桥,然后dfs的过程中生成了一棵dfs树,该树有的边是桥,有的不是,用bridge[v] = true , 表 ...

  8. hdu1513 (滚动数据压缩空间)

    给定一个字符串,问最少添加多少个字符可以使得这个字符串变成回文串 if(str[i]==str[j]) dp[i][j] = dp[i+1][j-1] else dp[i][j] = min(dp[i ...

  9. JSP与ASP.PHP的比較

    眼下,最经常使用的三种动态网页语言为:ASP(Active Server Pages).PHP(HyperText Preprocessor)及JSP(Java Server Pages). JSP与 ...

  10. 【翻译】Why JavaScript Is and Will Continue to Be the First Choice of Programmers

    花费2半小时,那么最终会被翻译.假设有问题,请提出,毕竟,自己的6不超过级别. 附加链接 Why JavaScript Is and Will Continue to Be the First Cho ...