摘抄“GPU Programming And Cg Language Primer 1rd Edition” 中文名“GPU编程与CG语言之阳春白雪下里巴人”

  这一节中主要阐述图形硬件的相关知识,主要包括GPU中数据的存放硬件,以及各类缓冲区的具体含义和用途,如:z buffer(深度缓冲区)、stencil buffer(模板缓冲区)、frame buffer(帧缓冲区)和color buffer(颜色缓冲区)。


2.4.1    GPU内存架构


寄存器和内存有什么区别?
从物理结构而言,寄存器是cpu或gpu内部的存储单元,即寄存器是嵌入在cpu或者gpu中的,而内存则可以独立存在;从功能上而言,寄存器是有限存储容量的高速存储部件,用来暂存指令、数据和位址。Shader编成是基于计算机图形硬件的,这其中就包括GPU上的寄存器类型,glsl和hlsl的着色虚拟机版本就是基于GPU的寄存器和指令集而区分的。
  

2.4.2 Z Buffer与Z值


  Z buffer应该是大家最为熟悉的缓冲区类型,又称为depth buffer,即深度缓冲区,其中存放的是视点到每个像素所对应的空间点的距离衡量,称之为Z值或者深度值。可见物体的Z值范围位于【0,1】区间,默认情况下,最接近眼睛的顶点(近裁减面上)其Z值为0.0,离眼睛最远的顶点(远裁减面上)其Z值为1.0。使用z buffer可以用来判断空间点的遮挡关系,著名的深度缓冲区算法(depth-buffer method,又称Z缓冲区算法)就是对投影平面上每个像素所对应的Z值进行比较的。
Z值并非真正的笛卡儿空间坐标系中的欧几里德距离(Euclidean distance),而是一种“顶点到视点距离”的相对度量。所谓相对度量,即这个值保留了与其他同类型值的相对大小关系。在steve Baker撰写的文章“Learning to love your Z-buffer”中将GPU对Z值的计算公式描述为:
  

 

  其中 f表示视点到远裁减面的空间距离, n表示视点到近裁减面的空间距离, z表示视点到顶点的空间距离,N表示Z 值精度。
  大多数人所忽略的是,z buffer中存放的z值不一定是线性变化的。在正投影中同一图元相邻像素的Z值是线性关系的,但在透视投影中却不是的。在透视投影中这种关系是非线性的,而且非线性的程度随着空间点到视点的距离增加而越发明显。
  当3D图形处理器将基础图元(点、线、面)渲染到屏幕上时,需要以逐行扫描的方式进行光栅化。图元顶点位置信息是在应用程序中指定的(顶点模型坐标),然后通过一系列的过程变换到屏幕空间,但是图元内部点的屏幕坐标必须由已知的顶点信息插值而来。例如,当画三角形的一条扫描线时,扫描线上的每个像素的信息,是对扫描线左右端点处已知信息值进行插值运算得到的,所以内部点的Z值也是插值计算得到的。同一图元相邻像素点是线性关系(像素点是均匀分布的,所以一定是线性关系),但对应到空间线段上则存在非线性的情况,如图 7所示。所示:线段AE是某三角面片的两个顶点,投影到屏幕空间对应到像素1和像素5;光栅化时,需要对像素2、3、4进行属性插值,从视点引射线到空间线段上的交点分别为B、C、D。从图中可以看出,点B、C、D并不是均匀分布在空间线段上的,而且如果离视点越远,这种差异就越发突出。即,投影面上相等的步长,在空间中对应的步长会随着离视点距离的增加而变长。所以如果对内部像素点的Z值进行线性插值,得到的Z值并不能反应真实的空间点的深度关系。Z值的不准确,会导致物体显示顺序的错乱,例如,在游戏中常会看到远处的一些面片相互交叠。
为了避免或减轻上述的情况,在设置视点相机远裁减面和近裁减面时,两者的比值应尽量小于1000。要想解决这个问题,最简单的方法是通过将近截面远离眼睛来降低比值,不过这种方法的副作用时可能会将眼前的物体裁减掉。
  

  很多图形硬件使用16位的Z buffer,另外的一些使用24位的Z buffer,还有一些很好的图形硬件使用32位的。如果你拥有32位的Z buffer,则Z精度(Z-precision)对你不是一个问题。但是如果你希望你的程序可以灵活的使用各种层次的图形硬件,那么你就需要多思考一下。
Z精度之所以重要,是因为Z值决定了物体之间的相互遮挡关系,如果没有足够的精度,则两个相距很近的物体将会出现随机遮挡的现象,这种现象通常称为“flimmering”或”Z-fighting”。


2.4.3 Stencil Buffer

  A stencil buffer is an extra buffer, in addition to the color buffer and depth buffer found on modern computer graphics hardware. The buffer is per pixel, and works on integer values, usually with a depth of one byte per pixel. The depth buffer and stencil buffer often share the same area in the RAM of the graphics hardware.
  Stencil buffer,中文翻译为“模板缓冲区”,它是一个额外的buffer,通常附加到z buffer中,例如:15位的z buffer加上1位的stencil buffer(总共2个字节);或者24位的z buffer加上8位的stencil buffer(总共4个字节)。每个像素对应一个stencil buffer(其实就是对应一个Z buffer)。 Z buffer和stencil buffer通常在显存中共享同一片区域。Stencil buffer对大部分人而言应该比较陌生,这是一个用来“做记号”的buffer,例如:在一个像素的stencil buffer中存放1,表示该像素对应的空间点处于阴影体(shadow volume)中。


2.4.4 Frame Buffer


  A framebuffer is a video output device that drives a video display from a memory buffer containing a complete frame of data. The information in the buffer typically consists of color values for every pixel on the screen. Color values are commonly stored in 1-bit monochrome, 4-bit palettized, 8-bit palettized, 16-bit highcolor and 24-bit truecolor formats. An additional alpha channel is sometimes used to retain information about pixel transparency. The total amount of the memory required to drive the framebuffer depends on the resolution of the output signal, and on the color depth and palette size.
  Frame buffer,称为帧缓冲器,用于存放显示输出的数据,这个buffer中的数据一般是像素颜色值。Frame buffer有时也被认为是color buffer(颜色缓冲器)和z buffer的组合(《实时计算机图形学(第二版)》12页)。那么frame buffer位于什么地方呢?在webMediaBrands网站上摘录了一段英文说明,即frame buffer通常都在显卡上,但是有时显卡会集成到主板上,所以这种情况下frame buffer被放在内存区域(general main memory)。
  Frame buffer: The portion of memory reserved for holding the complete bit-mapped image that is sent to the monitor. Typically the frame buffer is stored in the memory chips on the video adapter. In some instances, however, the video chipset is integrated into the motherboard design, and the frame buffer is stored in general main memory.