投影方式- 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;

 }

投影方式- Unity3D游戏开发培训的更多相关文章

  1. 用户输入- Unity3D游戏开发培训

    用户输入- Unity3D游戏开发培训   作者:Jesai 时间:2018-02-12 14:28:45 用户输入Input 鼠标按键: -方法:GetMouseButton(); -方法:GetM ...

  2. 内置3D对象-Unity3D游戏开发培训

    内置3D对象-Unity3D游戏开发培训 作者:Jesai 2018-02-12 19:21:58 五大面板: -Hierachy:当前场景中的物体 图 1-1 -Project:项目中的所有资源 图 ...

  3. Unity3D游戏开发培训

    Unity3D游戏开发培训 作者:Jesai 时间:2017-01-08 修改:2017-01-09 12:36:15 1         项目的构成 图1-1 如图1-1所示,Unity3D的项目构 ...

  4. [Unity3D]Unity3D游戏开发3D选择场景中的对象,并显示轮廓效果强化版

    大家好,我是秦培,欢迎关注我的博客,我的博客地址blog.csdn.net/qinyuanpei. 在上一篇文章中,我们通过自己定义着色器实现了一个简单的在3D游戏中选取.显示物体轮廓的实例. 在文章 ...

  5. Unity3D游戏开发初探—2.初步了解3D模型基础

    一.什么是3D模型? 1.1 3D模型概述 简而言之,3D模型就是三维的.立体的模型,D是英文Dimensions的缩写. 3D模型也可以说是用3Ds MAX建造的立体模型,包括各种建筑.人物.植被. ...

  6. Unity3D游戏开发从零单排(四) - 制作一个iOS游戏

    提要 此篇是一个国外教程的翻译,尽管有点老,可是适合新手入门. 自己去写代码.debug,布置场景,能够收获到非常多.游戏邦上已经有前面两部分的译文,这里翻译的是游戏的最后一个部分. 欢迎回来 在第一 ...

  7. [Unity3D]Unity3D游戏开发之飞机大战项目解说

    大家好,我是秦元培,欢迎大家继续关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei. 首先感谢大家对我博客的关注,今天我想和大家分享的是一个飞机大战的项目.这是一个比較综合的 ...

  8. [Unity3D]Unity3D游戏开发《反对》说到游戏(上)——目标跟踪

    朋友,大家好.我是秦培,欢迎关注我的博客.我的博客地址blog.csdn.net/qinyuanpei. 首先博主要自我反省,过了这么久才来更新博客,这段时间主要是在忙着写期末的作业,所以博主基本上没 ...

  9. [Unity3D]Unity3D游戏开发之跑酷游戏项目解说

    大家好,我是秦元培.我參加了CSDN2014博客之星的评选,欢迎大家为我投票,同一时候希望在新的一年里大家能继续支持我的博客. 大家晚上好.我是秦元培,欢迎大家关注我的博客,我的博客地址是blog.c ...

随机推荐

  1. dotnet 非泛型 类型 System.Collections.IEnumerable 不能与类型实参一起使用

    如果在开发的时候遇到非泛型 类型"IEnumerable"不能与类型参数一起使用,那么就是变量的命名空间没弄对 在 dotnet 里面有 System.Collections.IE ...

  2. Linux命令之nohup 和 重定向

    用途:使运行的程序忽略SIGHUP. 语法:nohup Command [ Arg ... ] [ & ]描述:nohup 命令运行由 Command 参数和任何相关的 Arg 参数指定的命令 ...

  3. cglib的使用

    前言 最近一直在看Spring源码,其实我之前一直知道AOP的基本实现原理: 如果针对接口做代理默认使用的是JDK自带的Proxy+InvocationHandler 如果针对类做代理使用的是Cgli ...

  4. JSPs

    简介 Tomcat 8.0 使用 Jasper 2 JSP 引擎去实现 JavaServer Pages 2.3 规范. Jasper 2 经过了重新设计,极大改善了上一版 Jasper 的性能.除了 ...

  5. TCP/IP||IP选路

    1.选路原理 在IP搜索路由表分为几个步骤 1.搜索匹配的主机地址 2.搜索匹配的网络地址 3.搜索默认表项. IP层进行选路实际是一种选路机制,搜索路由表并决定向哪个网络接口发送分组,区别选路策略, ...

  6. spring boot(一)创建项目

    网上有很多springboot的入门教程,自己也因为项目要使用springboot,所以利用业余时间自学了下springboot和springcloud,使用下来发现springboot还是挺简单的, ...

  7. 【题解】有标号的DAG计数3

    [HZOI 2015] 有标号的DAG计数 III 我们已经知道了\(f_i\)表示不一定需要联通的\(i\)节点的dag方案,考虑合并 参考[题解]P4841 城市规划(指数型母函数+多项式Ln), ...

  8. $CF908D\ New\ Year\ and\ Arbitrary\ Arrangement$ 期望$dp$

    正解:期望$dp$ 解题报告: 传送门$QwQ$ 阿关于题目里那个形如$ab$的子序列我说下,,,我我我之前$get$了好久$QAQ$.这里子序列的个数的定义是这样儿的,举个$eg$,$aabb$,就 ...

  9. <算法><go实现>左括号补全-双栈法

    输入:1+2)*33-44)*555-666))) 输出:((1+2)*((33-44)*(555-666))) 代码实现及注释: package main import "fmt" ...

  10. 2019年终总结&小半年流媒体服务器开发经验总结

    目录 2019年终总结&小半年流媒体服务器开发经验总结 19年开发小结 流媒体服务框架设计 登录服开发 ffmpeg音视频服务开发 音视频控制 流媒体服务开发小结 rtp处理 视频的合成&am ...