Unity Shader学习三:Cg语言基础语法

        观前提示:本文章是个人笔记,只是给自己看的,我自己看得懂就行。

目录

一、Cg数据类型

1、基本数据类型

2、Cg向量数据类型

3、Cg矩阵数据类型

4、Cg数组类型

5、Cg结构类型

6、Cg数据类型转换

二、Cg表达式与控制语句

1、Cg关系运算符

2、Cg向量bool逻辑运算

3、Cg逻辑操作符

4、Cg数学操作符

5、Cg位移操作符

6、Cg Swizzle操作符

7、Cg条件运算符

8、Cg操作运算符优先级

9、Cg控制流语句

10、Cg关键字

三、输入、输出与语义控制

1、Cg uniform

2、Cg输入/输出修饰符

3、Cg输入语义和输出语义的区别

4、顶点着色器的输入语句

5、顶点着色器的输出语句

6、片元着色器的输入语义

7、语义绑定方法

四、函数与程序设计

1、Cg函数

2、Cg标准函数库


一、Cg数据类型

1、基本数据类型

        Cg支持7种基本的数据类型:

        float32 位浮点数据,一个符号位

        half:16 浮点数据

        fixed:12 位浮点数

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

        bool:布尔数据

        sampler*:纹理对象的句柄,分为 6 : sampler, sampler1D, sampler2D, sampler3D, samplerCUBEsamplerRECT

        string:字符类型

2、Cg向量数据类型

        Cg提供了内置的向量数据类型(built-in vector data types),内置的向量数据类型基 于基础数据类型。

        例如:float4,表示float类型的4元向量; bool4,表示bool 类型 4 元向量。

        注意:向量最长不能超过 4 ,即在 Cg 程序中可以声明 float1float2float3float4 类型的数组变量,但是不能声明超过 4 元的向量。

        向量初始化方式一般为: float4 array = float4(1.0, 2.0, 3.0, 4.0)。

3、Cg矩阵数据类型

        Cg 提供矩阵数据类型,不过最大的维数不能超过 4*4 阶。

float1x1 matrix1;//等价于 float matirx1; ”x“是字符,并不是乘号! 
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};

4、Cg数组类型

        在着色程序中,数组通常的使用目的是作为从外部应用程序传入大量参数输出到Cg的顶点程序中的形参接口。简而言之,数组数据类型在Cg程序中的作用是:作为函数的形参,用于大量数据的转递。

        Cg中声明数组变量的方式和C语言类似例如:

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

//对数组进行初始化的方式为
float a[4] = {1.0, 2.0, 3.0, 4.0}; //初始化一个数组

//获取数组长度
float a[2] = {1.0, 2.0}; int nLen = a.length;

//声明多维数组以及初始化
float b[2][3] = {{0.0, 0.0, 0.0},{1.0, 1.0, 1.0}};

//对多维数组取长度
int length1 = b.length; // length1 值为 2
int length2 = b[0].length; // length2 值为3

        数组和矩阵有些类似,但是并不是相同。

        例如 4*4 阶数组的的声明方式为: float M[4][4];

        4 阶矩阵的声明方式为:float4x4 M;

        前者是一个数据结构,包含16float类型数据,后者是一个4阶矩阵数据。

        float4x4 M[4],表示一个数组,包 含44阶矩阵数据。

        注意:进行数组变量声明时,一定要指定数组长度,除非是作为函数参数而声明的 形参数组。

5、Cg结构类型

        Cg语言支持结构体(structure),实际上Cg中的结构体的声明、使用和C++ 非常类似(只是类似,不是相同)

        声明一个该结构体类型的变量,代码如下

struct myAdd
{
	float val;
	float add(float x)
	{
		return val + x;
	}
};
myAdd s;

        注意:在当前的所有的profile版本下如果结构体的一个成员函数使用了成员变量则该成员变量要声明在前。此外成员函数是否可以重载依赖于使用的profile版本。

6、Cg数据类型转换

        Cg中的类型转换和C语言中的类型转换很类似。C 语言中类型转换可以是强制类型转换,也可以是隐式转换,如果是后者,则数据类型从低精度向高精度转换。在 Cg 语言中也是如此。例如:

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

        Cg 语言中对于常量数据可以加上类型后缀,表示该数据的类型,例如:

float a = 1.0;
float  b = a + 2.0h; //2.0h 为 half 类型常量数据,运算是需要做类型转换

//常量的类型后缀(type suffix)有 3 种
1、f:表示 float;
2、h:表示 half;
3、x:表示 fixed;

二、Cg表达式与控制语句

1、Cg关系运算符

        关系操作符,用于比较同类型数据(不同类型的基础数据需要进行类型转换,不同长度的向量,不能进行比较)之间的大小关系或者等价关系。

2、Cg向量bool逻辑运算

        Cg语言表达式允许对向量使用所有的boolean operator,如果是二元操作符,则被操作的两个向量的长度必须一致。表达式中向量的每个分量都进行一对一的运算,最后返回的结果是一个bool类型的向量,长度和操作数向量一致。例如:

float3 a = float3(0.5, 0.0, 1.0);
float3 b = float3(0.6, -0.1, 0.9);
bool3 c = a < b;

//运算后向量c的结果为
bool3(true, false, false);

3、Cg逻辑操作符

        Cg语言中有3种逻辑操作符(也被称为boolean Operators),逻辑操作符运算后的返回类型均为bool类型。

        逻辑操作符也可以对向量使用,返回的变量类型是同样长度的内置bool向量。

        注意:Cg中的逻辑与(&&)和逻辑或(||)不存在C中的短路现象(short-circuiting,即只用计算一个操作数的bool值即可),而是参与运算的操作数据都进行bool分析。

4、Cg数学操作符

        Cg语言对向量的数学操作提供了内置的支持Cg中的数学操作符有:*乘法; /除法; -取反; +加法; -减法; %求余; ++; --; *=; /=; +=; -=;

        后面四种运算符有时被归纳入赋值操作符,不过它们实际上进行数学计算,然后进行赋值,所以这里也放入数学操作符中进行说明。

        需要注意的是:求余操作符%。只能在int类型数据间进行,否则编译器会提示错误信息:

error C1021: operands to “%” must be integral.

5、Cg位移操作符

        Cg语言中的移位操作符,功能和C语言中的一样,也可以作用在向量上,但向量类型必须是int类型。

        例如:

int2 a = int2(0.0,0.0);
int2 b = a>>1;

6、Cg Swizzle操作符

        可以使用Cg语言中的swizzle操作符(.)将一个向量的成员取出组成一个新的向量。swizzle操作符被GPU硬件高效支持。swizzle操作符后接xyzw, 分别表示原始向量的第一个、第二个、第三个、第四个元素;swizzle操作符后接 rgba的含义与前者等同。不过为了程序的易读性,建议对于表示颜色值的 向量,使用swizzle操作符后接rgba的方式。

float4(a, b, c, d).xyz;// 等价于 float3(a, b, c) 
float4(a, b, c, d).xyy;// 等价于 float3(a, b, b)
float4(a, b, c, d).wzyx;// 等价于 float4(d, c, b, a)
float4(a, b, c, d).w;// 等价于 float d

        注意:Swizzle操作符只能对结构体和向量使用,不能对数组使用。

7、Cg条件运算符

expr1 ? expr2 : expr3;

if(a < 0){b = a;}
else{c = a;}

8、Cg操作运算符优先级

9、Cg控制流语句

        Cg中的控制流语句和循环语句与C语言类似。

        条件语句有:ifif-elseif-else if-else

        循环语句有:whilefor

        break、continue 语句可以在forwhile语句中使用。

10、Cg关键字

        Cg 中的关键字很多都是照搬C\C++中的关键字,不过 Cg 中也创造了一系列独特的关键字, 这些关键字不但用于指定输入图元的数据含义(是位置信息,还是法向量信息),本质也则对应着这些图元数据存放的硬件资源(寄存器或者纹理),称之为语义词(Semantics),通常也根据其用法称之为绑定语义词(binding semantics)

        除语义词外,Cg 中还提供了三个关键字:inoutinout。用于表示函数的输入参数的传递方式,称为输入\输出关键字,这组关键字可以和语义词合用表达硬件上不同的存储位置,即同一个语义词,使用 in 关键字修辞和 out 关键词修辞,表示的图形硬件上不同的寄存器。

        Cg 语言还提供两个修辞符:uniform 用于指定变量的数据初始化方式;const 关键字的含义与 C\C++中相同,表示被修辞变量为常量变量。

三、输入、输出与语义控制

1、Cg uniform

        Cg 语言将输入数据流分为两类:

        (1)Varying inputs,即数据流输入图元信息的各种组成要素。

        (2)Uniform inputs,表示一些与三维渲染有关的离散信息数据,这些数据通常由应用程序传入,并通常不会随着图元信息的变化而变化,如材质对光的反射信息、运动矩阵等。

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

2、Cg输入/输出修饰符

        参数传递是指:函数调用实参值初始化函数形参的过程。

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

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

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

3、Cg输入语义和输出语义的区别

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

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

        语义分为输入语义和输入语义,输入语义和输出语义是有区别的。

4、顶点着色器的输入语句

        参数使用语义使用举例:

in float4 modelPos: POSITION

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

5、顶点着色器的输出语句

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

        这些语义词适用于所有的Cg vertex profiles作为输出语义和Cg fragment profiles的输入语义:POSITIONPSIZEFOGCOLOR0-COLOR1TEXCOORD0-TEXCOORD7

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

        示例:

void main_v(float4 position: POSITION, 
	    out float4 oposition : POSITION,
	    uniform float4x4 modelViewProj)
{
	//oposition = mul(modelViewProj,position); 
}

        为了保持顶点程序输出语义和片元程序输入语义的一致性,通常使用相同的 struct类型数据作为两者之间的传递,这是一种非常方便的写法,推荐使用。

        示例:

struct VertexIn {
    float4 position : POSITION; 
    float4 normal : NORMAL;
};

struct VertexScreen {
    float4 oPosition : POSITION;
    float4 objectPos : TEXCOORD0; 
    float4 objectNormal : TEXCOORD1;
};

        注意:当使用struct结构中的成员变量绑定语义时,需要注意到顶点着色程序中使用的POSITION语义词,是不会被片元程序所使用的。

        如果需要从顶点着色程序向片元程序传递数据,例如顶点投影坐标、光照信息等则可以声明另外的参数,绑定到TEXCOORD系列的语义词进行数据传递,,实际上TEXCOORD系列的语义词通常都被用于从顶点程序向片段程序之间传递数据。

        当然,你也可以选择不使用struct结构而直接在函数形参中进行语义绑定。无论使用何种方式都要记住vertex program中的绑定语义(POSITION除外)的输出形参中的数据会传递到fragment program中绑定相同语义的输入形参中。

6、片元着色器的输入语义

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

void main_f(out float4 color : COLOR) 
{ 
	color.xyz = float3(1.0,1.0,1.0); 
	color.w = 1.0; 
}

7、语义绑定方法

        入口函数输入\输出数据的绑定语义有四种方法:

//绑定语义放在函数的参数列表的参数声明后面中
[const] [in|out |inout]<type><identifier> [ : <binding-semantic>][=<initializer>]

//绑定语义可以放在结构体(struct)的成员变量后面
struct <struct-tag> { 
<type><identifier> [:<binding-semantic >]; 
}; 

//绑定语义词可以放在函数声明的后面
<type> <identifier> (<parameter-list>) [:<binding-semantic] {
<body>
}

//最后一种语义绑定的方法是,将绑定语义词放在全局非静态变量的声明后面
<type> <identifier> [:<binding-semantic>][=<initializer>]; 

四、函数与程序设计

1、Cg函数

        Cg 语言中的函数声明形式与 C\C++中相同由返回类型(return type)、函数名、形参列表(parameter list, 位于括号中,并用逗号分隔的参数表)和函数体组成,函数体包含在花括号中。 如果没有返回值则函数的返回类型是 void

        Cg 语言支持函数重载(Functon Overlaoding),其方式和 C++基本一致通过形参列表的个数和类型来进行函数区分。

        所谓入口函数,即一个程序执行的入口例如 C\C++程序中的 main()函数。通常高级语言程序中只有一个入口函数不过由于着色程序分为顶点程序和片断程序两者对应着图形流水线上的不同阶段所以这两个程序都各有一个入口函数。

2、Cg标准函数库

        和 C 的标准函数库类似Cg 提供了一系列内建的标准函数。这些函数用于执行数学上的通用计算或通用算法(纹理映射等)

        Cg 标准函数库主要分为五个部分

        数学函数(Mathematical Functions);

        几何函数(Geometric Functions);

        纹理映射函数(TextureMapFunctions);

        偏导数函数(Derivative Functions);

        调试函数(Debugging Function);

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值