首先,我们要了解为什么会存在这些奇奇怪怪的空间,他们存在的意义是什么?
举个栗子:我们初中物理都学过,运动是相对的。两个同方向同速度运动的物体在他们自己看来相互是静止的。也就是说,我们要表达物体的位置,需要有参照物。我们在睡觉的时候自己感觉是静止的,但那是相对于地球来说。实际上相对于太阳我们一直在高速运动。那么回到3D世界,我们该如何定义这个参照物呢?
聪明的设计师们一下就想到了:坐标轴
我们只需要在整个场景中设定一个基本的原点作为中心,然后以原点发散出一个三维坐标系,就可以准确表达每个物品的位置了。这个以原点为中心发散的坐标轴构成的空间,就是世界空间。
诚然这个方法非常天才,但是却不够好用。比如我们不好表达一个物品相对于自己的旋转和缩放
我们都知道模型是由一个一个点连接成网格组成的,那么如果每个点的位置都是相对于世界原点来定义的话,那么我们想要将一个处于世界空间任意位置的模型进行缩放或者旋转,那我们就会得到一个奇怪的结果:缩放会相对于世界原点进行缩放,如果不在世界中心,他会向一边偏移。旋转更是地狱,他会直接相对于原点旋转到其他的象限……
所以,有没有什么好办法可以让模型相对于自己的中心缩放和旋转呢?简单,改变参照物。如果这个时候我们不再用世界原点作为参照物,而是给每个模型也设置一个模型原点的位置,让这个模型的所有点相对于他自己的原点进行变化,那不就可以实现了嘛。于是就诞生了物体空间(局部空间)。
那么我们现在终于能够正确且简单的表达物体在世界中的位置、大小和旋转了,理论上来说已经完美了。但,真的如此吗?
果然我们又遇到了新的问题,三维世界是表达出来了,但是我们总要有一个观察者的视角吧。诚然,我们可以把摄像机也作为一个物体放进世界中,以此来表示和世界的关系。但这毕竟是相机,属于特殊视角,是我们最后输出整个场景作为视频的媒介。假如说,我想要实现一个戴着碎裂眼镜的效果,那是不是就需要一个相对于视角静止的坐标系空间了?
这次我猜你已经可以抢答了!为了使用上的方便,我们直接给摄像机的物体空间进行特殊规定吧:
我们规定摄像机的中心为原点,而整个场景世界随着相机的变换而相对于这个相机来进行变换。这有点像是回归第一人称了,我永远不动,整个世界相对于我在动。有了这个空间我们可以很简单的实现一些相对于视角静止的东西,比如UI页面之类的。这就是摄相机空间了。
那么最后,我们只剩一个最困难的问题了:
首先在我之前的文章【入门】PBR和NPR 了解不同风格渲染中有提到:
使用基于兰伯特光照模型得到的 NDotL(法线方向点乘光入射方向)可以计算出一个物体的顶点光照结果。
所以我们可以得出结论,只需要改变模型的法线,就可以改变模型最终的光照效果。这就引出了一个新的概念:法线贴图。
首先,法线贴图是做什么的?
我们的模型为了节省性能消耗,往往面数不会做的特别高,但是这就会导致模型的细节减少,尤其是对应的光照效果大打折扣。那么有没有什么办法可以在性能开销不超标的情况下实现光照细节呢?有,答案就是,我们可以先做出面数非常多,非常精细的模型,然后将他的法线信息全部转换成xyz坐标,最后进行最小最大值映射之后直接存入到模型对应贴图的RGB三个通道中。这样就可以将高精度模型的法线信息存入一张图片的每个像素点中。而这张图片就是所谓的法线贴图
那么我们该如何在低精度模型上还原这些信息呢?
本质上其实还是相对位置的问题,我们保存高精模型的法线的时候,是直接存在贴图当中了,那么我们还原的时候肯定要在同样的坐标系环境下才能正确还原。那么保存的时候是什么坐标系呢?
我们将法线的xyz存在了贴图当中,那么这个位置的变换肯定少不了模型的UV坐标。
我们的顶点现在拥有原本的低精度模型法线和UV,那么UV本质就是贴图映射到模型的一个二维坐标系,它本身就带有两个轴向,我们只需要将平面的UV轴变换到模型上再附加上顶点的法线,就成功的凑齐了一个原点和三个轴向,这也是我们保存法线贴图时无意间拼凑出来的一个空间坐标系,这个坐标系也就是所谓的切线空间。
接下来只需要在这个切线空间下对法线贴图的每个像素的rgb进行xyz坐标的还原,就可以得到一份存在于切线空间中的高精度模型法线了,最后只需要在切线空间中进行对应的光照和切线空间法线的点乘,就可以在低精度模型上复原高精度的光照效果了。