投影方式- Unity3D游戏开发培训
投影方式- 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游戏开发培训的更多相关文章
- 用户输入- Unity3D游戏开发培训
用户输入- Unity3D游戏开发培训 作者:Jesai 时间:2018-02-12 14:28:45 用户输入Input 鼠标按键: -方法:GetMouseButton(); -方法:GetM ...
- 内置3D对象-Unity3D游戏开发培训
内置3D对象-Unity3D游戏开发培训 作者:Jesai 2018-02-12 19:21:58 五大面板: -Hierachy:当前场景中的物体 图 1-1 -Project:项目中的所有资源 图 ...
- Unity3D游戏开发培训
Unity3D游戏开发培训 作者:Jesai 时间:2017-01-08 修改:2017-01-09 12:36:15 1 项目的构成 图1-1 如图1-1所示,Unity3D的项目构 ...
- [Unity3D]Unity3D游戏开发3D选择场景中的对象,并显示轮廓效果强化版
大家好,我是秦培,欢迎关注我的博客,我的博客地址blog.csdn.net/qinyuanpei. 在上一篇文章中,我们通过自己定义着色器实现了一个简单的在3D游戏中选取.显示物体轮廓的实例. 在文章 ...
- Unity3D游戏开发初探—2.初步了解3D模型基础
一.什么是3D模型? 1.1 3D模型概述 简而言之,3D模型就是三维的.立体的模型,D是英文Dimensions的缩写. 3D模型也可以说是用3Ds MAX建造的立体模型,包括各种建筑.人物.植被. ...
- Unity3D游戏开发从零单排(四) - 制作一个iOS游戏
提要 此篇是一个国外教程的翻译,尽管有点老,可是适合新手入门. 自己去写代码.debug,布置场景,能够收获到非常多.游戏邦上已经有前面两部分的译文,这里翻译的是游戏的最后一个部分. 欢迎回来 在第一 ...
- [Unity3D]Unity3D游戏开发之飞机大战项目解说
大家好,我是秦元培,欢迎大家继续关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei. 首先感谢大家对我博客的关注,今天我想和大家分享的是一个飞机大战的项目.这是一个比較综合的 ...
- [Unity3D]Unity3D游戏开发《反对》说到游戏(上)——目标跟踪
朋友,大家好.我是秦培,欢迎关注我的博客.我的博客地址blog.csdn.net/qinyuanpei. 首先博主要自我反省,过了这么久才来更新博客,这段时间主要是在忙着写期末的作业,所以博主基本上没 ...
- [Unity3D]Unity3D游戏开发之跑酷游戏项目解说
大家好,我是秦元培.我參加了CSDN2014博客之星的评选,欢迎大家为我投票,同一时候希望在新的一年里大家能继续支持我的博客. 大家晚上好.我是秦元培,欢迎大家关注我的博客,我的博客地址是blog.c ...
随机推荐
- H3C DHCP中继配置示例
- RabbitMQ-事务和Confirm消息确认
,如果要保证消息的可靠性,需要对消息进行持久化处理,然而消息持久化除了需要代码的设置之外,还有一个重要步骤是至关重要的,那就是保证你的消息顺利进入Broker(代理服务器),如图所示: 正常情况下,如 ...
- 微软软件开发技术二十年回顾-Windows DNA篇
五. Windows DNA篇 微软的Windows分布式因特网应用体系(简称Windows DNA)是微软创建新一代高适应性商业解 决方案的框架,它使公司能够充分地挖掘数字神经系统的优点.Windo ...
- HDU4742 CDQ分治,三维LIS
HDU4742 CDQ分治,三维LIS 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4742 题意: 每个球都有三个属性值x,y,z,要求最长的lis的 ...
- Lede定时重拨
系统,计划任务, 0 4 * * * ifup wan 梅林定时重拨: #! /bin/sh #断开拨号连接 killall pppd #延时10秒 #重新拨号 pppd >& &a ...
- LeetCode3_无重复字符的最长子串(数组&字符串问题)
题目: 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "ab ...
- PHP常用函数拾遗
PHP中常用过滤函数addslashes().mysql_real_escape_string().mysql_escape_string() 如addslashes().mysql_real_es ...
- Service Mesh服务网格清单
Service Mesh服务网格清单 Istio Istio官网 Istio中文官网 Istio开源 无需太多介绍Service Mesh明日之星,扛把子,截止2019.11还有太多问题没解决 复杂性 ...
- spring-redis-session 自定义 key 和过期时间
对于分布式应用来说,最开始遇到的问题就是 session 的存储了,解决方案大致有如下几种 使用 spring-session 它可以把 session 存储到你想存储的位置,如 redis,mysq ...
- System类StringBuilder小结