学习Shader-渲染流水线介绍

        有人说,程序员的三大浪漫是编译原理、操作系统和图形学。不管认不认同,我们只是想借此说明图形学在程序员心目中的地位。

        在开始学习之前,我们有必要了解什么是Shader,即着色器。与之关系非常紧密的就是渲染流水线。可以说,没有了解过渲染流水线的工作流程,就无法说自己对Shader已经入门。要怎么学会使用Shader,我们首先要了解Shader是怎么工作的。实际上,Shader仅仅是渲染流水线的一个环节,想要让我们的Shader发挥出它的作用,我们就需要知道它在渲染流水线中扮演了怎样的角色。


        什么是渲染流水线?

        渲染流水线的概念是指将一个三维场景渲染成一张张二维图像投射到电脑屏幕的过程,这个过程通常是由CPU和GPU共同完成的。

        渲染流程分为三个阶段: 应用阶段、几何阶段、光栅化阶段

        应用阶段

        这一部分通常是由CPU负责 ,分为三个主要任务。第一步,准备好场景中需要渲染的数据(视锥体,模型,光源等);第二步,进行粗粒度剔除工作,把那些不可见的物体剔除出去 ,第三步,设置好每个模型的渲染状态(贴图,纹理,shader等),然后输出渲染图元(点、线、三角面等)给下一个阶段。

        几何阶段

        几何阶段的主要任务是将输入过来的图元信息进行多部处理转换成输出屏幕空间的二维顶点坐标、每个顶点对应的深度值、着色等相关信息 ,并传递给下一个阶段。

        光栅化阶段

        这一阶段会将上一个阶段 传递的数据来产生屏幕上的像素,并渲染出最终的图像。

        这里将应用阶段详细的拿出来介绍。

        1.渲染流水线的起点是CPU,所有需要渲染的数据都需要从硬盘中加载到内存中,然后将网络纹理等数据传输到显存中。

纹理所需的数据(两张纹理以及三个网格)从硬盘最终加载到显存中。在渲染时,GPU可以快速访问这些数据


当把数据传输到显存中,RAM中的数据就可以移除了,但是一些网格数据等CPU任然需要拿出来做碰撞检测,所以这些数据我们就补希望被移除,因此,从硬盘中加载到内存时一个非常耗时的过程。在这之后,CPU将指导GPU如何渲染工作的。

        2.渲染状态决定了场景中的网格将采用什么样的方式被渲染,例如:顶点渲染、面片渲染、又或者光源、材质等。

        3.当上面的工作都准备号后CPU就需要调用一个渲染命令来告诉GPU:”我帮你把数据都准备好了,现在你可以按照我的设置来进行渲染了。“这个渲染命令就是Draw Call。

       

        CPU通过调用Draw Call来告诉GPU开始进行一个渲染过程。一个Draw Call会指向本次调用需要渲染的图元列表


        当GPU从CPU那里得到的渲染命令后就会进行一系列的GPU渲染操作,也成为GPU流水线,也就是几何阶段与光栅化阶段。

GPU的渲染流水线实现。颜色表示了不同阶段的可配置性或可编程性:绿色表示该流水线阶段是完全可编程控制的,黄色表示该流水线阶段可以配置但不是可编程的,蓝色表示该流水线阶段是由GPU固定实现的,开发者没有任何控制权。实现表示该shader必须由开发者编程实现,虚线表示该shader是可选的


这里我们将主要的流水线阶段进行详细解释

1.顶点着色器主要负责内容如下

(1)坐标转换。把顶点坐标从模型空间转换到齐次裁剪空间。我们可以通过改变顶点位置来模拟水面布料等。

(2)顶点光照。

        GPU在每个输入的网格顶点上都会调用顶点着色器。顶点着色器必须进行顶点的坐标变换,需要时还可以计算和输出顶点的颜色 。例如,我们可能需要进行逐顶点的光照。


顶点着色器会将模型顶点的位置变换到齐次裁剪坐标空间下,进行输出后再由硬件做透 视除法得到NDC下的坐标


2.裁剪主要任务是将那些不在摄像机视野范围内的物体剔除。如果某个物体部分在视野外,而

其他在视野内的话,视野外的顶点则会会用一个新的顶点代替。注意这一步是不可编程的。

        

 只有在单位立方体的图元才需要被继续处理。因此,完全在单位立方体外部的图元(红 色三角形)被舍弃,完全在单位立方体内部的图元(绿色三角形)将被保留。和单位立方体相 交的图元(黄色三角形)会被裁剪,新的顶点会被生成,原来在外部的顶点会被舍弃。


3.屏幕映射的任务是将每一个图元的XY坐标转换成屏幕坐标系。

        屏幕映射将X,Y坐标从(-1,1)范围转换到屏幕坐标系中


        OpenGL和DirectX的屏幕坐标系差异,在一张图像中 ,在OpenGL中零点在左下角,而在DirectX在左上角


4.三角形设置会计算光栅化一个三角形网格所需的信息,将上一步获得的三角形顶点连接成线,三角形的边。为了能够计算边界像素的坐标信息,我们就需要得到三角形边界的表示方式,这一个计算三角网格表示数据的过程就叫做三角形设置 。它的输出是为了下一个阶段做准备。

5.三角形遍历会将三角网格覆盖的每一个像素点生成一个片元(片元包含屏幕坐标、深度信息  、顶点信息、发现纹理坐标等,不包含颜色信息)

        三角形便利的过程。根据几何阶段输出的顶点信息,最终得到该三角网格覆盖的像素 位置,对应像素会生成一个片元,而片元中的状态时对三个顶点的信息进行插值得到的。


6.片元着色器将上一个阶段对顶点信息插值得到每个像素点的颜色。

        根据上一步插值后的片元信息,片元着色器计算该片元的输出颜色


7.逐片元操作

(1)决定每个片元的可见性,设计很多测试工作,例如深度测试 ,模板测试等。

(2)如果一个片元通过了所有测试,那么接下来就需要把这个片元的颜色值和颜色缓冲区的颜色进行合并。

        逐片元操作阶段所做的操作。只有通过了所有的测试后,新生成的片元才能和颜色缓冲区中已经存在的像素颜色进行混合,最后再写入颜色缓冲区中    


对于不透明的物体,我们可以关闭混合操作 ,这样片元着色器得到的颜色值就会直接覆盖掉颜色缓冲区的像素值。但对于半透明物体我就需要让混合操作来让这个物体看起来时透明的。混合操作就像是PS里的图层关系,不透明图层会直接覆盖下面的图层像素值

 混合操作的简化流程图


转载来自:https://www.jianshu.com/p/31fac41ea502

参考书籍《Unity Shader入门精要》

猜你喜欢

转载自blog.csdn.net/weixin_43418880/article/details/127067742