# 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} $ 其中 表示视点到远裁剪面的空间距离, 表示视点到近裁剪平面的空间距离, 表示视点到顶点的空间距离, 表示 值精度 (这个值的推导可以后面在入门精要里学,他这里直接给结论了) 需要注意的是,正交空间里 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 | struct myAdd{ |
函数里的变量需要声明在函数之前
# 接口类型
很少用
# 类型转换
低精度 -> 高精度
1 | float a = 1.0; |
类型后缀
f:float
h: half
x: fixed P59