做网站js是什么,百度的广告策略,东莞市网络科技有限公司,常宁城乡建设局网站查询前言 在过完games101课程后仍然觉得自己还有许多地方不懂与遗漏#xff0c;以此来补充与复习一些其中的知识。 参考#xff1a;Games101、《Unity Shader 入门精要》
GPU渲染流水线(GPU Rendering Pipeline) ----注#xff1a;Games101课程中所展示渲染流程与书中有所不同以此来补充与复习一些其中的知识。 参考Games101、《Unity Shader 入门精要》
GPU渲染流水线(GPU Rendering Pipeline) ----注Games101课程中所展示渲染流程与书中有所不同大体相同细节展示有所不同这点请看图
这里以《Unity Shader入门精要》中为主介绍如下图 补充绿色表示完全可编程控制黄色表示可以配置但不是可编程蓝色表示由CPU固定实现。实线表示该Shader必须由开发者编程实现虚线表示该Shader是可选的。
----------------------下面说明各阶段
Application应用阶段
渲染流水线的起点是CPU即应用阶段。应用阶段大致可分为以下3个阶段 1把数据加载到显存中 2设置渲染状态 3调用Draw Call 把数据加载到显存中 渲染所需要的数据需要从硬盘传输到系统内存中RAM网格和纹理等数据被加载到显存中。真实渲染中需要加载到显存中的数据还有顶点的位置信息、法线方向、顶点颜色、纹理坐标等。 设置渲染状态 渲染状态可以理解为场景中的网格是怎样被渲染的即使用哪个顶点着色器/片元着色器、光源属性、材质等。如果没有更改渲染状态的话那么所有网格都将使用同一种渲染状态。 下图为同一状态下渲染3个网格。 接下来就是调用Draw Call啦 调用Draw Call 其实Draw Call本质上就是一个命令它的发起方是CPU接收方是GPU。当我们给定了一个Draw Call时GPU就会根据渲染状态例如材质、纹理、着色器等和所有输入的顶点数据来进行计算。
----------关于Draw Call的一些补充---------- Draw Call本身的含义很简单就是CPU调用图像编程接口入OpenGL中的glDrawElements命令。有一个常见的误区时Draw Call中造成性能问题的元凶时GPU认为GPU上的状态切换是耗时的其实真正“拖后腿”的是CPU。 问题一CPU和GPU是如何实现并行工作的 若没有流水线化则CPU需要等GPU完成上一个渲染任务才能再次发送渲染命令这导致效率低下。而解决方法就是使用一个“命令缓冲区” 命令缓冲区包含了一个命令队列CPU向其中添加命令GPU从中读取命令CPU与GPU互不干扰。如下图 黄色方框内的命令就是Draw Call而红色方框内的命令用于改变渲染状态。使用红色方框来表示改变渲染状态的命令是因为这些命令往往更加耗时
问题二为什么Draw Call多了会影响帧率 在每次调用Draw Call之前CPU需要向GPU发送很多内容包括数据、状态和命令等。在这一阶段CPU需要完成很多工作例如检查渲染状态等。当CPU完成这些准备工作之后GPU就可以开始本次渲染了。但是由于GPU的渲染能力很强会导致GPU的渲染速度大于CPU提交命令的速度。如果Draw Call的数量太多CPU就会把大量时间花费在提交Draw Call上造成CPU的过载。如下图 虚线框表示GPU已经完成的命令。此时命令缓冲区已没有可执行的命令GPU处于空闲状态而CPU还没有准备好下一个渲染命令。
问题三如何减少Draw Call 这里仅提一种方法叫做“批处理” 方法。 提交大量很小的Draw Call会造成CPU的性能瓶颈即CPU把时间都花费在准备Draw Call的工作上了。批处理的思想是把很多小的Draw Call合并成一个大的Draw Call。 批处理技术更适合于那些静态的物体。
Geometry Processing几何阶段
几何阶段又细分为以下几个阶段 1顶点着色器 2曲面细分着色器 3几何着色器 4裁剪 5屏幕映射
顶点着色器 顶点着色器Vertex Shader是完全可编程的顶点着色器本身不可以创建或者销毁任何顶点而且无法得到顶点与顶点之间的关系。顶点着色器的主要工作坐标变换和逐顶点光照。如下图
坐标变换在顶点着色器中完成MVP变换把顶点坐标从模型空间转换到齐次裁剪空间。接着通常再由硬件做透视除法最终得到NDC。
曲面细分着色器 一个可选着色器用于细分图元。
几何着色器 一个可选着色器用于逐图元的着色操作或者用于产生更多的图元。
裁剪 裁剪提出的目的是要为了处理掉那些不在摄像机视野范围内的物体。由于我们已知在NDC下的顶点位置即顶点位置在一个立方体内则只需要将图元裁剪到单位立方体内如下图 图片补充和单位立方体相交的图元会被裁剪新的顶点会被生成原来在外部的顶点会被舍弃。
屏幕映射 屏幕映射的任务是把每个图元的x和y坐标转换到屏幕坐标系下。这个过程实际是一个缩放的过程但是屏幕映射不会对输入的z坐标做任何处理。过程如下图 一些补充在OpenGL中屏幕左下角为最小的窗口坐标值在DirectX中屏幕的左上角为最小的窗口坐标值。
Rasterization光栅化阶段
光栅化阶段细分为以下几个阶段 1三角形设置 2三角形遍历 3片元着色器 4逐片元操作
三角形设置 这是光栅化的第一个流水线阶段。上一个阶段输出的都是三角网格的顶点为了得到整个三角网格对像素的覆盖情况我们还需计算每条边上的像素坐标。为了能够计算边界像素的坐标信息我们就需要得到三角形边界的表示方式。这样一个计算三角网格表示数据的过程就叫做三角形设置。
三角形遍历 这个阶段将会检查每个像素是否被一个三角网格所覆盖。如果被覆盖则生成一个片元。这个阶段也被称为扫描变换 这一阶段还会根据三角网格3个顶点信息对整个覆盖区域的像素进行插值利用重心坐标。如下图一个简化的计算过程 这一步的输出得到一个片元序列。但是一个片元并不是真正意义上的像素而是包含了很多状态的集合用于计算每个像素的最终颜色。
片元着色器 片元着色器Fragment Shader是另一个可编程着色器阶段又叫做像素着色器Pixel Shader。片元着色器的输入是上一个阶段对顶点信息插值得到的结果而它的输出是一个或者多个颜色值。 前面的光栅化戒定慧产生一系列的数据信息用来表述一个三角网格是怎天覆盖每个像素的。而每个片元就负责存储这样一系列数据。 如下图 这一阶段可以完成许多重要的渲染技术如纹理采样。 局限它仅可以影响单个片元当执行片元着色器时它不可以将自己的任何结果直接发送给它的邻居们。
逐片元操作 这是真正会对像素产生影响的一个流水线阶段。 这一阶段会有几个主要任务 1进行测试工作如深度测试、模板测试等。 2如果一个片元通过了所有的测试就需要把这个片元的颜色值和已经存储在颜色缓冲区中的颜色进行合并或者说是混合。下图是简化后的逐片元操作所做的操作。
在逐片元操作中的后面的合并操作时对于不透明物体开发者可以关闭**混合Blend**操作。这样片元着色器计算得到的颜色值就会直接覆盖掉颜色缓冲区的像素值。对于半透明物体就需要使用混合操作来让这个物体看起来是透明的。 《Unity Shader入门精要》中前面部分对渲染管线的介绍到此结束。下面是一些额外补充
不同的文章对渲染管线的阶段分配介绍各有不同清楚大体过程即可。系统为了避免我们看到那些正在进行光栅化的图元GPU会使用双重缓冲Double Buffering也就是说对场景的渲染发生在幕后即后置缓冲Back Buffering中。一旦场景已经被渲染到了后置缓冲中GPU就会交换后置缓冲和前置缓冲Front Buffering。鉴于自己总是弄混顶点着色器的作用在此再次总结一下顶点着色器中完成MVP变换将顶点变换至齐次裁剪空间中再由硬件做透视除法得到NDC。接着再由系统做裁剪以及屏幕映射。
下面再放上一些在Games101中渲染管线的图方便作对比 写在最后尽管写了不少中间仍然可能会出现错误后面继续学习发现错误后加以改正。 初次写于2023.10.7