Shader 入门(二)

渲染管线的理解:

最近在学习Unity Shader编程,为了加深对编程过程的理解,所以将学习过程中的一些学习内容记录下来,方便以后进行再次阅读。不说废话了,直奔今天的主题。

了解管线之后,能让人了解3D物体从自身的数据传入开始到最后呈现在屏幕上的所有历程。在理解和解决渲染发生的问题的时候,往往有指导性作用。管线基本分为固定管线可编程管线,固定管线,暂时没有什么好讲的,今天主要谈下可编程管线。参考的是OpenGL的图。

渲染管线流程如下图:
Shader 入门(二)_第1张图片
这种模式下, GPU 的 Vertex Shader(其中一橙色块)和 Fragment Shader(另一个橙色块),都是一段通过用户层可以设置的供GPU运行的代码。Vertex Shader接收从GPU送进来的顶点信息,并对每个顶点运行用户的顶点程序,即顶点着色程序; Fragment shader 接收 GPU送进来的像素信息,并对每个像素运行用户的像素程序,即像素着色程序(精确的说,fragment 并不等同于pixel,但这里简化这个说法)。通过这样的方式,用户就可以在这两段程序里放置自己的算法,对于金属,使用一种算法;对于塑料,又是另外一种算法。因为这些地方都是可以进行编程的,所以这个管线也就被叫做“可编程管线”。

渲染管线具体可细分为:顶点处理、面处理、光栅化、像素处理。

Shader 入门(二)_第2张图片

顺着图中的箭头方向,就是数据一步一步被处理,最后写到显示缓冲区(framebuffer)的过程,每个单位都是一个一个的步骤走,类似工厂的流水线。

下面具体说下上面的工作流程:
(1)用户给GPU传入顶点数据到流水线,顶点数据是一个属性,如:位置、法线、颜色等。
(2)上图中的Vertex Shader接手处理每个顶点,对Vertex Shader来说就是接收了在(1)当中的输入的顶点数据信息流。要输出什么,在可编程管线中,完全是看用户写的代码要做什么。在这个步骤中,输出的信息有一个约束,至少有一个位置(position)信息必须被输出,作为一个有效的顶点信息
(3)元件组装( Primitive Assembly),对于 OpenGL 来说,元件有 3 种,点、线和三角形。从第(2)步出来的顶点数据,再结合用户传给流水线的其他数据(告知这些顶点之间的关系),会被这个过程组装成这三个类型中的一种。镶嵌/或者说是细分(Tessellation)会在此后运行,让前面的 primitive 能被细分成更小的元件以满足不同的精度需求。
(4)几何体着色器(Geometry Shader),该着色器得到第三步出来的 primitive,它的输出是0个或者更多的primitives。
(5)Transform Feedback,在 OpenGL 这里,几何体着色器后可以吐出相关的 primitive到所谓的缓冲物体(buffer object)中(其实就是定义好格式的一些数据结构),这些buffer object可以被保存用作其他的作用。如果在这里抛弃流水线后续的工作,那么整个流水线的产出就是这些东西。
(6)顺图中的实线,后续是裁剪(Clipping)。根据用户设置的视椎体的可视范围,primitives会被剔除(整体在可视范围外),部分在外的则被按照规则切割成几个primitives。在现在的GPU上,用户除了视椎体,也可以通过裁剪面(Clip plane)来指定额外的裁剪信息。在3D中,大多数是单面的primitive,这个时候,背面朝向相机的primitive也会被裁剪掉。
(7)能达到光栅化(Rasterization)这步的物体,会被这个步骤进行光栅化,举例来说,一个三角形primitive,会产生填充其内部的许多所谓的碎片(fragment)。fragment跟 pixel(像素)不同的地方在于,在专业角度,它是一系列信息,用来判断对应的像素最后的数据。
(8)碎片着色器(Fragment Shader得到上面处理出来的数据,然后运行用户给定的一段程序,计算出最后的像素的相关信息。它的输出是一系列的值:颜色和深度信息。
(9)fragment shader 的输出进行Fragment Tests 这个阶段,会首先进行Alpha 测试(alpha test),继而模板测试(stencil test),如果 fragment 没有经过测试,那么就不会进入到最后的缓冲区( framebuffer);然后进行深度测试( depth test),如果通不过,就不会进入 framebuffer。【注: OpenGL 的相关文档有提到,如果 fragment shader对 fragment 的深度不会修改,那么这个测试可以提到 fragment shader 之前,所谓的“Early Z Test”】
(10)Blending 是后续的工作,如果 fragment 可以被写入 framebuffer,则这个 fragment和已经在 framebuffer 中的值可以做一定的混合,实现不同的效果,举例,半透明效果。
(11)上一步出来的值,就准备开始往 framebuffer 中写了,写的时候可以通过 Writing Mask来控制哪些值要写到 framebuffer,可以控制到颜色、深度、模板值,也可以控制到颜⾊的某个通道。
(12)结束。


参考资料
[1]: Unity Shader 编程 由http: //98jy.net所著

你可能感兴趣的:(U3D)