开发环境
Window7
CgToolkit
VS2008
羽化的第二十篇博客,没想到写到二十篇了,送上有点稍晚,Cg基础部分学得或多或少了,不出意外下周开始学写Cg代码了,到时候再慢慢更新在博客上,由于明哥的给力我们的地图终于支持到了6层,正在向无限层发起挑战,明哥钢霸得。。。这周翻了地牢围攻3,很精美的一款游戏,2代可以说是羽化玩过的仅次于暗黑的相同类型游戏,3代由于加入Square制作后,技术明显提升,各种Flare应用得淋漓尽致,但没了原来的朴实与多样性,彻头彻尾变成了另一个游戏。。。话说波仔被车撞了,也就是上周的事情,知道以后些许担心,但也有些许气愤,作为在上海唯一的老乡朋友,居然不告诉我。。。但幸好没事,依然和我们犀利dota- - 工作越来越忙,人手不足一直是个很头疼的问题,况且大家都没这方面经验,作为公司的第一个Unity游戏,居然做成MMORPG类型,其实羽化虽然信心满满,但总会遇到很多无法预料的问题,还是太弱了。。。
发个牢骚(以下为个人意见):其实羽化一直搞不懂,为什么一个游戏公司养这么多策划,羽化认为策划应该是一个高层次的职业少而精,对应文艺或者设计方面的人才,能提供有价值的参考和规定制作的核心内容:游戏系统、场景、剧情、数值调整等复杂设定,但现在的公司里策划却能每天悠然自得,竟是些看漫画、看电影、打游戏、吃吃零食的空虚年轻人,策划需要丰富的阅历和灵感不错,但不是玩玩国内的垃圾游戏(国内也有很多好作品,但大多数是仿制的垃圾),看几部贺岁电影能培养出来的。。。做一个MMO就想仿照魔兽世界,又搞些多余的休闲方式和活动,这样根本无法超越它,这可能就是国内游戏缺少创新的主要原因,也和这个利益社会有关系吧。羽化认为国内很少有游戏制作人这种说法,制作人应该置于策划,高于策划,控制整个游戏的制作内容而不是规定游戏的制作方式,由于缺少一个与程序、美术、策划三方交流的核心,所以经常是一堆空虚的策划在一起商量一些大家都懂的常识问题,于是又一款山寨游戏就这此诞生了。总的一句话:策划这职业不是什么人都能当的,国内的策划伤不起- -
介绍 Cg Runtime
Cg代码使用代码来描述材质,但是他们需要应用程序的支持来创建图像。在Cg的程序界面,你必须做两件事:
1. 为正确的配置编译程序,换句话说,就是我们要编译程序按照特点定的3D API的应用程序和底层硬件配置。
2. 连接程序在应用中,使其允许应用程序支持不同的和统一的数据接口给程序。
你有两种方式执行他们,一种是当应用程序编译在一个可执行文件中的时候,另一种是在运行的时候,应用程序在执行的时候。Cg Runtime是一个应用程序接口,允许Cg程序在运行时编译和链接。其优势在于未来的兼容性,没有依赖限制,输入参数管理三个方面。
Header Files 头文件
要引用Cg runtimeAPI在C或者C++中,头文件有以下几种:
核心: #include <Cg/cg.h>
OpenGL: #include <Cg/cgGL.h>
Direct3D 9: #include <Cg/cgD3D9.h>
Direct3D 8: #include <Cg/cgD3D8.h>
Creating a Context 创建关联
一个Context是一个容器包含多个Cg程序,他保存Cg程序就像分享数据意义。下面是创建方法:
CGcontext context = cgCreateContext();
Compiling a Program 编译程序
编译Cg程序通过添加一个Context通过 cgCreateProgram():CGprogram program = cgCreateProgram(context,CG_SOURCE, myVertexProgramString,CG_PROFILE_ARBVP1, "main", args);
CG_SOURCE表明myVertexProgramString,一个string类型参数,包含Cg起源代码,没有预先编译代码,甚至如果你想,Cg runtime允许你创建一个程序来预编译。
CG_PROFILE_ARBVP1是一个表面的编译程序,“main”参数给这个功能命名作为入口当程序运行时,最后args是一个空字符串的空列表,可以传递一个参数来编译。
Loading a Program 加载程序
//在Direct3D首先设置硬件
cgD3D9SetDevice(Device);
//下面读取Direct3D 9 Cg Runtime:
cgD3D9LoadProgram(program, CG_FALSE, 0);
//或者Direct3D 8 Cg Runtime:
cgD3D8LoadProgram(program, CG_FALSE, 0, 0, vertexDeclaration);
//在OpenGL则是
cgGLLoadProgram(program);
Modifying Program Parameters 参数修改
想修改参数,第一步先获得句柄:
CGparameter myParameter = cgGetNamedParameter(program, "myParameter");
myParameter是源文件中出现的参数。
第二步是设定一个参数值,这个功能取决于参数类型,下面是个例子:
cgGLSetParameter4fv(myParameter, value); //OpenGL
cgD3D9SetUniform(myParameter, value); //Direct3D
cgSetParameterValuefr(myParameter, 4, value); //数值参数可以通过Cg Runtime获得,这是被假定为一个float4类型参数
Executing a Program 执行程序
先设置配置文件,Direct3D中没有明确的配置。
cgGLEnableProfile(CG_PROFILE_ARBVP1); //OpenGL
cgGLDisableProfile(CG_PROFILE_ARBVP1); //相反
下面是绑定程序:
cgGLBindProgram(program); // OpenGL
cgD3D9BindProgram(program); //Direct3D
Releasing Resources 释放资源
cgD3D9SetDevice(0);
cgDestroyProgram(program);
cgDestroyContext(context); //破坏所有
Cg Runtime 核心
顾名思义,应用中负责提供所有的Cg管理程序,主要负责3个主要概念:context,program,parameter,依次代表了CGcontext, CGprogram, 和CGparameter object 类型。
Cg Context 核心
向Cg runtime提供创造,毁灭,查询,链接等功能。
CGcontext cgCreateContext(); //创造
void cgDestroyContext(CGcontext context); //毁灭所有链接,包括包含此链接的所有程序
CGbool cgIsContext(CGcontext context); //查询有效性
Cg Program 核心
提供创建,毁灭,迭代结束,和查询程序。
//程序直接包含源代码
CGprogram cgCreateProgram(CGcontext context,CGenum programType,
const char* program,CGprofile profile,
const char* entry,const char** args);
//一个字符串包含文件名,里面是源代码
CGprogram cgCreateProgramFromFile(CGcontext context,CGenum programType,
const char* program,CGprofile profile,
const char* entry,const char** args);
//移除程序
void cgDestroyProgram(CGprogram program);
当一个程序问完成,他会自动卸载或者释放,为了方便下次使用,程序必须重编译再加载和回收。编译可执行手动执行或者自动:
cgCompileProgram(CGprogram program); //一般用于编译或者重编译
void cgSetAutoCompile(CGcontext ctx, CGenum flag);
//后面的flag一般为CG_COMPILE_MANUAL、CG_COMPILE_IMMEDIATE、CG_COMPILE_LAZY
CGbool cgIsProgramCompiled(CGprogram program);
程序包含链接,这里提供了迭代,如果没用返回0:
CGprogram cgGetFirstProgram(CGcontext context);
CGprogram cgGetNextProgram(CGprogram program);
CGprogram program = cgGetFirstProgram(context);
while (program != 0)
{
/* Here is the code that handles the program */
program = cgGetNextProgram(program);
}
查询方法很多:
CGbool cgIsProgram(CGprogram program); //有效性
const char* cgGetLastListing(CGcontext context); //编译结果 只针对cgCreateProgram
//得到属性
CGcontext cgGetProgramContext(CGprogram program);
CGprofile cgGetProgramProfile(CGprogram program);
CGprofile cgGetProfile(const char* profileString);
const char* cgGetProfileString(CGprofile profile);
const char* cgGetProgramString(CGprogram program,
CGenum stringType);
//这里的stringType一般对应CG_PROGRAM_SOURCE、CG_PROGRAM_ENTRY、 CG_PROGRAM_PROFILE、CG_COMPILED_PROGRAM
Cg Parameters 核心
参数分为3类:程序参数、特效参数、共享参数。 分别联系着Cg programs,Cg Effects,Cg contexts。 Cg提供有提取,创建和查找程序参数。CGparameter cgGetFirstStructParameter(CGparameter parameter); //提供程序迭代,如果类型不为CG_STRUCT会返回0
同时要提供数组元素可使用:
int cgGetArrayDimension(CGparameter parameter);
int cgGetArraySize(CGparameter parameter, int dimension);
CGparameter cgGetArrayParameter(CGparameter parameter,int index); //如果类型不为CG_ARRAY会返回0
下面是一个完整的使用实例:
void IterateProgramParameters(CGprogram program)
{
RecurseProgramParameters(cgGetFirstParameter(program, CG_PROGRAM));
}
void RecurseProgramParameters(CGparameter parameter)
{
if (parameter == 0)
return;
do
{
switch(cgGetParameterType(parameter))
{
case CG_STRUCT:
RecurseProgramParameters(
cgGetFirstStructParameter(parameter));
break;
case CG_ARRAY:
int arraySize = cgGetArraySize(parameter, 0);
for (int i = 0; i < arraySize; ++i)
RecurseProgramParameters(cgGetArrayParameter(parameter, i));
break;
default:
/* Here is the code that handles the parameter */
break;
}
} while((parameter = cgGetNextParameter(parameter))!= 0);
}
实际上,经常遍历所有参数用“leaf”:
CGparameter cgGetFirstLeafParameter(CGprogram program,CGenum namespace);
CGparameter cgGetNextLeafParameter(CGparameter parameter);
所有程序参数可以直接寻回:
CGparameter cgGetNamedProgramParameter(CGprogram program,CGenum namespace,const char* name);
Cg runtime提供的参数值管理方法:
int cgGetParameterValue{i,f,d}{r,c}(CGparameter param, int nvals, type *v);
const double* cgGetParameterValues(CGparameter parameter,CGenum valueType,int* numberOfValuesReturned);
Shared Parameters 共享参数
Cgruntime支持创建任何类型的实例参数在一个Cg context中,一个参数可能连接多个拥有相同兼容的参数,包括任何程序或者环境参数在这个链接中。
共享参数通过CGcontext连接,创建方式如下:
CGparameter cgCreateParameter(CGcontext ctx, CGtype type);
CGparameter cgCreateParameterArray(CGtype type, int length);
CGparameter cgCreateParameterMultiDimArray(CGtype type, int dim, int *lengths);
删除方式:删除后所有连接取消
Void cgDeleteParameter(CGparameter param);
连接参数:一个共享参数创建成功也许会连接很多程序,特效或者共享参数使用
void cgConnectParamteer(CGparameter source, CGparameter sink);
Void cgDisconnectParameter(param); //取消连接
Cg中也经常使用模块或者是接口,这方面使用和普通高级语言类似。
Parameter Properties 参数属性
参数属性包含很多内容,含有效性、关联、大小、以及其他属性。
interface MyInterface
{
float SomeMethod(float x);
};
struct MyStruct : MyInterface
{
float Scale;
SomeMethod(float x)
{
return(Scale * x);
}
};
上面是一个例子,如果这个程序在开始时创建,那么MyInterface和MyStruct类型将会添加到输出结果中。下面是关联类型:
CGtype cgGetParameterNamedType(CGparameter param);
CGtype cgGetNamedUserType(CGhandle handle, const char *name); //handle可以使任意cg程序或者特效
//父类可以获得所有入口点
int cgGetNumParentTypes(CGtype type);
CGtype cgGetParentType(CGtype type, int index);
//单一类型获取入口点
int cgGetNumUserTypes(CGprogram program);
CGtype cgGetUserType(CGprogram program, int index);
//针对老应用获取入口
CGtype cgGetParameterType(CGparameter parameter);
//可应用于查询
const char* cgGetTypeString(CGtype type);
//也可能是一般类型参数
CGparameterclass cgGetParameterClass(CGparameter param);
同样可以查看有效性和关联性:
CGbool cgIsParameter(CGparameter parameter);
CGbool cgIsParameterReferenced(CGparameter parameter);
查看大小:
int cgGetParameterRows(CGparameter param);
int cgGetParameterColumns(CGparameter param);
int cgGetArrayDimension(CGparameter param); //维度
int cgGetArraySize(CGparameter param, int dimension); //特定尺寸
int cgGetArrayTotalSize(CGparameter param); //总共大小
CGtype cgGetArrayType(CGparameter param); //规定类型可以在以后查询使用
//一样可以用不固定类型数组
void cgSetArraySize(CGparameter param, int size);
void cgSetMultiDimArraySize(CGparameter param, int *sizes); //多维
查看属性
CGparameterclass cgGetParameterClass(CGparameter param); //常规类查询
/*
CG_PARAMETERCLASS_SCALAR
CG_PARAMETERCLASS_VECTOR
CG_PARAMETERCLASS_MATRIX
CG_PARAMETERCLASS_STRUCT
CG_PARAMETERCLASS_SAMPLER
CG_PARAMETERCLASS_OBJECT
*/
//程序查询
CGprogram cgGetParameterProgram(CGparameter parameter);
//可变性查询
CGenum cgGetParameterVariability(CGparameter parameter);
//设置可变性,这里的vary可能为CG_UNIFORM,CG_LITERAL,CG_DEFAULT
void cgSetParameterVariability(CGparameter parameter, CGenum vary);
//获取参数方向
CGenum cgGetParameterDirection(CGparameter parameter);
//检索参数名
const char* cgGetParameterName(CGparameter parameter);
//取回语义字符串
const char* cgGetParameterSemantic(CGparameter parameter);
//资源分配参数,若没任何关联返回CG_UNDEFINED
CGresource cgGetParameterResource(CGparameter parameter);
//确定一个资源点和对应字符串
CGresource cgGetResource(const char* resourceString);
const char* cgGetResourceString(CGresource resource);
//允许恢复原本资源
CGresource cgGetParameterBaseResource(CGparameter parameter);
//检索数值部分资源
unsigned long cgGetParameterResourceIndex(CGparameter parameter);
//得到默认或者统一数值
const double* cgGetParameterValues(CGparameter parameter,CGenum valueType, int* numberOfValuesReturned);
Cg核心错误报告
应用程序会缓冲查询错误代码,如下方法:
CGerror error = cgGetError();
CGerror error = cgGetFirstEror();
const char* errorString = cgGetErrorString(error);
//登记错误处理器
typedef void (*CGerrorHandlerFunc)(CGcontext ctx, CGerror err, void *appdata);
void cgSetErrorHandler(CGerrorHandlerFunc func, void *data);
一般使用如下:
void HandleCgError(CGcontext ctx, CGerror err, void *appdata)
{
fprintf(stderr, "Cg error: %s\n", cgGetErrorString(err));
const char *listing = cgGetLastListing(ctx);
if (listing != NULL)
fprintf(stderr, " last listing: %s\n", listing);
}
很多网友询问羽化如何使用Unity显示广告,看过源代码由于不难,用的是羽化写过的Android调用方法,没有深入研究,只是看到明哥实现过,所以先去明哥那取下经,在做研究- -
下期预告:
Unity Android平台AdMob应用