Cg 中提供了三个关键字,in、out、inout,用于表示函数的 输入参数的传递方式,称为输入\输出关键字,这组关键字可以和语义词合用表 达硬件上不同的存储位置,即同一个语义词,使用 in 关键字修辞和 out 关键词修 辞,表示的图形硬件上不同的寄存器。
1. in: 修辞一个形参只是用于输入,进入函数体时被初始化,且该形参值 的改变不会影响实参值,这是典型的值传递方式。 2. out: 修辞一个形参只是用于输出的,进入函数体时并没有被初始化,这 种类型的形参一般是一个函数的运行结果; 3. inout: 修辞一个形参既用于输入也用于输出,这是典型的引用传递。 举例如下: void myFunction(out float x); //形参 x,只是用于输出 void myFunction(inout float x); //形参 x,即用于输入时初始化,也用于输出数据,也可以使用 return 语句来代替 out 修辞符的使用。输入\输出修辞符通常和语 义词一起使用,表示顶点着色程序和片段着色程序的输入输出。
Cg 语言还提供两个修辞符:uniform,用于指定变量的数据初始化方式;const 关键字的含义与 C\C++中相同,表示被修辞变量为常量变量。
Cg 语言将输入数据流分为两类:
1. Varying inputs,即数据流输入图元信息的各种组成要素。从应用程序输入 到 GPU 的数据除了顶点位置数据,还有顶点的法向量数据,纹理坐标数据 等。Cg 语言提供了一组语义词,用以表明参数是由顶点的哪些数据初始化 的。
2. Uniform inputs,表示一些与三维渲染有关的离散信息数据,这些数据通 常由应用程序传入,并通常不会随着图元信息的变化而变化,如材质对光的 反射信息、运动矩阵等。Uniform 修辞一个参数,表示该参数的值由外部应 用程序初始化并传入;例如在参数列表中写:
uniform float brightness,
uniform float4x4 modleWorldProject
表示从“外部”传入一个 float 类型数据,和一个 4 阶矩阵。“外部”的含义 通常是用 OpenGL 或者 DirectX 所编写的应用程序。 使用 Uniform 修辞的变量,除了数据来源不同外,与其他变量是完全一样的。 需要注意的一点是:uniform 修辞的变量的值是从外部传入的,所以在 Cg 程 序(顶点程序和片段程序)中通常使用 uniform 参数修辞函数形参,不容许声明 一个用 uniform 修辞的局部变量!否则编译时会出现错误提示信息: Error C5056:’uniform’not allowed on local variable 。
Cg 语言也提供 const 修辞符,与 C\C++中含义一样,被 const 所修辞的变量 在初始化之后不能再去改变它的值。
在 C\C++中,当一个数组作为函数的形参时,实际上传入的只是指向首元素 的指针,并且数组边界被忽略(参阅 stephen C.Dewhurst 所著的《C++必知必会》)。 而在 Cg 语言中不存在指针机制(图形硬件不支持),数组作为函数形参,传递 的是数组的完整拷贝。
Cg 语言支持函数重载(Functon Overlaoding),其方式和 C++基本一致,通 过形参列表的个数和类型来进行函数区分。
通常高级语言程序中只有一个入口函数,不过由于着色程序分为顶点程序和 片断程序,两者对应着图形流水线上的不同阶段,所以这两个程序都各有一个入 口函数。 顶点程序和片段程序有且只有一个入口函数,当程序进行编译时,需要指定 入口函数名称,除非入口函数名为 main。顶点程序和片段程序的入口函数形式,已经完全由 它们在渲染管线中所处的阶段所决定。在前面已经阐述过,顶点程序接收应用程 序传递的顶点数据(通常位于模型坐标空间),然后进行坐标空间转换和光照处 理,最后输出投影坐标和计算得到的光照颜色;而片段程序接收从顶点程序输出 的数据,并进行像素颜色计算。在片段程序中往往涉及到纹理颜色的处理,其输 入参数中常有纹理形参的声明。所以通过观察程序的输入输出语义绑定,就可以区分入口函数对应到顶点程序还是片段程序。
Cg 标准函数库主要分为五个部分: 1. 数学函数(Mathematical Functions); 2. 几何函数(Geometric Functions); 3. 纹理映射函数(Texture Map Functions); 4. 偏导数函数(Derivative Functions); 5. 调试函数(Debugging Function);
1.数学函数:
2.几何函数:Cg 语言标准函数库中有 3 个几何函数会经常被使用到,分别是:normalize 函数,对向量进行归一化;reflect 函数,计算反射光方向向量;refract 函数,计算折射光方向向量。强烈注意: 1. 着色程序中的向量最好进行归一化之后再使用,否则会出现难以预料的 错误; 2. reflect 函数和 refract 函数都存在以“入射光方向向量”作为输入参数, 注意这两个函数中使用的入射光方向向量,是从外指向几何顶点的;平时我 们在着色程序中或者在课本上都是将入射光方向向量作为从顶点出发。
3.纹理映射函数:s 象征一元、二元、三元纹理坐标;z 代表使用“深度比较(depth comparison)” 的值;q 表示一个透视值(perspective value,其实就是透视投影后所得到的齐次坐 标的最后一位),这个值被用来除以纹理坐标(S),得到新的纹理坐标(已归一 化到 0 和 1 之间)然后用于纹理查询。 纹理函数非常多,总的来说,按照纹理维数进行分类,即:1D 纹理函数, 2D 纹理函数,3D 纹理函数,已经立方体纹理。需要注意,TexREC 函数查询的 纹理实际上也是二维纹理。
tex1D(sampler1D tex, float s) 一维纹理查询
tex1D(sampler1D tex, float s, float dsdx, float dsdy) 使用导数值(derivatives)查询一维纹理
Tex1D(sampler1D tex, float2 sz) 一维纹理查询,并进行深度值比较
Tex1D(sampler1D tex, float2 sz, float dsdx,float dsdy) 使用导数值(derivatives)查询一维纹理, 并进行深度值比较
Tex1Dproj(sampler1D tex, float2 sq) 一维投影纹理查询
Tex1Dproj(sampler1D tex, float3 szq) 一维投影纹理查询,并比较深度值
Tex2D(sampler2D tex, float2 s) 二维纹理查询
Tex2D(sampler2D tex, float2 s, float2 dsdx, float2 dsdy) 使用导数值(derivatives)查询二维纹理
Tex2D(sampler2D tex, float3 sz) 二维纹理查询,并进行深度值比较
Tex2D(sampler2D tex, float3 sz, float2 dsdx,float2 dsdy) 使用导数值(derivatives)查询二维纹理,并进行深度值比较
Tex2Dproj(sampler2D tex, float3 sq) 二维投影纹理查询
Tex2Dproj(sampler2D tex, float4 szq) 二维投影纹理查询,并进行深度值比较
texRECT(samplerRECT tex, float2 s)
texRECT (samplerRECT tex, float2 s, float2 dsdx, float2 dsdy)
texRECT (samplerRECT tex, float3 sz)
texRECT (samplerRECT tex, float3 sz, float2 dsdx,float2 dsdy)
texRECT proj(samplerRECT tex, float3 sq) texRECT proj(samplerRECT tex, float3 szq) Tex3D(sampler3D tex, float s) 三维纹理查询
Tex3D(sampler3D tex, float3 s, float3 dsdx, float3 dsdy) 结合导数值(derivatives)查询三维纹理
Tex3Dproj(sampler3D tex, float4 szq) 查询三维投影纹理,并进行深度值比较
texCUBE(samplerCUBE tex, float3 s) 查询立方体纹理
texCUBE (samplerCUBE tex, float3 s, float3 dsdx, float3 dsdy) 结合导数值(derivatives)查询立方体纹理
texCUBEproj (samplerCUBE tex, float4 sq) 查询投影立方体纹理
4.偏导函数:偏导数的物理含义是:在某一个方向上的变化快慢。 所以 ddx 求的是 X 方向上,相邻两个像素的某属性值的变化量;ddy 球的是 Y 方向上,相邻两个像素的某属性值的变化量。 如果函数 ddx 的参数为 myVar,该参数对应的像素点 记为 pij ( ) , ,则 ddx(myVar)的值为“像素点 pi j ( +1, ) 的值减去 myVar”。同理, 92 ddy(myVar)的值为“像素点 pij ( ) , 1+ 的值减去 myVar”。如果函数 ddx 和 ddy 的输 入参数为常数,则函数返回值永远为 0。
ddx(a) 参数 a 对应一个像素位置,返回该像素 值在 X 轴上的偏导数
ddy(a) 参数 a 对应一个像素位置,返回该像素 值在 X 轴上的偏导数
作用:1. 函数 ddx 和 ddy 用于求取相邻像素间某属性的差值; 2. 函数 ddx 和 ddy 的输入参数通常是纹理坐标; 3. 函数 ddx 和 ddy 返回相邻像素键的属性差值;