type
status
date
slug
summary
tags
category
icon
password
这里写文章的前言:
一个简单的开头,简述这篇文章讨论的问题、目标、人物、背景是什么?并简述你给出的答案。
可以说说你的故事:阻碍、努力、结果成果,意外与转折。
📝 主旨内容
观点1
引用的话语
观点2
引用的话语
🤗 总结归纳
总结文章的内容
📎 参考文章
- 一些引用
- 引用文章
综述
什么是渲染管线
将一个三维场景渲染成二维图像的完整过程
从一系列的顶点、纹理等信息出发,把这些信息最终转换成一张人眼可以看到的图像
整个过程由CPU和GPU共同完成
渲染流程主要分为三个阶段: 应用阶段、几何阶段、光栅化阶段
应用阶段(Application Stage)
应用主导, CPU负责实现,开发者具有绝对控制权
- 准备场景数据:摄像机位置、视锥体、场景中的模型、光源
- 粗粒度剔除(culling):把不可见的物体剔除出去,不需要移交到几何阶段处理
- 设置好每个模型的渲染状态: 如使用的材质(漫反射颜色、高光反射颜色)
图像纹理、shader等, 输出渲染所需的几何信息——渲染图元
渲染图元:可以是点、线、三角面等, 传递到几何阶段
几何阶段(Geometry Stage)
GPU进行
处理每个渲染图元,进行逐顶点、逐多边形操作
- 把顶点坐标变换到屏幕空间中,再交给光栅器进行处理
对输入的图元进行多步处理后,输出屏幕空间的二维顶点坐标、每个顶点对应的深度值、着色器等,传递到下一阶段
光栅化阶段(Rasterizer Stage)
GPU进行
使用几何阶段传递的数据来产生屏幕上的像素,并渲染出最终的图像
- 决定每个渲染图元中的哪些像素应该被绘制在屏幕上, 上一阶段得到的逐顶点数据(如纹理坐标,顶点颜色等)进行差值,然后再进行逐像素处理
CPU和GPU之间的通信
渲染流水线的起点是CPU, 应用阶段
把数据加载到显存中
从硬盘(HDD)→系统内存(RAM)→显存(VRAM)
- 所有数据都要加载到RAM中
- 网格和纹理要加载到显卡上的存储空间显存中
- 为什么要加载到显存中?
因为显卡对于显存的访问速度更快,
而且大多显卡对ram没有直接的访问权限
- TIPS
大多数据加载到显存中后,CPU可以删除
但是部分数据仍然要保留,如网格可以进行碰撞检测
HDD→RAM过程相当耗时
设置渲染状态
这些状态定义了场景中的网格是如何被渲染的
具体使用了哪个顶点着色器/片元着色器、光源属性、材质等
调用 DrawCall
由CPU发起, GPU接受, 命令仅仅指向一个需要被渲染的图元列表,不会包含任何材质信息
GPU流水线
几何阶段
输入装配器阶段
从显存中读取几何数据(顶点、索引),并将他们装配为几何图元
顶点着色器Vertex Shader
完全可编程
图元被装配完毕后,其顶点被送入顶点着色器
可以把顶点着色器看成一种输入与输出均为单个顶点的函数
每个要被绘制的顶点都须经过顶点着色器
每个顶点在这里进行空间变换、顶点的着色等
曲面细分着色器 Tessellation Shader
完全可编程
利用镶嵌化处理计数对网格中的三角形进行细分,从而增加物体表面的三角形数量
并将这些三角形偏移到适当的为止,使网格表现出更加细腻的细节
几何着色器 Geometry Shader
完全可编程
输入为完整的图元,执行逐图元的着色操作
可以创建或销毁几何体,可以利用几何着色器将输入的图元拓展为一个或多个其他图元,抑或根据某些条件而选择不输出
裁剪 Clipping
可配置
将不再摄像机视野内的顶点裁剪掉, 剔除某些三角图元面片
(如果一个三角形一部分在摄像机视野内,另一部分不在,也需要将不在的那部分剔除。裁剪算法:找到面片和摄像机边缘的所有交点,并将这些顶点按顺序组织成新的裁剪多边形,再将该多边形分解为多个三角形。)
可以使用自定义的裁剪屏幕来配置裁剪区域
屏幕映射 Screen Mapping
GPU固定实现
把每个图元的坐标转换到屏幕坐标系中
光栅化阶段
三角形设置 Triangle Setup
GPU固定实现
此阶段会计算光栅化一个三角形所需的信息
根据几何阶段传进来的三角形顶点,计算每条边上的像素坐标
三角形遍历 Triangle Traversal
GPU固定实现
检查每个像素是否被一个三角形网格覆盖,被覆盖的话就会生成一个片元
片元着色器 Fragment Shader
完全可编程
对每一个像素片段进行处理,根据顶点的差值属性作为输入来计算出对于的像素颜色
逐片元操作 Per-Fragment Operation
可配置
深度缓冲、模板测试、混合等
参考资料:
《DirectX 12 3D 游戏开发实战》
《UnityShader 入门精要》