开发环境
Window7
羽化的第十八篇博客,这周上了6天班,感觉其实和5天差不多。。。作为预演的最后一周,基本上达到了之前的要求,如何搭建地图问题在明哥的神威下得到了解决-0-这样寻路自然也是水到渠成~ ~现在多人在线基本实现,但动作补帧还有待完善,一切都很顺利,至少程序在我手上,我会尽最大可能使其完美-0- 这周把《现代战争3》完结了,游戏流程高潮迭起,绝无冷场,唯一的不足就是短了点。总的来说,使命召唤这次依然秒杀战地,前者毕竟制作经验丰富,但后者技术支持够强,依然有机会赶上。终于把360刷机了,进度很快但还是很多游戏没时间玩,游戏这坑越来越深了啊=。=
正如羽化上次说的,从图形学和Cg入手Shader,这些需要一些C/C++的基础,有很多是网上找到的资料,加上自己的理解,把相对比较重要独特的地方拿出来,感谢那些拿出来分享的人,继续开始研究- -
开始Cg之旅
在NVIDIA 的网页上下载CgToolkit ,截止到2011 年11 月,Cg 语言的版本为3.0。下载之后直接安装即可。在安装目录的bin 目录下一个可执行程序:cgc.exe。这是NVIDIA 提供的Cg 程序编译器。Cg 语言规范是公开和开放的,并且 NVIDIA 开放了Cg 编译器技术的源代码,使用无限制的、免费的许可证。目前还没有一个主流的专门为编写着色程序而开发的IDE,很多人都是直接在文本中写好程序后,然后将文件后缀改为.cg。在网上有一个名为的Visual Studio2008 插件,安装之后可以支持编写着色程序。如果Cg Toolkit 安装正确,在NVIDIA Corporation\Cg\bin 文件夹下会看到cgc.exe 文件。首先打开命令行窗口,输入“cgc –h”(引号不用输入),如果安装正确,则会出现下图所示的提示信息。
Cg的优势
Cg 同时被OpenGL 与Direct3D 两种编程API 所支持。这一点不但对开发人员而言非常方便,而且也赋予了Cg 程序良好的跨平台性。一个正确编写的Cg应用程序可以不做任何修改的同时工作在OpenGL 和Direct3D 之上。并且Nvida官网上有Cg的专业教程,为了方便学习这里羽化送上自己保存的PDF版,而且在安装目录下也有CgUsersManual,很棒的一个手册。
Cg 程序编译的命令形式
cgc [options] file
[options]表示可选配置项,file 表示Cg 程序文件名。可选配置项包括编译时选择使用的profile、着色程序的入口函数名称,以及着色程序文件名。比较典型的编译方式是:
cgc –profile glslv –entry main_vtest.cg
-profile 是profile 配置项名;glslv 是当前所使用的profile名称;-entry着色程序的入口函数名称配置项;main_v 是顶点着色程序的入口函数名;test.cg 是当前的着色程序文件名。编译器指定的着色程序入口函数名默认为main,通常为了将顶点\片段着色程序入口函数名区别开来,而并不使用默认名称。在下面所有的例子中,main_v 表示顶点着色程序入口函数名,main_f 表示片段着色程序入口函数名。
CG 数据类型
Cg支持7 种基本的数据类型:
1.float,32位浮点数据,一个符号位。浮点数据类型被所有的profile 支持(但是DirectX8 pixel profiles 在一些操作中降低了浮点数的精度和范围)
2. half,16位浮点数据
3. int,32位整形数据,有些profile会将int类型作为float类型使用
4. fixed,12位定点数,被所有的fragmentprofiles 所支持
5. bool,布尔数据,通常用于if 和条件操作符(?:),布尔数据类型被所有的profiles支持
6. sampler*,纹理对象的句柄(thehandle to a texture object),分为6 类:sampler, sampler1D, sampler2D, sampler3D, samplerCUBE,和samplerRECT。 DirectXprofiles不支持samplerRECT 类型,除此之外这些类型被所有的pixel profiles 和 NV40 vertex program profile 所支持。由此可见,在不远的未来,顶点程序也将广泛支持纹理操作
7. string,字符类型,该类型不被当前存在的profile 所支持,实际上也没有必要在Cg 程序中用到字符类型,但是你可以通过Cg runtime API 声明该类型变量,并赋值;因此,该类型变量可以保存Cg 文件的信息
除了上面的基本数据类型外,Cg还提供了内置的向量数据类型(built-invector data types),内置的向量数据类型基于基础数据类型。例如:float4,表示float 类型的4 元向量;bool4,表示bool类型4 元向量。(用过Unity的应该对Vector3和Vector4不会陌生吧- -)
结构类型
实际上Cg 中的结构体的声明、使用和C++非常类似,默认访问属性在结构体中为public,结构体的声明以关键字struct 开始,然后紧跟结构体的名字,接下来是一个大括号,并以分号结尾(不要忘了分号)。大括号中是结构体的定义,分为两大类:成员变量和成员函数。一般来说,Cg 的源代码都会在文件首部定义二个结构体,分别用于定义输人和输出的类型,这二个结构体定义与普通的C 结构定义不同,除了定义结构体成员的数据类型外,还定义了该成员的绑定语义类型( Binding Semantics),所谓绑定语义类型是为了与宿主环境进行数据交换的时候识别不同数据类型的。目前Cg 支持的绑定语义类型包括POSTION 位置),COLOR(颜色),NORMAL(法向量),Texcoord(纹理坐标)等类型。
Swizzle 操作符
可以使用Cg语言中的swizzle操作符(.)将一个向量的成员取出组成一个新的向量。swizzle操作符被GPU硬件高效支持。swizzle操作符后接x、y、z、w,分别表示原始向量的第一个、第二个、第三个、第四个元素;swizzle操作符后接r、g、b和a的含义与前者等同。不过为了程序的易读性,建议对于表示颜色值的向量,使用swizzle操作符后接r、g、b和a的方式。
举例如下:
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
输入流
Cg语言将输入数据流分为两类:
1.Varying inputs,即数据流输入图元信息的各种组成要素。从应用程序输入到GPU 的数据除了顶点位置数据,还有顶点的法向量数据,纹理坐标数据等。Cg 语言提供了一组语义词,用以表明参数是由顶点的哪些数据初始化的。
2. Uniforminputs,表示一些与三维渲染有关的离散信息数据,这些数据通常由应用程序传入,并通常不会随着图元信息的变化而变化,如材质对光的反射信息、运动矩阵等。Uniform 修辞一个参数,表示该参数的值由外部应用程序初始化并传入。uniform 修辞的变量的值是从外部传入的,所以在Cg 程序(顶点程序和片段程序)中通常使用uniform 参数修辞函数形参,不容许声明一个用uniform 修辞的局部变量!
输入\输出修辞符
Cg语言中参数传递方式同样分为“值传递”和“引用传递”,但指针机制并不被GPU 硬件所支持,所以Cg 语言采用不同的语法修辞符来区别“值传递”和“引用传递”这些修辞符分别为:
1. in: 修辞一个形参只是用于输入,进入函数体时被初始化,且该形参值的改变不会影响实参值,这是典型的值传递方式。
2. out: 修辞一个形参只是用于输出的,进入函数体时并没有被初始化,这种类型的形参一般是一个函数的运行结果;
3. inout: 修辞一个形参既用于输入也用于输出,这是典型的引用传递。
Semantic与Binding Semantics
语义词,表示输入图元的数据含义(是位置信息,还是法向量信息),也表明这些图元数据存放的硬件资源(寄存器或者纹理缓冲区)。顶点着色程序和片段着色程序中Varying inputs 类型的输入,必须和一个语义词相绑定,这称之为绑定语义(binding semantics)。
通常我们在应用程序涉及的顶点位置和法向量都是三元向量,至于为什么要将三元向量便为四元向量,又称齐次坐标,具体请看附录A。顶点位置坐标传入顶点着色程序中转化为四元向量,最后一元数据为1,而顶点法向量传入顶点着色程序中转化为四元向量,最后一元数据为0。
下期预告:
Thinking in Shader(3)