3D渲染——光栅化渲染原理解析
前言
随着技术的发展,基于 GPU 的渲染技术得到了广泛应用,日常生活中常见的 3D 动画和游戏都是通过计算机渲染技术来实现。当前主要的 3D 渲染模型包括光栅化渲染和光线追踪两大类,本文主要围绕光栅化渲染进行介绍,描述了简单场景下3D渲染过程,主要帮助读者了解基于光栅化的 3D 渲染原理及过程。本文为系列文章,并在下一篇系列文章中以 Intel Gen12 为例,讲述 GPU 一些基本硬件单元及如何利用硬件加速渲染过程。希望通过这种软件计算 + 硬件实现的方式,让大家了解 GPU 3D 渲染原理及过程。
在渲染过程中,涉及到向量、矩阵等数学知识不再阐述。在后面用到的时候会有提及。 文中选择了一个简单的模型场景,过程也尽可能简化。旨在重点讲述光栅化流程,便于读者理解。 推荐课程 GAMES101,文章后面用到的一些图片出自该课件。
光栅化过程
图0 光栅化示意图
将几何图元(三角形/多边形)投影到屏幕上 将投影之后的图元分解成片段
模型建立
物体和相机的位置已经放好了,那么我们接下来要做的就是要将相机实际看到的内容最终显示到屏幕上。模型是三维的,而最终的成像是二维,所以这其中必然要有投影操作。
正交投影和透视投影
先来看一下透视投影和正交投影的效果图:
图4-1铁轨是平行的,但在透视投影的作用下,原本的平行线在远处变得相交。图4-2是观察正交视图和透视视图来对比两者区别,同样,在透视投影下,会有近大远小的效果,(图中四个顶点坐标分别为(-1, 10, -20), (1, 10, -20), (-1, -1, 0), (1, -1, 0),z 轴俯视观察。
这里没有推导透视投影矩阵,而是直接给出了矩阵变换后的效果图,一是希望读者从直观上感受透视投影的效果,二是文章主要内容是光栅化过程的概述,推导不作为重点。如果想了解透视投影的原理,可以学习《GAMES101》或者从《Fundamentals of Computer Graphics》中寻找答案 针对透视投影的效果,最终呈现出来的就是近大远小的视觉效果 无论是正交投影还是透视投影,我们目前做的都是针对几何图形的变换,但是最终的目的是屏幕显示,屏幕显示必然涉及到分辨率和屏幕尺寸。所以,正交投影和透视投影的最后一步都是标准化(图3-2),最终得到[-1, 1] ^ 3的标准立方体。屏幕上的窗口可以是动态变化的,如:400 x 600,600 x 800等,标准化后通过简单平移 + 缩放即可完成视口变换。
图5-2 最终显示的三角形(透明)
光栅化 & 着色
图6-1
这里先对屏幕做个简单的抽象,将各个像素抽象为正方形,像素中心即为正方形中心,每个小格子就是一个像素,每个小方格子为 1 * 1,像素位于中心,坐标为(x + 0.5, y+0.5) 上一小节提到了透视投影之后,会标准化成 [-1, 1] ^ 3 的标准化立方体,这时先忽略 z 坐标,根据立方体中各个点的 [x, y] 坐标投在屏幕上。当前的[x, y]是标准化坐标,需要做个简单的平移 + 缩放操作,将 x -> width,y -> height,其中 width、height 代表的屏幕中显示窗口大小,这一步叫做视口变换。
图7-1 投影示意图
图7-2 包围盒光栅化
图7-3 包围盒光栅化
首先根据投影后三个顶点的范围确定一个包围盒,这么做的好处是减少搜索范围。 确定了包围盒后,依次判定包围盒中的像素是否在三角形内,这里可以用向量叉乘方法,根据叉乘方向是否同向判定。 对于包含在三角形内的像素,对其进行着色。着色过程中,涉及到纹理坐标、法向量等要素的计算,图7-2中我们知道投影之后的三个顶点坐标、纹理坐标、法向量,但是无法获得三角形内任一点的这些数据,这时候就会用到三角形的重心坐标,利用重心坐标通过插值的方法获得三角形内任一点的数据。比如已知三角形三个顶点的纹理坐标(u, v),想知道三角形内任一点的纹理坐标,就可以通过该点的重心坐标获取,有一点需要切记,这里所说的重心坐标不是投影后的,而是在做透视投影之前的重心坐标,如果要用投影后的重心坐标,需要做修正。对于三角形内法向量计算也是相同道理。
图7-2、7-3考虑的都只针对自身三角形的光栅化,对于两个三角形的重叠部分没有考虑,后面讲的深度缓冲会解决这个问题。 在判定像素与三角形位置关系时,我们判定的是小方格中心点与三角形关系,即使中心点不在三角形内,像素的小方格子仍然会被三角形覆盖,那么小格子是标记为不亮、还是按照被覆盖的面积来着色,这块如果处理的不好很容易出现锯齿,这里就需要反走样技术,这里不再阐述。
深度缓冲
图8-2 最终投影
总结
Vertex Processing: 顶点处理,对空间中顶点进行变换,针对我们例子中简化的两个三角形模型,透视投影包含在顶点变换中。 Rasterization: 光栅化操作,对于我们这个例子就是对两个三角形做透视投影 --> 然后向[x, y]平面做投影 --> 视口变换,然后判定投影后的三角形内包含了多少像素。 Fragment Processing: 像素着色,例子中就是针对投影后两个三角形内的像素进行着色,这里与光照、纹理映射相关,对于三角形任一点的纹理坐标、法向量可以通过三角形顶点的这些信息及三角形重心坐标(透视投影前)计算得到。 Blending: 混合上屏,将最终混合结果填充到图形缓冲区,进而刷到屏幕。
END
🌟 活动推荐
2023 年 5 月 27-28 日,GOTC 2023 全球开源技术峰会将在上海张江科学会堂隆重举行。
为期 2 天的开源行业盛会,将以行业展览、主题发言、特别论坛、分论坛、快闪演讲的形式来诠释此次大会主题 ——“Open Source, Into the Future”。与会者将一起探讨元宇宙、3D 与游戏、eBPF、Web3.0、区块链等热门技术主题,以及 OSPO、汽车软件、AIGC、开源教育培训、云原生、信创等热门话题,探讨开源未来,助力开源发展。
长按识别下方二维码立即查看 GOTC 2023 详情/报名。
微信扫码关注该文公众号作者