Unity系列文章目录

文章目录

  • Unity系列文章目录
  • 前言
  • 4.1 背景:农场游戏
  • 4.2 笛卡儿坐标系
    • 4.2.2 三维笛卡儿坐标系
    • 4.2.3 左手坐标系和右手坐标系
    • 4.2.4 Unity 使用的坐标系
  • 参考

前言

计算机图形学之所以深奥难懂,很大原因是在于它是建立在虚拟世界上的数学模型。数学渗
透到图形学的方方面面,当然也包括Shader。在学习Shader 的过程中,我们最常使用的就是矢量
和矩阵(即数学的分支之一—线性代数)。
很多读者认为图形学中的数学复杂难懂。的确,一些数学模型在初学者看来晦涩难懂。但很
多情况下,我们需要打交道的只是一些基础的数学运算,而只要掌握了这些内容,就会发现很多
事情可以迎刃而解。我们在研究和学习他人编写的Shader 代码时,也不再会疑问:“他为什么要
这么写”,而是“哦,这里就是使用矩阵进行了一个变换而已。”
为了让读者能够参与到计算中来,而不是填鸭式地阅读,在一些小节的最后我们会给出一些
练习题。练习题的答案会在本章最后给出(不要偷看答案!)。需要注意的是,这些练习题并不是
可有可无的,我们并非想利用题海战术来让读者掌握这些数学运算,而是想利用这些练习题来阐
述一些容易出错或实践中常见的问题。通过这些练习题,读者可以对本节内容有更加深刻的理解。
那么,拿起笔来,让我们一起走进数学的世界吧!

4.1 背景:农场游戏

为了让读者更加理解数学计算的几何意义,我们先来假定一个场景。现在,假设我们正在开
发一款卡通风格的农场游戏。在这个游戏里,玩家可以在农场里养很多可爱的奶牛。与普通农场
游戏不同的是,我们的主角不是玩家,而是一头牛—妞妞,如图4.1 所示。妞妞不仅长得壮,
而且它对很多事情都充满了好奇心。

读者:为什么游戏主角不是玩家呢?我们:因为我们的策划就是这么任性。
在故事的一开始,农场世界是没有数学概念的。通过下面的学习,我们会见证数学给这个世
界带来了怎样翻天覆地的变化。

4.2 笛卡儿坐标系

在游戏制作中,我们使用数学绝大部分都是为了计算位置、距离和角度等变量。而这些计算
大部分都是在笛卡儿坐标系(Cartesian Coordinate System)下进行的。这个名字来源于法国伟
大的哲学家、物理学家、心理学家、数学家笛卡儿(René Descartes)。
那么,我们为什么需要笛卡儿坐标系呢?有这样一个传说,讲述了笛卡儿提出笛卡儿坐标系
的由来。笛卡儿从小体弱多病,所以他所在的寄宿学校的老师允许他可以一直留在床上直到中午。
在笛卡儿的一生中,他每天的上午时光几乎都是在床上度过的。笛卡儿并没有把这段时间用在睡
懒觉上,而是思考了很多关于数学和哲学上的问题。有一天,笛卡儿发现一只苍蝇在天花板上爬
来爬去,他观察了很长一段时间。笛卡儿想:我要如何来描述这只苍蝇的运动轨迹呢?最后,笛
卡儿意识到,他可以使用这只苍蝇距离房间内不同
墙面的位置来描述,如图4.2 所示。他从床上起身,
写下了他的发现。然后,他试图描述一些点的位置,
正如他要描述苍蝇的位置一样。最后,笛卡儿就发
明了这个坐标平面。而这个坐标平面后来逐渐发
展,就形成了坐标系系统。人们为了纪念笛卡儿的
工作,就用他的名字来给这种坐标系进行命名。
当然,上面传说的可靠性无从验证。一些较真
儿的读者就不用急着向本书勘误邮箱中发邮件说:
“嘿,你简直是胡说!”不过,读者可以从这个传说
中发现,笛卡儿坐标系和我们的生活是密切相关的。
4.2.1 二维笛卡儿坐标系
事实上,读者很可能一直在用二维笛卡儿坐标系,尽管你可能并没有听过笛卡儿这个名词。
你还记得在《哈利波特与魔法石》电影中,哈利和罗恩大战奇洛教授的魔法棋盘吗?这里的国际
象棋棋盘也可以理解成是一个二维的笛卡儿坐标系。
图4.3 显示了一个二维笛卡儿坐标系。它是不是很像一个棋盘呢?
一个二维的笛卡儿坐标系包含了两个部分的信息:
 一个特殊的位置,即原点,它是整个坐标系的中心;
 两条过原点的互相垂直的矢量,即x 轴和y 轴。这些坐
标轴也被称为是该坐标系的基矢量。
虽然在图4.3 中x 轴和y 轴分别是水平和垂直方向的,但这
并不是必须的。想象把上面的坐标系整体向左旋转30°。而且,
虽然图中的x 轴指向右、y 轴指向上,但这也并不是必须的。例
如,在2.3.4 节屏幕映射中,OpenGL 和DirectX 使用了不同的二
维笛卡儿坐标系,如图4.4 所示。
而有了这个坐标系我们就可以精确地定位一个点的位置。例
如,如果说:“在(1, 2)的位置上画一个点。”那么相信读者肯定知道这个位置在哪里。

我们来看一下笛卡儿坐标系给奶牛农场带来了什么变化。在没有笛卡儿坐标系的时候,奶牛
们根本没有明确的位置概念。如果一头奶牛问:“妞妞,你现在在哪里啊?”妞妞只能回答说“我
在这里”或者“我在那里”这些模糊的词语。但那头奶牛永远不会知道妞妞的确切位置。而把笛
卡儿坐标系引入到奶牛农场后,所有的一切都变得清晰起来。我们把奶牛农场的中心定义成坐标
原点,而把地理方向中的东、北定义成坐标轴方向。现在,如果奶牛再问:“妞妞,你现在在哪里
啊?”妞妞就可以回答说:“我在东1 米、北3 米的地方。”如图4.5 所示。

4.2.2 三维笛卡儿坐标系

在上面一节中,我们已经了解了二维笛卡儿坐标系。可以看出,二维笛卡儿坐标系实际上是
比较简单的。那么,三维比二维只多了一个维度,是不是也就难了50%而已呢?
不幸的是,答案是否定的。三维笛卡儿坐标系相较于二维来说要复杂许多,但这并不意味着
很难学会它。对人类来说,我们生活的世界就是三维的,因此对于理解更低维度的空间(一维和
二维)是比较容易的。而对于同等维度的一些概念;理解起来难
度就大一些;对于更高维度的空间(如四维空间),理解难度就更
大了。
在三维笛卡儿坐标系中,我们需要定义3 个坐标轴和一个原
点。图4.6 显示了一个三维笛卡儿坐标系。
这3 个坐标轴也被称为是该坐标系的基矢量(basis vector)。
通常情况下,这 3 个坐标轴之间是互相垂直的,且长度为1,这
样的基矢量被称为标准正交基(orthonormal basis),但这并不是
必须的。例如,在一些坐标系中坐标轴之间互相垂直但长度不为
1,这样的基矢量被称为正交基(orthogonal basis)。如非特殊说
明,本书默认情况下使用的坐标轴指的都是标准正交基。
读者:正交这个词是什么意思呢?
我们:正交可以理解成互相垂直的意思。在下面矩阵的内容中,我们还会看到正交矩阵的
概念。
和二维笛卡儿坐标系类似,三维笛卡儿坐标系中的坐标轴方向也不是固定的,即不一定是像
图4.6 中那样的指向。但这种不同导致了两种不同种类的坐标系:左手坐标系(left-handed
coordinate space)和右手坐标系(right-handed coordinate space)。

4.2.3 左手坐标系和右手坐标系

为什么在三维笛卡儿坐标系中要区分左手坐标系和右手坐标系,而二维中就没有这些烦人的
事情呢?这是因为,在二维笛卡儿坐标系中,x 轴和y 轴的指向虽然可能不同,就如我们在图4.4
中看到的一样。但我们总可以通过一些旋转操作来使它们的坐标轴指向相同。以图4.4 中OpenGL
和DirectX 使用的坐标系为例,为了把右侧的坐标轴指向转换到左侧那样的指向,我们可以首先
对右侧的坐标系顺时针旋转180°,此时它的y 轴指向上,而x 轴指向左。然后,我们再把整个纸
面水平翻转一下,就可以把x 轴翻转到指向右了,此时左右两侧的坐标轴指向就完全相同了。从
这种意义上来说,所有的二维笛卡儿坐标系都是等价的。
但对于三维笛卡儿坐标系,靠这种旋转有时并不能使两个不同朝向的坐标系重合。例如,在
图4.6 中,+z 轴的方向指向纸面的内部,如果有另一个三维笛卡儿坐标系,它的+z 轴是指向纸面
外部,x 轴和y 轴保持不变,那么我们可以通过旋转把这两个坐标轴重合在一起吗?答案是否定
的。我们总可以让其中两个坐标轴的指向重合,但第三个坐标轴的指向总是相反的。
也就是说,三维笛卡儿坐标系并不都是等价的。因此,就出现了两种不同的三维坐标系:左
手坐标系和右手坐标系。如果两个坐标系具有相同的旋向性(handedness),那么我们就可以通过
旋转的方法来让它们的坐标轴指向重合。但是,如果它们具有不同的旋向性(例如坐标系A 属于
左手坐标系,而坐标系B 属于右手坐标系),那么就无法达到重合的目的。
那么,为什么叫左手坐标系和右手坐标系呢?和手有什么关系?这是因为,我们可以利用我
们的双手来判断一个坐标系的旋向性。请读者举起你的左手,用食指和大拇指摆出一个“L”的
手势,并且让你的食指指向上,大拇指指向右。现在,伸出你的中指,不出意外的话它应该指向
你的前方(如果你一定要展示自己骨骼惊奇的话我也没有办法)。恭喜你,你已经得到了一个左手
坐标系了!你的大拇指、食指和中指分别对应了+x、+y 和+z 轴的方向,如图4.7 所示。
同样,读者可以通过右手来得到一个右手坐标系。举起你的右手,这次食指仍然指向上,中
指指向前方,不同的是,大拇指将指向左侧,如图4.8 所示。

正如我们之前所说,左手坐标系和右手坐标系之间无法通过旋转来同时使它们的3 个坐标轴
指向重合,如果你不信,你现在可以拿自己的双手来试验一下。
另外一个确定是左手还是右手坐标系的方法是,判断前向(forward)的方向。请读者坐直,
向右伸直你的右手,此时右手方向就是x 轴的正向,而你的头顶向上的方向就是y 轴的正向。这

时,如果你的正前方的方向是z 轴的正向,那么你本身所在的坐标系就是一个左手坐标系;如果
你的正前方的方向对应的是z 轴的负向,那么这就是一个右手坐标系。
除了坐标轴朝向不同之外,左手坐标系和右手坐标系对于正向旋转的定义也不同,即在初高
中物理中学到的左手法则(left-hand rule)和右手法则(right-hand rule)。假设现在空间中有一
条直线,还有一个点,我们希望把这个点以该直线为旋转轴旋转某个角度,比如旋转30°。读者
可以拿一支笔当成这个旋转轴,再拿自己的手当成这个需要旋转的点,可以发现,我们有两个旋
转方向可以选择。那么,我们应该往哪个方向旋转呢?这意味着,我们需要在坐标系中定义一个
旋转的正方向。在左手坐标系中,这个旋转正方向是由左手法则定义的,而在右手坐标系中则是
由右手法则定义的。
在左手坐标系中,我们可以这样来应用左手法则:还是举起你的左手,握拳,伸出大拇指让
它指向旋转轴的正方向,那么旋转的正方向就是剩下4 个手指的弯曲方向。在右手坐标系中,使
用右手法则对旋转正方向的判断类似。如图4.9 所示。
从图3.9 中可以看出,在左手坐标系中,旋转正方向是顺时针的,而在右手坐标系中,旋转
正方向是逆时针的。
左右手坐标系之间是可以进行互相转换的。最简单的方法就是把其中一个轴反转,并保持其
他两个轴不变。
对于开发者来说,使用左手坐标系还是右手坐标系都是可以的,它们之间并没有优劣之分。
无论使用哪种坐标系,绝大多数情况下并不会影响底层的数学运算,而只是在映射到视觉上时会
有差别(见练习题2)。这是因为,一个点或者旋转在空间内来说是绝对的。一些较真儿读者可能
会看不惯“绝对”这个词:“你怎么能忽略相对论呢?这世上一切都是相对的!”这些读者请容我
解释。这里所说的绝对是说,在我们所关心的最广阔的空间中,这些值是绝对的。例如我说,把
你的书从桌子的左边移到右边,你不会对这个过程产生什么疑问,此时我们关心的整个空间就是
桌子这个空间,而在这个空间中,书的运动是绝对的。但是,在数学的世界中,我们需要使用一
种数学模型来精确地描述它们,这个模型就是坐标系。一旦有了坐标系,每个点的位置就不再是
绝对的,而是相对于这个坐标系来说的。这种相对关系导致,即便从数学表示上来说两种表示方
式完全一样,但从视觉上来说是不一样的。
我们可以在奶牛农场的例子中体会左手坐标系和右手坐标系的分别。我们假设,妞妞想要到一个
新的地方,因为那里的草很美味。妞妞知道到达这个目标点的“绝对路径”是怎样的,如图4.10 所示。


我们可以分别在一个左手坐标系和右手坐标系中描述这样一次运动,即使用数学表达式来描
述它。我们会发现,在不同的坐标系中描述这样同一次运动是不一样的,如图4.11 所示。

在左手坐标系中,3 个坐标轴的朝向如图4.11 左图所示。妞妞首先向x 轴正方向平移1 个单
位,然后再向z 轴负方向移动4 个单位,最后朝旋转的正方向旋转60°。而在右手坐标系中,+z
轴的方向和左手坐标系中刚好相反,因此妞妞首先向x 轴正方向平移1 个单位(与左手坐标系中
的移动一致),然后再向z 轴正方向移动4 个单位(与左手坐标系中的移动相反),最后朝旋转的
负方向旋转60°(与左手坐标系中的旋转相反)。
可以看出,为了达到同样的视觉效果(这里指把妞妞移动到视觉上的同一个位置),左右手坐
标系在z 轴上的移动以及旋转方向是不同的。如果使用相同的数学运算(指均向z 轴某方向移动
或均朝旋转正方向旋转等),那么得到的视觉效果就是不一样的。因此,如果我们需要从左手坐标
系迁移到右手坐标系,并且保持视觉上的不变,就需要进行一些转换。读者可以参见本章最后的
扩展阅读部分。

4.2.4 Unity 使用的坐标系

对于一个需要可视化虚拟的三维世界的应用(如Unity)来说,它的设计者就要进行一个选
择。对于模型空间和世界空间(在4.6 节中会具体讲解这两个空间是什么),Unity 使用的是左手
坐标系。这可以从Scene 视图的坐标轴显示看出来,如图4.12 所示。这意味着,在模型空间中,
一个物体的右侧(right)、上侧(up)和前侧(forward)分别对应了x 轴、y 轴和z 轴的正方向。

但对于观察空间来说,Unity 使用的是右手坐标系。观察空间,通俗来讲就是以摄像机为原
点的坐标系。在这个坐标系中,摄像机的前向是z 轴的负方向,这与在模型空间和世界空间中的
定义相反。也就是说,z 轴坐标的减少意味着场景深度的增加,如图4.13 所示。

关于Unity 中使用的坐标系的旋向性,我们会在4.5.9 节中详细地讲解。

参考

Unity Shader入门精要
作者:冯乐乐

Unity Shader入门精要--第4 章 学习Shader 所需的数学基础相关推荐

  1. Unity Shader入门精要--第4 章 学习Shader 所需的数学基础:点和矢量

    Unity系列文章目录 文章目录 Unity系列文章目录 前言 点和矢量 4.3.1 点和矢量的区别 参考 前言 点(point)是n 维空间(游戏中主要使用二维和三维空间)中的一个位置,它没有大小. ...

  2. Unity Shader入门精要第七章 基础纹理之遮罩纹理

    Unity系列文章目录 文章目录 Unity系列文章目录 前言 一.实践 参考 前言 遮罩纹理(mask texture)是本章要介绍的最后一种纹理,它非常有用,在很多商业游戏中 都可以见到它的身影. ...

  3. Unity Shader入门精要第四章:学习Shader 所需的数学基础--坐标空间

    Unity系列文章目录 文章目录 Unity系列文章目录 前言 一.4.6.1 为什么要使用这么多不同的坐标空间 二.4.6.3 顶点的坐标空间变换过程 4.6.4 模型空间 4.6.6 观察空间 4 ...

  4. Unity Shader入门精要——第3章 Unity Shader基础

    Unity Shader入门精要读书笔记系列 第1章 欢迎来到Shader的世界 第2章 渲染流水线 第3章 Unity Shader基础 文章目录 Unity Shader入门精要读书笔记系列 前言 ...

  5. Unity Shader入门精要第3 章 Unity Shader 基础

    Unity系列文章目录 文章目录 Unity系列文章目录 前言 一.Unity Shader 概述 二.使用步骤 1.3.1.2 Unity 中的材质 2.Unity 中的Shader 3.Unity ...

  6. Unity Shader入门精要第七章 基础纹理 凹凸映射之在世界空间下计算

    Unity系列文章目录 文章目录 Unity系列文章目录 前言 一.pandas是什么? 二.使用步骤 2.Unity 中的法线纹理类型 参考 前言 现在,我们来实现第二种方法,即在世界空间下计算光照 ...

  7. Unity Shader入门精要第七章 基础纹理渐变纹理

    Unity系列文章目录 文章目录 Unity系列文章目录 前言 一.渐变纹理是什么 参考 前言 尽管在一开始,我们在渲染中使用纹理是为了定义一个物体的颜色,但后来人们发现,纹理 其实可以用于存储任何表 ...

  8. Unity Shader入门精要 第4章 笛卡尔坐标系 读书笔记

    第4章 学习Shader所需的数学基础-笛卡尔坐标系 注意:图片的来源基本来自作者冯乐乐的GitHub,感谢作者分享 https://github.com/candycat1992/Unity_Sha ...

  9. TA课程笔记01——光照(主要为shader入门精要第六章)

    //老师在这里简单的简述了一下渲染流水线,我在之前的图形学笔记中很详细的讲述了渲染流水线的过程,便不再赘述 //因为老师很详细的将几种常见的光照模型都讲了一遍,但都是美术方向,前面的案例也都缺少代码, ...

最新文章

  1. 【Mysql】MySQL event 计划任务
  2. Firewalld防火墙应用
  3. react 与 Vue的一些比较
  4. pfsense 2.2RC版本应用
  5. MMORPG的一份Unity手游性能蓝皮书
  6. 今日问题:开发在临近发布时“画蛇添足”,测试没有时间测试,该如何处理?
  7. 基于vue开发简易备忘录,实现列表增删
  8. 使用kubeadm安装部署k8s
  9. html 语音识别输入法,9种外语语音识别 搜狗输入法成国内支持语种最多输入法...
  10. 15个免费学习JavaScript的最佳网站
  11. 群晖NAS设备MIB手册
  12. 当前默认服务器维护尚未完成,更新公告 | 7月11日早8点停服维护
  13. CMOS图像传感器工作原理
  14. 计算机if函数自动填充,Excel表格函数怎么能实现自动填充-excel填充函数,excel表格根据公式自动填充...
  15. logo设计灵感的创意网站
  16. js距离单位换算_js实现单位互换px/cm/mm篇
  17. 非企用户该如何推广?什么事非企户呢?
  18. 【亚马逊运营】什么情况下使用Coupon卖家们知多少?
  19. 一个不错的免费二级域名,可以自己解析A记录 CNAME等,而且是备案的域名。
  20. [转载] Python 机器学习经典实例

热门文章

  1. 怎么看java架包里的源码,vlx文件可以查看源代码|怎么查看Jar包源码?如何打开Jar文件?...
  2. 怎么才能在word里从第三页开始编页码啊
  3. 《电脑编程技巧与维护2008年合订本》
  4. 浅谈蓝湖使用ps插件快速构建代码
  5. C语言typedef函数指针用法
  6. Linux 内核实时补丁 PREEMPT_RT补丁 与 Linux4.1.15 + patch-4.1.15-rt18.patch 补丁,实测实时性差
  7. 人工智能论文术语集25
  8. Mysql中使用json格式存储数据好吗?
  9. 新媒体管理师是什么?为什么那么多人都在考你知道吗?
  10. labelme标注的json文件转化成ICDAR2015格式