图形学—渲染管线简介

图形学—渲染管线简介

Archer阿澈 Lv1

本文主要介绍CPU到GPU的渲染管线各个阶段及常用概念。

概念阶段

《Real Time Rendering》将渲染流程分为以下三个阶段:

1. 应用阶段(Application Stage)

在CPU上执行,这一阶段主要执行四个任务:

  • 准备场景逻辑数据:
    在CPU侧准备好摄像机属性,光源属性,模型信息等基本数据。
  • 粗粒度剔除:
    通过一些逻辑判断预先在CPU端将完整不可见的物体直接剔除,减少提交到 GPU 的绘制调用(Draw Call)和数据量,常见的 CPU 侧剔除包括视锥剔除(Frustum Culling),遮挡剔除(Occlusion Culling)等。
  • 设置模型渲染状态:
    定义场景中模型的渲染方式。材质,纹理,着色器都属于模型的渲染状态。
  • 调用Draw Call:
    通知GPU根据场景逻辑数据和模型渲染状态执行一次完整的绘制流程,这个完整的绘制流程就是GPU渲染管线。

2. 几何阶段(Geometry Stage)

在GPU上执行,根据应用阶段输出的几何信息绘制一些点,线,三角面,即渲染图元(rendering primitives)。主要任务为:将顶点坐标变换到屏幕空间并输出顶点属性数据传递给下一阶段。

渲染图元(rendering primitives):渲染图元是GPU进行渲染的基本几何单位,GPU通过处理这些基本图元(如点、线、三角形)将3D模型转换为2D影像,最常见的渲染图元是三角形。

通俗来讲,我们可以把这个阶段想象为GPU利用CPU提供的几何信息绘制一个网格线框的过程。

3. 光栅化阶段(Rasterizer Stage)

在GPU上执行,对几何阶段输出的逐顶点数据(顶点属性)进行插值得到逐像素数据并进行着色计算,然后在物理设备上输出像素,渲染出最终的图像。

GPU渲染管线

几何阶段和光栅化阶段组成了完整的GPU渲染管线,应用阶段调用Draw Call时就会启动GPU渲染管线,其具体的执行流程图如下:

00000000
接下来我们详细介绍其中的各个流水线阶段。

基础流程

1.顶点着色器(Vertex Shader)

顶点着色器是流水线的第一个阶段,它主要处理CPU提供的模型中的顶点数据,模型中的每个顶点都会并行的调用一次顶点着色器
顶点着色器需要完成的主要任务是坐标变换,逐顶点光照和计算后续阶段所需数据。其中坐标变换表示对顶点的位置坐标进行某种变换,即改变顶点位置。一般来讲,这一步指的是将顶点坐标从模型空间变换到齐次裁剪空间的操作。除此之外也可以用来模拟一些特殊效果,比如顶点动画。但不管我们采用什么样的变换计算方式,顶点着色器最终会将输出的位置坐标视为齐次裁剪空间下的坐标,并由硬件执行透视除法,得到归一化设备设备坐标(Normalized Device Coordinate, NDC,后续简称NDC)

归一化设备坐标系(NDC,Normalized Device Coordinates)

归一化设备坐标系(NDC,Normalized Device Coordinates)的范围可以用数学公式表示。NDC 坐标是经过投影变换和透视除法后的坐标,范围固定在一个标准化的立方体或长方体内,具体范围如下:

  • OpenGL NDC 坐标范围
  • DirectX / Vulkan NDC 坐标范围

00000013

此处涉及的空间,坐标和变换的概念以及透视除法的具体算法在这篇文章中有详细介绍。

这一阶段可以编程,并且必须手动实现。

2.曲面细分着色器(Tessellation Shader)

用于细分图元,可编程,但非必须实现。本文暂不详细介绍。

3.几何着色器(Geometry Shader)

用于执行逐图元着色操作,或者生产更多的图元,可编程,但非必须实现。本文暂不详细介绍。

4.裁剪(Clipping)

场景所在的空间是无限大的,但是摄像机视野范围是有限的,不会覆盖所有的图元。而一个图元与摄像机的视野范围的关系有三种:完全在视野内,完全在视野外,部分在视野内。裁剪这一流水线阶段的主要任务是将完全在视野外的图元删除,并将部分在视野内的图元重构:剔除其中坐标在NDC范围外的顶点,新增顶点来重构被裁剪的图元。
00000015
这一阶段不可编程,但可配置裁剪方式。

5.屏幕映射(Screen Mapping)

将NDC范围内的顶点坐标的xy分量构成的二维坐标变换(实际为缩放)到屏幕坐标系中。屏幕坐标系是一个二维坐标系,其坐标范围与显示画面的分辨率相关:
00000014

00000016

这一阶段不可编程也不可配置,是固定阶段。

6.三角形设置(Triangle Setup)

从顶点数据计算图元边界的表示方式,从而得到边界像素的坐标信息,这一信息主要用于下一阶段。
这一阶段不可编程也不可配置,是固定阶段。

7.三角形遍历(Triangle Traversal)

检查每个像素是否被一个图元所覆盖,如果是则生成一个片段(Fragment),每个片段的属性都是通过对顶点属性插值得到的
下图展示了片段生成和顶点属性插值的一个示例。
00000018

片段(Fragment)是一个抽象概念,与像素并不同义,片段是包含了像素在内的很多属性的集合,包括但不限于像素屏幕坐标,深度信息,以及几何阶段输出的顶点属性,如法线和纹理坐标等。
具体的顶点属性插值算法请见这篇文章。

这一阶段不可编程也不可配置,是固定阶段。

8.片段着色器(Fragment Shader)

最重要的可编程阶段之一,绝大多数重要渲染技术都在这个阶段执行。片段着色器执行逐片段的着色(Shading),输出结果即为屏幕上每个像素实际显示的颜色。与顶点着色器的执行方式类似,三角形遍历阶段输出的每个片段都会并行的调用一次片段着色器

此处涉及的像素颜色值计算逻辑,即着色(Shading)在这篇文章中有详细介绍。

这一阶段可以编程,但不是必须实现。

9.逐片段操作(Per-Fragment Operations)

主要任务是对每个片段顺序执行模板测试和深度测试,若片段通过了这两个测试,则将片段颜色值与颜色缓冲区中的颜色值进行混合

9.1 模板测试(Stencil test)

模板测试的逻辑流程如下:

00000021

模板测试会读取模板缓冲区对应片段位置的模板值,将其与一个可配置的参考值(reference value)进行比较,比较函数由开发者配置。如果片段没有通过测试,片段就会被舍弃。模板测试失败和通过时均可配置不同的更新逻辑和更新值。
相比于深度测试,模板测试更加灵活,可以实现很多高级渲染效果,比如阴影和轮廓的渲染。

9.2 深度测试(Depth test)

深度测试的逻辑流程如下:

00000022

深度测试会读取深度缓冲区对应片段位置的深度值,将其与该片段的深度值进行比较,比较函数由开发者配置。如果片段没有通过测试,片段就会被舍弃。若深度测试失败,则无法更新深度缓冲区;若深度测试通过,则可选择是否更新深度缓冲区,更新值不可配置。
值得注意的是,即便没有开启深度测试,也可选择是否更新深度缓冲,这是深度测试与模板测试的不同点。

9.3 混合(Blend)

混合操作的逻辑流程如下:

00000023

混合操作会读取颜色缓冲区对应片段位置的颜色值,将其与该片段的颜色值进行插值混合,混合方式和混合因子均可配置,混合结果会用于更新颜色缓冲区。
混合通常用于实现半透明物体渲染和图层叠加效果。

总结

各个阶段开发者的控制权限:

流水线阶段 可编程/可配置/固定 是否必须实现
1.顶点着色器(Vertex Shader) 可编程
2.曲面细分着色器(Tessellation Shader) 可编程
3.几何着色器(Geometry Shader) 可编程
4.裁剪(Clipping) 可配置
5.屏幕映射(Screen Mapping) 固定
6.三角形设置(Triangle Setup) 固定
7.三角形遍历(Triangle Traversal) 固定
8.片段着色器(Fragment Shader) 可编程
9.逐片段操作(Per-Fragment Operations) 可配置

常用名词和概念 TODO:

Draw Call

CPU调用图形接口,命令GPU进行渲染操作就是Draw Call。

命令缓冲区(Command Buffer)

命令缓冲区包含了一个命令队列,CPU向其中添加命令,GPU从其中读取命令。如果没有命令缓冲区,那么CPU需要等待GPU完成上一个渲染任务才能再次发送渲染命令。
命令缓冲区中的命令有很多种类,包含改变渲染状态(改变着色器,改变纹理等)命令以及Draw Call等。

00000001

批处理(Batching)

在命令缓冲区的模型下,CPU提交Draw Call的速度通常是远低于GPU实际执行渲染命令的,一个显然的优化方法是将Draw Call合批,比如将多个Mesh在CPU内存中合并(适用于静态物体)。

  • 静态批处理
  • 动态批处理

着色语言(Shading Language)

  • GLSL(OpenGL Shading Language)是跨平台的着色语言,但这种跨平台性是由于OpenGL没有提供着色器编译器,而是由显卡驱动来完成着色器的编译工作。换句话说,GLSL是依赖硬件而非操作系统的着色语言。由于GLSL编译器由显卡供应商实现,其具体编译结果将受到硬件影响。

  • HLSL(High Level Shading Language)是DirectX使用的着色语言,编译器由微软实现,仅支持Windows,XBox等平台。在编译器版本相同的情况下,就算使用不同的硬件,相同着色器的编译结果也一定相同。

  • CG(C For Graphic)Nvidia开发的跨平台着色语言,语法与HLSL非常像,可以轻松翻译成HLSL代码。

  • Title: 图形学—渲染管线简介
  • Author: Archer阿澈
  • Created at : 2023-09-20 18:04:21
  • Updated at : 2023-09-20 18:04:21
  • Link: https://www.archer-du.top/2023/09/20/Tech/ComputerGraphics/Render_Pipeline/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments