投影方式- Unity3D游戏开发培训

 

作者:Jesai

2018-02-12 20:33:13

摘  要

透视投影是3D渲染的基本概念,也是3D程序设计的基础。掌握透视投影的原理对于深入理解其他3D渲染管线具有重要作用。本文详细介绍了透视投影的原理和算法实现,包括透视投影的标准模型、一般模型和屏幕坐标变换等,并通过VC实现了一个演示程序。

在Unity3D里面,投影方式决定了我们人眼看到的场景,投影方式一般分为透视投影和正交投影两种,透视投影相当于我们人的眼睛看到的东西。越远越小,越近越大。还会出现一个倒影。在物理学上面的小孔成像就是透视投影。正交投影是平行光源的投射,物体不会随着距离的改变而改变。在计算机三维图像里面,投影是可以看作是一种将三维坐标变成二维坐标的方法。

相机设置

透视投影:与人的视觉系统相似,多用在三维平面中对三维世界的呈现。模型是由视点E和视平面P两部分构成(要求E不在平面P上),视点就是观察者的位置,也就是三维世界的角度,视平面就是渲染三维对象的二维平面图,对于任意一点X,构造一条从E到X的射线R,R与平面P的交点X,p即是X点的透视投影结果。如图所示:

图 1-1

图 1-2

 

正交投影:用于二维世界的呈现。

图 1-3

无论远近,大小是一样的

 

 

3D默认是透视投影(Perspective),2D默认是正交投影(Orthographic)。

透视投影的实现

6.1 载入3D模型

使用Matt Fairfax实现的Model_3DS类支持3DS模型文件的载入,该类的实现非常简单,而且很容易使用,具体可参考[7]。由于本文的DEMO只需要其中的模型载入功能,所以对源代码进行了删减,去掉了纹理加载(暂不需要)和渲染(我们自己实现)代码,在析构函数中添加了资源释放代码。

6.2 视图变换

为表示透视投影的一般模型,实现了KCamera类,除保存视点的位置和姿态,还保存视图变换矩阵m_kmView,随着视点位置和姿态的变化,视图矩阵也不断更新,更新算法详见第4节。对于世界坐标系中的任何一点v(x, y, z),通过v = m_kmView*v将其变换到透视投影的标准模型坐标系,详见KCamera::Transform函数。

6.3 透视变换

KFrustum类用来对透视投影的标准模型进行建模,其成员包括视平面的尺寸大小,以及近截面和远截面的z轴坐标。KFrustum通过Project函数将视图变换的结果变换为透视坐标。算法的原理见第3节,代码实现如下:

 void KFrustum::Project(KVector3& v)

 {

     // xp = x*n/z, yp = y*n/z, zp = n.

     float fFactor = GetNear()/v.z;

     v.x *= fFactor;

     v.y *= fFactor;

     v.z = GetNear();

 }

6.4 屏幕变换

屏幕变换的算法通过宏实现,代码如下:

 #define ToScreen(v, Ws, Hs) /

 {/

     float x = (v.x/GetWidth()+0.5f)*(Ws-);/

     float y = (v.y/GetHeight()+0.5f)*(Hs-);/

     v.x = KMath::Round(x);/

     v.y = KMath::Round(y);/

 }

6.5 渲染

Demo中的渲染使用软件实现,没有使用任何第三方图形库,主代码在KCamera::Render函数中,它接收两次参数:Model_3DS和KSurface,对Model_3DS中的顶点进行透视投影,然后将结果绘制到Ksurface中。函数代码如下:

 bool KCamera::Render(Model_3DS& m3DS, KSurface& kSurface)

 {

     kSurface.Fill(RGB(,,)); // 背景为黑色

     COLORREF crPen = RGB(,,); // 用红色绘制模型

     KMatrix4 m = m_kmView;

     int Ws = kSurface.GetWidth();

     int Hs = kSurface.GetHeight();

     for(int i=; i<m3DS.numObjects; i++)

     {

         Model_3DS::Object& obj = m3DS.Objects[i];

         for(int n=; n<obj.numFaces; n+=)

         {

             int index = obj.Faces[n]*;

             KVector4 v0(obj.Vertexes[index], obj.Vertexes[index+], obj.Vertexes[index+]);

             index = obj.Faces[n+]*;

             KVector4 v1(obj.Vertexes[index], obj.Vertexes[index+], obj.Vertexes[index+]);

             index = obj.Faces[n+]*;

             KVector4 v2(obj.Vertexes[index], obj.Vertexes[index+], obj.Vertexes[index+]);

             Transform(v0, Ws, Hs);

             Transform(v1, Ws, Hs);

             Transform(v2, Ws, Hs);

             // 绘制网线

             kSurface.MoveTo(v0.x, v0.y);

             kSurface.LineTo(v1.x, v1.y, crPen);

             kSurface.LineTo(v2.x, v2.y, crPen);

             kSurface.LineTo(v0.x, v0.y, crPen);

         }

     }

     return true;

 }

最新文章

  1. iOS开发 个别页面是否支持页面旋转
  2. iOS-保存照片或者视频到自定义相薄中以及读取数据
  3. ASP跨域调用Webservices方法
  4. C#的正则表达式
  5. ubuntu 装机及装机以后干的事情
  6. Java并发编程:阻塞队列(转载)
  7. C++学习45 流成员函数put输出单个字符 cin输入流详解 get()函数读入一个字符
  8. sql server查询出的结果中添加一列序列行
  9. 增强学习贪心算法与Softmax算法
  10. swift学习之一致性hash
  11. HDU 5496 - BestCoder Round #58 - Beauty of Sequence
  12. Java -- WeakHashMap
  13. iOS自动打包并发布脚本
  14. appium+python+eclipse 自动化测试框架构建!
  15. Nodejs连接mysql的增、删、改、查操作
  16. count(1)、count(*)与count(列名)的执行区别
  17. python基础之Day13
  18. 跟Python打包相关的一些文章
  19. Servlet3.0新特性WebFilter(Annotation Filter)详解
  20. 每日英语:Redfin Real-Estate Firm Gets Cold Shoulder in Silicon Valley

热门文章

  1. 【ts】 VSCode自动编译TypeScript终端报错
  2. 1471 - Defense Lines
  3. 聚类——DBSCAN
  4. HDU 3746 Cyclic Nacklace(kmp next数组运用)
  5. 搭建zookeeper出现错误:starting zookeeper... already running process 2853
  6. TOJ 6121: 学长的情书 ( 二分)
  7. &lt;Codeforce&gt;1082A. Vasya and Book
  8. [luogu1908]逆序对(upper_bound)
  9. 有限状态机FSM和层次状态机HSM
  10. python 练习题2