如何用2D平面展现3D图形
2D图形
在一个平面中有了两个点,知道了他们的XY坐标,就可以把它们链接起来画成一条线
通过控制A和B点的XY坐标可以控制一条线
在3D图像中,点的坐标多了一个Z轴的坐标系
但是在2D的屏幕坐标上不可能有XYZ立体的坐标轴
所以需要图形算法负责把3D坐标“拍平”显示到2D屏幕上,这个叫做3D投影
将3D的点转换为2D的点之后,再用之前链接2D点的方法去连接这些点,这个叫做线框渲染
投射的灵感:两种投影方法
推荐文章:
https://zhuanlan.zhihu.com/p/473031788
总的来说就是把一个3D图形移动到2D的坐标系上,中心对应的坐标系的原点,然后就可以得到这个3D的2D坐标了
如果用光去找一个3D的物体的时候,用一个平面去展示投影,当转动3D物体的时候,投影会看起来像3D物体,尽管投影面是平面。 电脑也是这样去做的将3D转成2D。首先屏幕就是一个2D的投影平面,根据投射的算法就可以将3D转成2D的坐标
正交投影
立方体的各个边在投影中互相平行,可以说利用数学将3D转换成了2D的坐标系
正交投影是一种平行投影,类似用一束平行光把物体的影像垂直地投射到地面上。
透视投射
透视投影可以产生近大远小的效果,就和人类观察世界的方式类似
在真实的3D世界中,平行线段会在远处收敛与一点
为什么复杂图形的绘制要使用三角形
在3D图形学中,我们叫三角形“多边形”
一堆多边形的集合叫做“网格”
网格越密,表面越光滑,细节越多
首先来讲为什么用三角形,而不是正方形
在一个空间中,三个点定义一个平面 如果给定3个3D点,就能画出一个平面。但是四个点就不一定了、 如果是两个点那么不够定义平面,只能够定义线段;如果是四个点那么可能定义的就不仅仅只有一个平面了,所以3是个完美的数字
填充图形算法
扫面线渲染
线框渲染虽然很酷,但是3D图像需要填充
步骤:
- 先铺上一层像素网络
- 扫描线算法,先会去读取多边形的三个点,找出最大和最小的Y值,然后只在这两个点之间进行工作
- 然后算法从上往下,一次处理一行,计算每一行和多边形相交的两个点。扫描线算法会填满两个相交点之间的像素 因为是三角形,如果相交一条边,必然相交另外一条边
抗锯齿
这样的三角形比较丑,因为边缘满是锯齿
一种减轻锯齿的方法叫做抗锯齿
抗锯齿:与其每一个像素都涂成一样的像素,可以判断多边形切过像素的程度来调整颜色。
如果像素在多边形内部直接填充颜色;如果多边形划过像素,那么颜色就会浅一些
遮挡的渲染算法
在3D场景中有很多的多边形,但是只有一部分能看见,因为其他的被遮挡住了。
排序算法(画家算法)
最简单的处理方法
从远到近排列,从远到近渲染,这叫画家算法,因为画家也是先画背景再画更近的 东西
步骤
- 第一步,就是从远到近进行排序(A黄色,B蓝色,C绿色 三个三角形的距离)
- 有序之后,利用扫描线算法进行填充多个多边形,一次填一个。(顺序是从远到近进行填色)
深度缓冲
这个算法和画家算法的思路一样,但是方法不一样
而且深度缓冲算法不需要进行排序,所以它的速度会更快
Z-buffering算法会记录场景中每个像素和摄像机的距离,在内存里存一个数字矩阵
步骤
- 首先,每个像素的距离被初始化为“无限大”,然后Z-buffering从列表里第一个多边形开始处理,也就是A
他和扫描线算法逻辑相同,但是他不是给像素进行填充颜色,而是吧多边形的距离和Z-buffing里面的距离进行对比,他总是记录更低的值
- Z缓冲区完成后,会和“扫描线”算法的改进高级版配合使用,不仅可以勘测到线的交叉点还可以知道某像素是否在最终场景中可见。如果不可见,扫描线算法会跳过那个部分
但是会有一个问题,如果距离相同的话,那么哪个画到上面?
多边形在内存中移来移去,访问顺序会不断变化,所以哪一个花在上面,往往是不可预测的
3D游戏的一个优化:背面剔除
三角形有两面,正面和背面。
游戏角色的头部或地面,只能看到朝外的一面,所以为了节省处理时间,会忽略多边形的背面,减少了一般多边形面数。
但是也有个bug就是从模型外面看的话其实头部和地面会消失
3D场景明暗处理
在3D场景中,物体表面应该有明暗变化。
这次还是拿茶壶来做实验,和之前的例子不一样。这次要考虑的是多边形面对的方向,他们不平行与屏幕,而是面对不同方向。面对的方向叫做“表面法线“
用一个垂直与表面的小箭头来显示这个方向
加一个光源,因为不同多边形面对光源的角度不同,因此会导致箭头的方向和光源照亮的方向重叠越多,代表这个多边形越亮
纹理Textures
纹理在图形学中是指外观,而不是手感。
纹理也有多种算法
纹理映射
最简单的用法
之前我们通过扫描线算法进行填充颜色时,可以看看内存中的纹理图像,决定填充该像素区域时用什么颜色
做到这点,需要将多边形坐标和纹理坐标进行对应
- 多边形坐标和纹理坐标进行对应
- 当决定填充当前像素选择什么颜色时,纹理算法进行查询纹理,从相应的区域取平均颜色,并填充到多边形
GPU:图形处理器
我们可以为这种特定运算进行做专门的硬件来加快速度
其次,我们可以吧3D场景分解成多个小部分,然后进行并行渲染,而不是按顺序渲染。
cpu不是为此设计的,因此图形运算不快,所以计算机工程师为图形做了专门的处理器,叫做GPU"图形处理单元"
GPU在显卡上,周围有专用的RAM,所有网格和纹理都在里面,让GPU的多个核心可以高速访问
参考链接
https://www.bilibili.com/video/av21376839?p=18
本文正在参加「金石计划 . 瓜分6万现金大奖」