graphics-doc-cg基础

数据类型

基本数据类型

Cg 中向量、矩阵与数组是完全不同,向量和矩阵是内置的数据类型(矩阵基于向量),而数组则是一种数据结构,不是内置数据类型。

常量的类型后缀( type suffix)有 3 种:

  • f :表示 float;
  • h: 表示 half;
  • x: 表示 fixed

float

float, 32 位浮点数据,一个符号位。浮点数据类型被所有的 profile 支持(但是 DirectX8 pixel profiles 在一些操作中降低了浮点数的精度和范围);

half

half, 16 为浮点数据;

int

int, 32 位整形数据,有些 profile 会将 int 类型作为 float 类型使用;

fixed

fixed, 12 位定点数,被所有的 fragment profiles 所支持;

bool

bool,布尔数据,通常用于 if 和条件操作符( ?:),布尔数据类型被所有的profiles 支持;

sampler*

sampler*,纹理对象的句柄( the handle to a texture object),分为 6 类:sampler, sampler1D, sampler2D, sampler3D, samplerCUBE,和 samplerRECT。DirectX profiles 不支持 samplerRECT 类型, 除此之外这些类型被所有的 pixelprofiles 和 NV40 vertex program profile 所支持。

string

string,字符类型,该类型不被当前存在的 profile 所支持,实际上也没有必要在 Cg 程序中用到字符类型,但是你可以通过 Cg runtime API 声明该类型变量,并赋值;因此,该类型变量可以保存 Cg 文件的信息。

向量

向量最长不能超过 4 元。

1
2
3
float float2 float3 float4
half half2 half3 half4
fixed fixed2 fixed3 fixed4

矩阵

矩阵最大的维数不能超过 4*4 阶

1
2
3
4
5
6
float1x1 matrix1;   // 表示 1*1 阶矩阵,包含 1 个 float 类型数据
float2x3 matrix2; // 表示 2*3 阶矩阵,包含 6 个 float 类型数据
float4x2 matrix3; // 表示 4*2 阶矩阵,包含 8 个 float 类型数据
float4x4 matrix4; // 表示 4*4 阶矩阵,这是最大的维数

float2x3 matrix5 = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0};

数组类型

在着色程序中,数组通常的使用目的是:作为从外部应用程序传入大量参数到 Cg 的顶点程序中的形参接口,例如与皮肤形变相关的矩阵数组,或者光照参数数组等。简而言之,数组数据类型在 Cg 程序中的作用是:作为函数的形参,用于大量数据的转递。

1
2
3
4
float a[10];    // 声明了一个数组,包含 10 个 float 类型数据
float4 b[10]; // 声明了一个数组,包含 10 个 float4 类型向量数据

float a[4] = {1.0, 2.0, 3.0, 4.0}; // 初始化一个数组

结构类型

结构体的声明以关键字 struct 开始,然后紧跟结构体的名字,接下来是一个大括号,并以分号结尾(不要忘了分号)。大括号中是结构体的定义,分为两大类:成员变量和成员函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
struct myAdd
{
float val;

float add(float x)
{
return val + x;
}
};

myAdd s;
float a = s.value;
float b = s.add(a);

关键字

Uniform

uniform 修辞的变量的值是从外部传入的,所以在 Cg 程序(顶点程序和片段程序)中通常使用 uniform 参数修辞函数形参,不容许声明一个用 uniform 修辞的局部变量!

const

const 所修辞的变量在初始化之后不能再去改变它的值。
const 修辞符与 uniform 修辞符是相互独立的,对一个变量既可以单独使用const 或者 uniform,也可以同时使用。

in

修辞一个形参只是用于输入,进入函数体时被初始化,且该形参值的改变不会影响实参值,这是典型的值传递方式。

1
2
void myFunction(in float x);        // 形参 x,只是用于输入
void myFunction(float x); // 等价与 in float x,这种用法和 C\C++完全一致

out

修辞一个形参只是用于输出的,进入函数体时并没有被初始化,这种类型的形参一般是一个函数的运行结果;

1
void myFunction(out float x);       // 形参 x,只是用于输出

inout

修辞一个形参既用于输入也用于输出,这是典型的引用传递。

1
void myFunction(inout float x);     // 形参 x,即用于输入时初始化,也用于输出数据

语义

语义词,表示输入图元的数据含义(是位置信息,还是法向量信息),也表明这些图元数据存放的硬件资源(寄存器或者纹理缓冲区)。顶点着色程序和片段着色程序中 Varying inputs 类型的输入,必须和一个语义词相绑定,这称之为绑定语义( binding semantics)。

语义,是两个处理阶段(顶点程序、片段程序)之间的输入\输出数据和寄存器之间的桥梁,同时语义通常也表示数据的含义,如 POSITION一般表示参数种存放的数据是顶点位置。

语义,只对两个处理阶段的输入\输出数据有意义,也就是说,语义只有在入口函数中才有效,在内部函数(一个阶段的内部处理函数,和下一个阶段没有数据传递关系)的无效。

语义,分为输入语义和输入语义;输入语义和输出语义是有区别的。虽然一些参数经常会使用相同的绑定语义词, 例如: 顶点 Shader 的输入参数, POSITION72指应用程序传入的顶点位置, 而输出参数使用 POSITION 语义就表示要反馈给硬件光栅器的裁剪空间位置,光栅器把 POSITION 当成一个位置信息。虽然两个语义都命名为 POSITION,但却对应着图形流水线上不同的寄存器。

顶点着色程序的输入语义

POSITION

表示该参数中的数据是的顶点位置坐标(通常位于模型空间),属于输入参数,语义词 POSITION 是输入语义,如果在 OpenGL 中则对应为接受应用程序传递的顶点数据的寄存器(图形硬件上)。

顶点位置坐标传入顶点着色程序中转化为四元向量 float4,最后一元数据为 1

NORMAL

float4类型,表示该参数中的数据是顶点法向量坐标(通常位于模型空间),属于输入参数,语义词 NORMAL 是输入语义,如果在 OpenGL 中则对应为接受应用程序传递的顶点法向量的寄存器(图形硬件上)。

顶点法向量传入顶点着色程序中转化为四元向量float4,最后一元数据为 0

BLENDWEIGHT

TANGENT

BINORMAL

PSIZE

BLENDINDICES

TEXCOORD0—TEXCOORD7

顶点着色程序的输出语义

顶点程序的输出数据被传入到片断程序中,所以顶点着色程序的输出语义词,通常也是片段程序的输入语义词。

顶点着色程序必须声明一个输出变量,并绑定POSITION语义词,该变量中的数据将被用于,且只被用于光栅化。

如果需要从顶点着色程序向片段程序传递数据,例如顶点投影坐标、光照信息等,则可以声明另外的参数,绑定到TEXCOORD系列的语义词进行数据传递,实际上TEXCOORD系列的语义词通常都被用于从顶点程序向片段程序之间传递数据。也可以选择不使用struct结构,而直接在函数形参中进行语义绑定。无论使用何种方式,都要记住vertex program中的绑定语义( POSITION除外)的输出形参中的数据会传递到fragment program中绑定相同语义的输入形参中。

POSITION

PSIZE

FOG

COLOR0-COLOR1

TEXCOORD0-TEXCOORD7

片段着色程序的输出语义

片段着色程序的输出语义词较少,通常是COLOR。这是因为片段着色程序运行完毕后,就基本到了GPU流水线的末端了。 片段程序必须声明一个out向量(三元或四元),绑定语义词COLOR,这个值将被用作该片断的最终颜色值。