2022年元宇宙概念突然火爆,一系列基于虚拟形象的社交app涌上市场,各大互联网公司也积极跟进,例如腾讯超级QQ秀,百度希攘,Meta Horrizon平台等等,其目的都是在虚拟世界建立与用户的对应关系,而在产品形态上,不一而同采用或者倾向于构建近似于3D开放世界的场景,以供用户化身数字形象后进行探索。
基于目前的产品形态分析,其背后的技术本质上与大部分游戏类似,都是基于3D渲染技术进行实现。不同的是,元宇宙业务更聚焦于移动设备,同时需要与现有业务app结合,例如腾讯超级QQ秀实际上是在QQ移动端中开辟了一块业务。因此对于移动开发者们来说,了解一些3D渲染技术对于未来工作将大有裨益。
而随着2023年苹果vision pro设备的发布,再一次将XR应用带入消费者视野。XR应用的背后除去硬件层面及空间计算层面的技术外,还有一大部分也是与3D渲染相关,对于未来想尝试XR应用开发的开发者们来说,学习一些渲染知识也是必要的。
本文将介绍一些与3D开发相关的基础概念。
1. 渲染:从加载到上屏
1.1 场景Scene
3D相比于2D,是更加直接地对物理世界的模拟。在3D场景中我们可以找到与物体世界一一对应的概念。
1.1.1 天空盒SkyBox
天空盒可以简单地理解成背景环境,比如我们的天空、大地等等。天空盒一般指的是非常远的,几乎不怎么发生变化的东西。但是不同于2D的,背景只是一个2D图片,3D场景的背景应该是立体环绕的。
在3D渲染中,要去实现一个这样的背景就会用到天空盒技术。所谓的天空盒其实就是将一个立方体展开,然后在六个面上贴上相应的贴图。在实际的渲染中,将这个立方体始终罩在摄像机的周围,让摄像机始终处于这个立方体的中心位置,然后根据视线与立方体的交点的坐标,来确定究竟要在哪一个面上进行纹理采样。
1.1.2 环境光Light
正如现实世界,在一个完全没有光线的地方,只能看到漆黑一片一样。3D场景也需要添加光线才能看到场景中的物体 。光照可以分为平行光、点光源、间接光等等,如下图所示。其中接触比较多的IBL光照,就是一种用环境立方体贴图模拟自然环境光照的技术,可以把贴图的每个像素看作一个光源。
1.1.3 摄像机Camera
在3D世界里摄像机类似于人类的眼睛,屏幕上呈现的画面,就是摄像头拍摄到的画面。当然在3D场景中并不是真的有摄像机这个实体模型,摄像机实际上就是包括位置、姿态、视角、光圈、远近平面在内的一系列参数的合集,通过这些参数可以计算出坐标转换的矩阵,从而把3D场景所有物体的坐标转换到一个成像平面上。这个过程稍后详细介绍。
1.1.3.1 摄像机位置如何确定
- 位置 :即一个指向摄像机的向量,如(0.0f, 0.0f, 2.0f)
- 方向 :摄像机指向哪个方向,即摄像头看向的点(Target)和摄像机位置(Position)两点构成的向量。比如现在我们让摄像机指向场景原点:(0, 0, 0),摄像机方向就是cameraPos - cameraTarget。
- 右轴 :代表摄像机空间的x轴的正方向 。为计算右向量,我们会先定义一个上向量(Up Vector,一般就是y轴正向量(0,1,0))。然后把上向量和第二步得到的方向向量进行叉乘。两个向量叉乘的结果会同时垂直于两向量,因此我们会得到指向x轴正方向的那个向量。
- 上轴:把右向量和方向向量进行叉乘即可。
1.1.3.2 LookAt矩阵
通过以上几个步骤,即可获得以摄像机为中心的一个摄像机坐标轴 。从而我们可以获得一个LookAt矩阵 ,通过该矩阵,我们可以将3D场景所有物体的坐标转换为以摄像头为原点的坐标。
其中R 是右轴,U 是上轴,D 是方向向量,P是摄像机位置。
1.1.4 3D实体(Entity)
即加载进**3D场景的模型&&,比如游戏中的人物,建筑,地面,道具等等都是一个3D实体。3D实体在场景中的运动可以拆解成位移、旋转、缩放三个基本操作。
以上即是一个简单3D场景的主要组成部分,通过将这些元素放置到指定的空间坐标中(x,y,z),即可构成更为复杂的系统。但是由我们的显示设备是2D屏幕,要如何将3D场景转换成可以在2D屏幕渲染的数据呢?
1.2 坐标系统
由于显示设备是2D屏幕,因此不管如何最终我们还是需要将3D的场景在2D屏幕上进行渲染。这里必然涉及到一系列的转换流程。来将3D无限空间的位置坐标转换到2D有限屏幕空间上。
1.2.1 坐标系统分类
对我们来说比较重要的总共有5个不同的坐标系统。
1.2.1.1 局部坐标系
3D物体自身的坐标系统,通常美工在输出一个3D模型时,会将定义的3D模型几何中心放到局部坐标的原点位置。
1.2.1.2 世界坐标系
3D世界的坐标系,所有物体的位置都是相对于世界坐标的原点进行摆放。当我们把模型放到世界坐标系中,模型就在世界坐标系里有了坐标。比如把物体A放在了距离原点X轴(1,0,0)的位置。
1.2.1.3 观察坐标系
观察坐标系是将世界坐标转化为用户视野前方的坐标 。因此观察空间就是从摄像机的视角所观察到的空间。而这通常是由一系列的位移和旋转的组合来完成,平移/旋转场景从而使得特定的对象被变换到摄像机的前方。
1.2.1.4 裁剪坐标系
屏幕范围是有限的,类似于人的视野是有限的,因此总有一部分画面要被裁减掉 。为了将顶点坐标从观察变换到裁剪空间,我们需要定义一个投影矩阵(Projection Matrix),它指定了一个范围的坐标,比如在每个维度上的-1000到1000。投影矩阵接着会将在这个指定的范围内的坐标变换为标准化设备坐标的范围(-1.0, 1.0)。所有在范围外的坐标不会被映射到在-1.0到1.0的范围之间,所以会被裁剪掉。
1.2.1.5 屏幕坐标系
最终渲染在2D屏幕上的屏幕坐标系。
1.2.2 坐标变换(MVP变换)
MVP变换的目的是将一个3D场景数据转换成最终渲染在2D屏幕上数据。
1.2.2.1 模型变换(Model Matrix)
通过平移、缩放、旋转(TRS操作),将物体放置到世界空间的指定位置形成的变换矩阵。
1.2.2.2 观察变换(View Matrix)
通过TRS操作,将物体转换到摄像头坐标空间而形成的矩阵,就是观察矩阵。观察矩阵就是前文我们讲解的LookAt矩阵。
1.2.2.3 投影变换(Projection Matrix)
将物体坐标从观察空间坐标系转换到裁剪坐标系而生成的矩阵就是投影变换矩阵。
- 正交投影
正射投影矩阵定义了一个类似立方体的平截头箱,它定义了一个裁剪空间,在这空间之外的顶点都会被裁剪掉。创建一个正射投影矩阵需要指定可见平截头体的宽、高和长度。在使用正射投影矩阵变换至裁剪空间之后处于这个平截头体内的所有坐标将不会被裁剪掉。
- 透视投影
如果你曾经体验过实际生活给你带来的景象,你就会注意到离你越远的东西看起来更小。这个奇怪的效果称之为透视(Perspective)。
- fov值,它表示的是视野(Field of View),并且设置了观察空间的大小。如果想要一个真实的观察效果,它的值通常设置为45.0f,但想要一个末日风格的结果你可以将其设置一个更大的值。
- 宽高比,由视口的宽除以高所得。
- 近 和远平面。我们通常设置近距离为0.1f,而远距离设为100.0f。所有在近平面和远平面内且处于平截头体内的顶点都会被渲染。
我们为上述的每一个步骤都创建了一个变换矩阵:模型矩阵、观察矩阵和投影矩阵。一个顶点坐标将会根据以下过程被变换到裁剪坐标,这个过程就是MVP变换。最后将(-1,1)坐标范围映射到屏幕像素,就得到了每个物体在屏幕上的坐标。
2. 深入了解3D模型:网格、材质与纹理
对于一个3D应用而言大部分时候操作的都是3D模型,包括模型位置调整、运动、换装等等。因此我们有必要对模型再深入地了解一下。
简单来说,一个3D物体可以拆解出三个部分:
- Mesh:网格数据,通过一些基础图元(例如三角形)定义模型形状;
- 材质:定义了Mesh渲染时颜色计算的相关参数,比如一个基于物理的渲染中,pbr材质包括基础颜色、反射度、金属粗糙度、法线贴图等等参数,这些参数会在光照计算时共同作用,最终形成物体表面的颜色。更详细的材质描述可以参考Filament官方材质文档;
- 纹理:物体表面的贴图。
下图是一个简单的Glb模型的拆解。
例如,通过更换材质上附着的纹理贴图,即可实现服装模型的更新,比如把篮球服的颜色纹理贴图换成蓝色图,就可以得到一件蓝色的篮球衣。
3. 运动:骨骼与表情
前面提到的都是静态的渲染,而在3D场景中模型除了在空间中的位置变化,其本身也是可以运动的,比如人物的摆手、奔跑动作等等。在3D场景中,制作动画的技术主要包括以下两种:
- 骨骼动画
- blendshape形变动画
3.1 骨骼动画
模型Mesh定义了模型静态的初始状态下的形状,而模型运动不需要每次都去修改Mesh的形状,只需要将Mesh与骨骼点进行绑定 (这个过程称为骨骼蒙皮,这个蒙皮由设计侧制作模型确认)。后续制作模型的动画就只需要通过TRS操作去改变骨骼的位置,即可以影响与骨骼绑定的mesh位置,整个过程与人物关节点运动带动皮肤位置变化是一样的。
而骨骼运动具体是如何影响Mesh,整个计算过程,可以详细阅读一下《gltf格式详解》。可以详细地了解到所有的数据计算过程。
3.2 blendShape动画
Mesh的运动除了有骨骼控制之外,也可以直接通过制作Mesh形变来控制。这个方式就是blendshape动画,通常用于一些比较细致的动画场景,比如面部表情动画。blendshape是通过定义两个极值状态的Mesh位置,然后在两个极值间插值,获得指定状态下的Mesh位置。
比如,眨眼动画,设计侧会定义一个blendShapeEyeBlink,值为0时表示闭眼,值为1时表示睁眼。眨眼动画就是在0~1之间随时间变化,即可实现眨眼。
blendshape技术目前被广泛应用在表情制作中,例如苹果Animoji,定义了52个表情基,通过组合该52个表情基动画,即可让模型面部做出更丰富的表情。
具体计算过程可以详细阅读一下《gltf格式详解》。可以详细地了解到所有的数据计算过程。
总结
以上就是在3D开发中会经常遇到的一些概念,理解了这些概念,完全可以应对一些简单3D场景的开发工作,更多细节感兴趣的同学可以再深入了解。