# Z-Buffer

Z-Buffer 是深度缓冲,即 Depth buffer, 里面存放的是视点到每个像素所对应的空间点的距离衡量,称之为 Z 值或深度值。可见物体的 Z 值范围位于 [0,1] 之间,默认情况下,近裁剪平面上的 Z 值为 0.0, 远裁剪平面上的 Z 值为 1,Z-buffer 可以用来判断空间点的遮挡关系. Z 值并非真正的笛卡尔坐标系中的欧几里得距离,而是一种视点到顶点距离的相对度量 $ z\_buffer\_value = (1<<N)*\frac {a*z+b}{z} $ $ a = \frac {f}{f-n} $ $ b = \frac {f*n}{n-f} $ 其中ff 表示视点到远裁剪面的空间距离,nn 表示视点到近裁剪平面的空间距离,zz 表示视点到顶点的空间距离,NN 表示ZZ 值精度 (这个值的推导可以后面在入门精要里学,他这里直接给结论了) 需要注意的是,正交空间里 z 值是线性的,但是透视空间里这个值不是线性的。当出现远处的面片发生重叠的情况时,一般叫做 flimmering 或者 Z-fighting

# Stencil Buffer

模板缓冲区,它是一个额外的 buffer, 通常附加在 z-buffer 上,15 位的 z-buffer 上附加 1 位的 stencil buffer (共 2 字节), 这只是一个做标记的 buffer

# Frame Buffer

FrameBuffer, 称为帧缓冲器,用于存放显示输出的数据,这个 buffer 中的数据一般是像素颜色值.Frame Buffer 有时也被认为是 color buffer (颜色缓存器)

# Shader Language

Shader language 目前主要有 3 种语言:基于 OpenGL 的 GLSL,基于 Direct3D 的 HLSL,还有 NVIDIA 公司的 Cg 语言。 之所以 Shader 分为了两种,顶点 shader 和片元 shader. 是因为 GPU 上的两个组件

  • Programmable Vertex Processor (可编程顶点处理器,又称顶点着色器)
  • Programmable Fragment Processor (可编程片元处理器,又称片元着色器)

这两个处理器都拥有非常强大的并行计算能力,并且非常擅长矩阵计算. 如果在顶点阶段输入顶点颜色,则 GPU 会根据硬件算法 (比如 Phong 或者 Ground 明暗) 来进行插值 但是在片段着色器中进行像素的独立计算,可控性会很好

# CG HLSL GLSL 对比

GLSL 基于 OpenGL
HLSL 基于 Direct3D
Cg 是 Nvidia 的 HLSL 和 CG 基本相同

# CG 语言概述

# CG 编译原理

CG 是动态语言,即运行时可以动态修改,
CG 编译器首先将 CG 程序翻译成可被图形 API (OpenGL 和 Direct3D) 所接受的形式,然后应用程序使用适当的 OpenGL 和 D3D 的命令传递给图形处理器。执行 CG 只依赖于硬件,比如如果不支持循环,那么 CG 循环这部分将无效 (无法通过编译)

# CG 数据类型

# 基本数据类型

  • float: 32 位浮点
  • half: 16 位浮点
  • int: 32 位整型
  • fixed: 12 位定点 (所有都支持)
  • bool
  • sampler*: 纹理对象的句柄,分为 6 类
    • sampler,sampler1D.sampler2D,sampler3D,samplerCUBE 和 samplerRECT D3D profile 不支持 RECT
  • string: 一般没必要

# 向量形式

float4 表示 float 类型的 4 元向量,bool4 表示 bool 类型 4 元向量 最长不能超过 4 元 float4 array = float4 (1.0,2.0,3.0,4.0) 较长的也可以通过较短的进行构建 float2 a = float2 (1.0,1.0)
float4 = float4(a,0.0,0.0);

# 矩阵形式

float1X1 matrix1, 等价于 float matrix1 float2X3。。。最大支持 4x4 矩阵初始化方法 float2x3 matrix5 = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0};

# 数组类型

数组通常的目的是:作为从外部应用程序传入大量参数到 cg 的顶点程序的形参接口,例如与皮肤形变相关的矩阵数组。或者光照参数数组等。 如
float a [10];
float4 b [10]; float a [4] = {1.0,2.0,3.0,4.0}// 初始化一个数组

获取数组长度:

int length = a.length

多维数组

float b\[2\]\[3\] = {{0.0,0.0,0.0},{1.0,1.0,1.0}}; 获取数组长度的方式为:
int length1 = b.length;
int length2 = b [0].length; 数组与矩阵类似,但并不相同,后者是一个矩阵,可以直接通过矩阵进行操作。前者则是一个包含了相应数组个数数据的数组

# 结构类型

CG 的结构和 C++ 类似,但并不相同

1
2
3
4
5
6
7
8
struct myAdd{
float val;
float add(float x){
return val+x;
}
};

myAdd a;

函数里的变量需要声明在函数之前

# 接口类型

很少用

# 类型转换

低精度 -> 高精度

1
2
3
float a = 1.0;
half b = 2.0;
float c = a+b;//等价于 float c =a + (float)b

类型后缀

f:float
h: half
x: fixed P59