投影方式- 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. linux 在 /proc 里实现文件

    所有使用 /proc 的模块应当包含 <linux/proc_fs.h> 来定义正确的函数. 要创建一个只读 /proc 文件, 你的驱动必须实现一个函数来在文件被读时产生数据. 当 某个 ...

  2. spring的几个面试题

    Spring 是一种轻量级开发框架,旨在提高开发人员的开发效率以及系统的可维护性.Spring 官网:https://spring.io/. 我们一般说 Spring 框架指的都是 Spring Fr ...

  3. Linux 内核硬件资源

    一个 ISA 设备可配备有 I/O 端口, 内存区, 和中断线. 尽管 x86 处理器支持 64 KB I/O 端口内存(即, 处理器有 16 条地址线), 一些老 PC 硬 件仅解码最低的 10 位 ...

  4. 【52.55%】【BZOJ 4520】K远点对

    Time Limit: 30 Sec  Memory Limit: 512 MB Submit: 588  Solved: 309 [Submit][Status][Discuss] Descript ...

  5. Linux网络IO模型

    同步和异步,阻塞和非阻塞 同步和异步 关注的是结果消息的通信机制 同步:同步的意思就是调用方需要主动等待结果的返回 异步:异步的意思就是不需要主动等待结果的返回,而是通过其他手段比如,状态通知,回调函 ...

  6. UI 素材相关收集

    图标素材收藏网址  阿里:iconfont.cn 图片压缩:https://tinypng.com/ gif动图压缩:https://tool.gifhome.com

  7. win10安装Keras报错处理

    本机已经安装好TensorFlow安装Keras的过程中遇到了些问题,解决后做一下记录: 1.Keras与TensorFlow的关系 Keras默认以TensorFlow为后端,同时可选以Theano ...

  8. SSL/TLS 配置

    Quick Start 下列说明将使用变量名 $CATALINA_BASE 来表示多数相对路径所基于的基本目录.如果没有为 Tomcat 多个实例设置 CATALINA_BASE 目录,则 $CATA ...

  9. python单例设计模式

    class Dog(object): __instance = None def __init__(self): pass def __new__(cls): if not cls.__instanc ...

  10. jquery简单实现复选框的全选与反选

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...