渲染管线噔噔噔
发布时间:2026/8/25 13:31:49 作者:尧图编辑部 阅读量:1,286

一、前言这里是随机一次的梦到哪句讲哪句环节二、渲染管线简要描述1.应用阶段决定并准备要画什么例如更新场景、摄像机、动画、模型和材质然后提交绘制命令。应用阶段决定画什么2.几何阶段把模型的 3D 顶点经过位置变换、裁剪、组装等处理变成准备投影到屏幕上的三角形数据。几何阶段决定形状和位置3.光栅化阶段把这些三角形转换成屏幕上的片元并通过片元着色、深度测试、混合等步骤得到最终图像。光栅化阶段决定哪些像素显示什么颜色三、细嗦应用阶段我们按照流程从头到尾来说说应用阶段搞什么东东1.首先由玩家操作键盘、鼠标或者触摸输入2.更新各种状态角色位置、粒子、物理运动、摄像机位置方向视野、动画3.剔除摄像机看不到的物体4.使用已经加载好的模型、纹理和材质并更新本帧变化的矩阵、动画、颜色等参数5.安排绘制顺序6.设置渲染状态意思就是用什么规则什么资源去做渲染这个工作7.提交Draw Call但是这个命令仅仅会指向一个需要被渲染的图元 (primitives) 列表而不会再包含任何材质信息这是因为我们已经在上一个阶段中完成了注意对于模型、纹理材质这些东西只有首次加载的时候写入系统内存然后再加载到显存里因为显卡读取显存更快而且大多数显卡对系统内存是没有访问权限的还有在把这些数据从系统内存加载到显存后并不是说就可以把这些数据从系统内存删除了因为cpu可能也需要调用他们他们从磁盘加载过来是很费劲的四、几何阶段的解读几何阶段主要做的是对每个顶点进行从模型空间转换到齐次裁剪空间接着通常再由硬件作透视除法最终得到归一化的设备坐标。具体过程是这样的模型空间–世界空间–观察空间–裁剪空间1.读取DrawCall命令将获得的数据构成三角形2.顶点着色器处理将顶点的坐标转换、变换法线、计算逐顶点光照、计算顶点颜色3.曲面细分着色器(可选)把一个三角形细分成很多三角形4.几何着色器(可选)增加、删除或修改图元图元说的就是三角形5.裁剪三角形GPU 判断三角形是否超出摄像机的可视范围。这和应用阶段的物体剔除不同应用阶段判断整个物体要不要提交 Draw Call几何阶段判断物体内部的三角形如何裁剪6.透视除法和屏幕映射GPU 将裁剪空间坐标转换为屏幕坐标产生近大远小的透视效果。这时三角形已经知道三个顶点在屏幕上的位置每个顶点对应的 UV、颜色、法线等数据这里的透视除法就是将xyz3个坐标分别除以第四个分量ww初始是1经过投影矩阵后被计算出来7.交给光栅化阶段几何阶段最后输出一批已经确定位置和形状的三角形以及每个顶点的附加数据后续光栅化阶段会把三角形覆盖的区域转换成片元继续执行片元着色器五、光栅化阶段干了什么1.转换到屏幕坐标几何阶段经过透视除法后得到 NDC 坐标光栅化阶段再把它转换成实际屏幕坐标。NDC坐标指的就是透视除法计算后得到的坐标也是归一化坐标但是和普通的归一化0~1不一样它是-1~12.确定三角形覆盖的范围并确定范围内的片元片元就是可能称为像素点的一个东西在采样点也就是还没被绘制颜色的像素点这个没被处理的像素点的中心要是在三角形内部那就被确定为一个片元但是片元不一定最终被绘制成像素点一个像素点的位置可能有多个片元但是只有最靠前的片元才会被处理为像素3.插值顶点数据三角形的三个顶点通常分别有不同的UV 坐标顶点颜色法线深度其他自定义数据GPU 会根据片元在三角形中的位置对这些数据进行插值。UV 和法线也会被插值。透视场景下通常使用透视校正插值。4.执行片元着色器片元着色器通常对每个片元执行一次负责计算颜色采样纹理计算光照混合顶点颜色处理透明度生成法线贴图效果丢弃某些片元5.逐片元操作对每个片元进行进行深度、模板等测试GPU 判断这个片元是否应该保留深度测试是否被前面的物体遮挡模板测试是否允许写入指定区域剪裁测试是否在有效绘制区域内透明度测试透明片元是否丢弃6.颜色混合如果物体是透明的GPU 会把新颜色和已经存在的颜色混合最终颜色 新颜色 × 透明度 旧颜色 × (1 - 透明度)注意上述的这个顺序不统一有的GPU会在执行片元着色器前先进行逐片元操作因为当 GPU 在片元着色器阶段花了很大力气终于计算出片元的颜色后 却发现这个片元根本没有通过这些测试 也就是说这个片元还是被舍弃了 那之前花费的计算成本全都浪费了对于一个充分发挥性能的GPU当然是提前知道哪些片元要操作在Unity 给出的渲染流水线中 我们也可以发现它给出的深度测试是在片元着色器之前。这种将深度测试提前执行的技术通常也被称为Early-Z技术但是也会出现一些问题如果你提前测试深度有一个镂空的叶子挡在墙的前面在镂空的部分是透明的像素这个部分应该是要显示后面的墙但是提前测试的时候会告知后面的片元着色器这里有片叶子在墙的前面但是不告诉它叶子是镂空的结果片元着色器就只绘制了镂空的叶子但是镂空的部分没有显示后面的墙。按正常的流程走的话这里片元着色器会把镂空的部分的像素clip去除掉用后面的墙来填充因此现代的 GPU 会判断片元着色器中的操作是否和提前测试发生冲突如果有冲突就会禁用提前测试。但是 这样也会造成性能上的下降 因为有更多片元需要被处理了。 这也是透明度测试会导致性能下降的原因。六、处理DrawCall我们通过三个问题来了解DrawCall的处理过程1.在这个渲染流程中CPU和GPU是如何并行工作的命令缓冲区CPU提交的DrawCall命令会放入这个缓冲区队列中CPU不用管GPU是不是闲置的我只需要把任务丢进这个缓冲队列其他的GPU你自个看着办当然这个缓冲队列不止放DrawCall命令更换着色器或者纹理的命令也在这里面2.为什么DrawCall过多会影响帧率帧率是由cpu和gpu共同主导的当cpu负担很大需要制作很多DrawCall命令的时候gpu游刃有余说C哥你行不行啊这点像素我洒洒水就绘制完了这时候就是cpu耗时长影响帧率。3.如何减少DrawCall这个问题你要先知道DrawCall是怎么来的我们应用阶段得知DrawCall是我们C哥根据场景状态准备好渲染资源和参数然后向G哥提交Draw Call对于同一套渲染规则可以合并在一起做成一个DrawCallGpu一趟就跑出来了而不同规则就会导致生成不同的DrawCall我们要解决的就是怎么让相同规则的一起塞进一个DrawCall里让G哥来绘制4.总结Draw Call是CPU提交给GPU的绘制命令不是CPU计算顶点后生成的结果。减少Draw Call的关键是让更多物体共享同一套Shader、材质和渲染状态并通过合并网格或实例化在一次绘制命令中处理更多物体。最核心的条件是这些物体必须能够使用同一套渲染规则在一次命令中被 GPU 绘制。细节分析1.要使用相同的Shader或者Shader变体例如都使用同一种光照 Shader。如果一个用标准材质、一个用透明 Shader通常不能直接合并。2.渲染状态相同包括深度测试方式是否写入深度透明混合方式背面剔除方式渲染通道图元类型等3.材质和纹理共享最简单的情况是使用同一个材质和纹理。如果纹理不同也可以通过纹理图集Texture Array在 Shader 中根据索引选择纹理让它们共享一次绘制。4.必须属于同一个渲染Pass普通颜色绘制、阴影绘制、深度绘制通常是不同 Pass不能简单合成一个 Draw Call。5. 几何数据能否合并把两个箱子的顶点数据拼成一个大网格6.物体间的差异能否作为数据传入差异比如这两个箱子可以拼成一个大网格但是需要位置数据来区分他们的差异7.物体的绘制顺序能否合并不透明的物体可以调整顺序来按材质合批但是透明的物体不能随意合并因为他的绘制受远近顺序影响满足上述条件的合批的方案有如下StaticBatch / DynamicBatch / GPUInstancing七、总结今天梦到渲染管线了你梦到了吗