3D图形学(2):GPU渲染管线与可编程着色器

内容引自《Real Time Rendering 3rd》

渲染管线流程图

3D图形学(2):GPU渲染管线与可编程着色器

其中:

  • 绿色的阶段都是完全可编程。
  • 黄色的阶段可配置,但不编程。
  • 蓝色的阶段完全固定。

 

顶点着色器 Vertext Shader

 

  • 顶点着色器(The Vertex Shader)的功能于2001年首次在DirectX 8中引入。由于它是流水线上的第一个阶段,可选是在GPU还是CPU上实现。而在CPU上实现的话,需将CPU中的输出数据发送到GPU进行光栅化。目前几乎所有的GPU都支持顶点着色。
  • 顶点着色器是完全可编程的阶段,是专门处理传入的顶点信息的着色器,顶点着色器可以对每个顶点进行诸如变换和变形在内的很多操作。顶点着色器一般不处理附加信息,也就是说,顶点着色器提供了修改,创建,或者忽略与每个多边形顶点相关的值的方式,例如其颜色,法线,纹理坐标和位置。通常,顶点着色器程序将顶点从模型空间(Model Space)变换到齐次裁剪空间(Homogeneous Clip Space),并且,一个顶点着色器至少且必须输出此变换位置。
  • 值得注意的是,在这个顶点着色阶段之前发生了一些数据操作。比如在DirectX中叫做输入装配(Input Assembler)的阶段,会将一些数据流组织在一起,以形成顶点和基元的集合,发送到管线。
  • 传入的每个顶点由顶点着色器程序处理,然后输出一些在三角形或直线上进行插值后获得的值。顶点着色器既不能创建也不能消除顶点,并且由一个顶点生成的结果不能传递到另一个顶点。由于每个顶点都被独立处理,所以GPU上的任何数量的着色器处理器都可以并行地应用到传入的顶点流上。
  • 顶点着色器的输出可以以许多不同的方式来使用,通常是随后用于每个实例三角形的生成和光栅化,然后各个像素片段被发送到像素着色器,以便继续处理。而在Shader Model 4.0中,数据也可以发送到几何着色器(Geometry Shader)或输出流(Streamed Output)或同时发动到像素着色器和几何着色器两者中。

几何着色器 The Geometry Shader
 

  • 几何着色器(Geometry Shader)是顶点和片段着色器之间一个可选的着色器,随着2006年底 DirectX10的发布被加入到硬件加速图形管线中。几何着色器作为Shader Model 4.0的一部分,不能早期着色模型(<=SM 3.0)中使用。
  • 几何着色器的输入是单个对象及对象相关的顶点,而对象通常是网格中的三角形,线段或简单的点。另外,扩展的图元可以由几何着色器定义和处理。
  • 几何着色器可以改变新传递进来的图元的拓扑结构,且几何着色器可以接收任何拓扑类型的图元,但是只能输出点、折线(line strip)和三角形条(triangle strips)。
  • 几何着色器需要图元作为输入,在处理过程中他可以将这个图元整个丢弃或者输出一个或更多的图元(也就是说它可以产生比它得到的更多或更少的顶点)。这个能力被叫做几何增长(growing geometry)。如上所述,几何着色器输出的形式只能是点,折线和三角形条。
  • 当我们未添加几何着色器时,默认的行为是将输入的三角形直接输出。我们添加了几何着色器之后,可以在几何着色器中修改输出的图形,我们可以输出我们想要输出的任何图形。

流输出 Stream Output

       GPU的管线的标准使用方式是发送数据到顶点着色器,然后对所得到的三角形进行光栅化处理,并在像素着色器中处理它们。 数据总是通过管线传递,无法访问中间结果。流输出的想法在Shader Model 4.0中被引入。在顶点着色器(以及可选的几何着色器中)处理顶点之后,除了将数据发送到光栅化阶段之外,也可以输出到流,也就是一个有序数组中进行处理。事实上,可以完全关掉光栅化,然后管线纯粹作为非图形流处理器来使用。以这种方式处理的数据可以通过管线回传,从而允许迭代处理。这种操作特别适用于模拟流动的水或其他粒子特效。

像素着色器 Pixel Shader
 

  • 像素着色器(Pixel Shader,Direct3D中的叫法),常常又称为片元着色器(Fragment Shader, OpenGL中的叫法),用于进行逐像素计算颜色的操作,让复杂的着色方程在每一个像素上执行。如图GPU渲染管线所示,像素着色器是光栅化阶段的主要步骤之一。在顶点和几何着色器执行完其操作之后,图元会被裁剪、屏幕映射,结束几何阶段,到达光栅化阶段,在光栅化阶段中先经历三角形设定和三角形遍历,之后来到像素着色阶段。
  • 像素着色器常用来处理场景光照和与之相关的效果,如凸凹纹理映射和调色。名称片断着色器似乎更为准确,因为对于着色器的调用和屏幕上像素的显示并非一一对应。举个例子,对于一个像素,片断着色器可能会被调用若干次来决定它最终的颜色,那些被遮挡的物体也会被计算,直到最后的深度缓冲才将各物体前后排序。
  • 需要注意,像素着色程序通常在最终合并阶段设置片段颜色以进行合并,深度值也可以由像素着色器修改。模板缓冲( stencil buffer )值是不可修改的,而是将其传递到合并阶段(merge stage)。在SM 2.0以及以上版本,像素着色器也可以丢弃(discard )传入的片段数据,即不产生输出。这样的操作会消耗性能,因为通常在这种情况下不能使用由GPU执行的优化 。诸如雾计算和alpha测试的操作已经从合并操作转移到SM 4.0 中的像素着色器里计算。
  • 可以发现,顶点着色程序的输出,在经历裁剪、屏幕映射、三角形设定、三角形遍历后,实际上变成了像素着色程序的输入。在Shader Model 4.0中,共有16个向量(每个向量含4个值)可以从顶点着色器传到像素着色器。当使用几何着色器时,可以输出32个向量到像素着色器中。像素着色器的追加输入是在Shader Model 3.0中引入的。例如,三角形的哪一面是可见的是通过输入标志来加入的。这个值对于在单个通道中的正面和背面渲染不同材质十分重要。而且像素着色器也可以获得片段的屏幕位置。

合并阶段 The Merging Stage
 

  • 作为光栅化阶段名义上的最后一个阶段,合并阶段(The Merging Stage)是将像素着色器中生成的各个片段的深度和颜色与帧缓冲结合在一起的地方。这个阶段也就是进行模板缓冲(Stencil-Buffer)和Z缓冲(Z-buffer)操作的地方。最常用于透明处理(Transparency)和合成操作(Compositing)的颜色混合(Color Blending)操作也是在这个阶段进行的。
  • 虽然合并阶段不可编程,但却是高度可配置的。在合并阶段可以设置颜色混合来执行大量不同的操作。最常见的是涉及颜色和Alpha值的乘法,加法,和减法的组合。其他操作也是可能的,比如最大值,最小值以及按位逻辑运算。

总结

3D图形学(2):GPU渲染管线与可编程着色器

GPU渲染管线的一个流程概览:

  • 顶点着色器( The Vertex Shader )是完全可编程的阶段,顶点着色器以对每个进行诸如变换和变形在内的很多操作,提供了修改 /创建 /忽略顶点相关属性的功能,这些包括颜色、 法线、纹理坐标和位置。顶点着色器的必须完成任务是将从模型空间转换到齐次裁剪空间。
  • 几何着色器( The Geometry Shader )位于顶点着色器之后,允许 GPU 高效地创建和销毁几何图元。几何着色器是可选的,是完全可编程阶段,主要对图元(点、线、三角形)的顶点进行操作。几何着色器接收顶点着色器的输出作为输入,通过高效几何运算,将数据输出,随后经过几何阶段和光栅化阶段的其他处理后,会发送给片元着色器。
  • 裁剪( Clipping)属于可配置的功能阶段,在此阶段可选运行裁剪方式,以及添加自定义裁剪面。
  • 屏幕映射( Screen Mapping )、三角形设置( Triangle Setup )和三角形遍历( Triangle Traversal  )阶段是固定功能阶段。
  • 像素着色器( Pixel Shader,Direct3D 中的叫法)常又称为片元着色器 ( Fragment Shader ,OpenGL 中的叫法 ),是完全可编程的阶段,主要作用进行像素处理,逐像素处理像素颜色。
  • 合并阶段( The Merger Stage)处于完全可编程和固定功能之间,尽管不能编程,但是高度可配置,以进行一系列的操作。其除了合并操作,还分管颜色修改( Color Modifying ), Z缓冲( Z-buffer ),混合( Blend ),模板( Stencil )和相关缓存的处理。