AGAL(Adobe Graphics Assembly Language) 语言是Adobe 公司为stage3D 开发一门图形渲染语言,类似 Opengl Shader Language.

AGAL有30个指令,并不复杂. 只要熟练掌握这30个指令的使用方式,以及如果将程序参数传入AGAL,以及从AGAL中输出参数,就可以入门编写自己想要的效果了.

在寄存器中 有128个存储临时变量的地方 v0-v127

现在针对一个最简单的 AGAL shader 程序,来看看如何操作

[cc lang=”actionscript3″ nowrap=”false”]
var fragmentShaderAssembler : AGALMiniAssembler = new AGALMiniAssembler();
fragmentShaderAssembler.assemble(Context3DProgramType.FRAGMENT,
“mov oc, v2n”
);

[/cc]
这个操作是将 v2 中的变量输出到 oc 中.

[cc lang=”actionscript3″ nowrap=”false”]
meshIndexData = Vector.(
[0,1,2, 0,2,3]
);

meshVertexData = Vector.(
[ -1,-1,1, 0,0, 0,0,1, 1.0,0.0,0.0,1.0,
1,-1,1, 1,0, 0,0,1, 0.0,1.0,0.0,1.0,
1,1,1, 1,1, 0,0,1, 0.0,0.0,1.0,1.0,
-1,1,1, 0,1, 0,0,1, 1.0,1.0,1.0,1.0
]);
[/cc]
这个操作构造了2个三角形,IndexData 为三角形要用到的顶点索引位, VertexData 为顶点数据

[cc lang=”actionscript3″ nowrap=”false”]
//rgba
context3D.setVertexBufferAt(2, vertexBuffer, 8, Context3DVertexBufferFormat.FLOAT_4);
[/cc]
将rgba的数值传入渲染.
setVertexBufferAt 的第一个参数就是要使用的 临时寄存器位置, 2 表示 使用v2(0-7). vertexBuffer 为数据, 8 表示要使用的数据是从 VertexData 顶点数据中第8位开始的 即 “1.0,0.0,0.0,1.0”, 最后一个参数是 FLOAT_4 即要使用的数据类型,它表示我们要使用一个4位的浮点型,rgba有4位,如果你传入的是顶点数据x,y,z, 那么你应该使用的是 FLOAT_3 . 对于rgba来说,他们是不可能出现负数的,这意味着你使用BYTES_4 也是可行的,而且最好这么使用.

试着让一个自定义的材质呈现不同颜色
在 agal 中要渲染一个材质的话,需要如下shader
[cc lang=”actionscript3″ nowrap=”false”]
var fragmentShaderAssembler : AGALMiniAssembler = new AGALMiniAssembler();
fragmentShaderAssembler.assemble(Context3DProgramType.FRAGMENT,
“tex ft0, v1, fs0 <2d,repeat,miplinear>n” +
“mov oc, ft0n”
);
[/cc]
“tex ft0, v1, fs0 <2d,repeat,miplinear>n” 指从 fs0 的地方取得材质, 从 v1 的地方取得 坐标系, 然后将他们存入 ft0
“mov oc, ft0n” 将 ft0 的数据输出
那么怎么给 fs0 和 v1 赋值呢?
fs0 赋值方式为 context3D.setTextureAt(0,myTexture);
v1 赋值方式为 context3D.setVertexBufferAt(1, vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2); v1 的数据就只之前的 meshData 从第三位开始的 U,V 数据.

从上面的agal代码中,我们将材质的颜色仅仅是重现而已,并没有让它呈现不同颜色,接下来,我们来常识实现变色

shader如下
[cc lang=”actionscript3″ nowrap=”false”]
var fragmentShaderAssembler3 : AGALMiniAssembler = new AGALMiniAssembler();
fragmentShaderAssembler3.assemble(Context3DProgramType.FRAGMENT,
“tex ft0, v1, fs0 <2d,repeat,miplinear>n” +
“mul ft1, v2, ft0n” +
“mov oc, ft1n”
);
[/cc]
这个shader程序仅仅比之前多一行
“mul ft1, v2, ft0n” 的操作为 对于材质的每一个像素 都乘以 从v2中获取的rgba参数,并将结果存入 ft1
“mov oc, ft1n” 将这些参数输出

如果不是针对每一个像素,而是让整个材质呈现同一种颜色.
只需要将第二句改变为 “mul ft1, fc0, ft0n”
fc0 的赋值方式为 context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT,0,Vector.([1,0,0,1]));

最后整理一下AS3.0 中 API的解释,以及所有寄存器的定义,最后是30个寄存器列表
Continue reading

使用MoleHill 来构建一个选择的方形,不借助任何现成的第三方引擎.
直接上代码
代码中的注释已经非常的详尽了.

提前做一个绘制方向顶点定义的解释
[cc lang=”actionscript3″ nowrap=”false”]
private function initData() : void
{
//定义每个多边形用到的顶点
//一个方形是由2个三角形构成的
meshIndexData = Vector.
([
0,1,2, 0,2,3,
]);

// 源数据需要用到4个顶点
// xyz坐标, texture 坐标系 UV, 归一化 xyz
meshVertexData = Vector.
([
//X, Y, Z, U, V, nX, nY, nZ
-1, -1, 1, 0, 0, 0, 0, 1,
1, -1, 1, 1, 0, 0, 0, 1,
1, 1, 1, 1, 1, 0, 0, 1,
-1, 1, 1, 0, 1, 0, 0, 1
]);
}
[/cc]

meshIndexData 的作用是顶点索引,即告诉渲染程序,当前顶点的数据要从 顶点数据集中的第几个索引中去取.
meshIndexData 的长度6,在渲染网格的时候将其长度/2 来告诉程序每个网格要到3个顶点.
meshVertexData 就是顶点数据 长度为4, 每8个为1组,因此渲染网格的时候将其长度/8
meshVertexData 中的xyz 构成的是一个坐标系中的方形的4个坐标点 UV用来定义该点唯一坐标系的中哪一个区域, 其中0表示负半轴,1表示正半轴
nx,ny,nz表示归一化后的xyz坐标

后面是完整代码和demo
Continue reading

手头项目做到尾声了。 在整理代码的时候无意中想到,项目中大量的用到了 greenSock 的 TweenMax 和 TweenLite 甚至是 Loader

查询资料后发现 这个开源的缓动类库实际上不允许运用在 商业项目中的。项目要是在国内运营还好,问题是项目是运营在facebook 上的,这样就比较危险了。
于是动手自己编写了一个缓动类库进行替换(还好项目中只有4处用到了缓动)。 但是!! 由于项目中打击怪物掉落物品的这一个效果是使用 TweenMax 的俱乐部插件绘制的抛物线,这块要自行模拟就比较复杂了。

由于要实现的效果是物品上抛时减速,下落时加速的效果。
于是我先根据抛物线公式,通过x轴偏移计算当前y轴高度。
Continue reading

可以结合此文共同观看
人工智能-基于位置的触发器管理

之前的一个月的某一段时间,私在为公司一款游戏的免费体验版本编写本地人工智能系统。 准确的说,是RPG即时战斗部分的人工智能。

先来确定智能战斗系统的中的AI思考类型

友好型 – 无法被攻击,也无法攻击别人
中立型 – 不主动攻击,被攻击后开始反击
进攻型 – 同阵营之外,范围内主动攻击

之后确定AI状态机中的几个状态

RESET – 脱离战斗,复位,刷新时用到的状态
RUN – 跑动状态
ATTACK – 攻击状态
SEARCH – 索敌状态
STAND – 发呆状态
WANDER – 漫游状态

以 进攻型 AI为例,各状态的衔接如下
默认 WANDER 每N毫秒间隔 切换至 SEARCH , 如果索敌成功 切换至 RUN, 索敌失败 切换回 WANDER。
当进入 RUN 时 每N毫秒间隔 判断目标是是否进入攻击范围 , 如果是,切换至 ATTACK, 如果否 保持 RUN。
当进入 RUN 时 每N毫秒间隔 判断目标是否脱离索敌区域, 如果是,切换至 RESET, 如果否 保持 RUN。
当进入 ATTACK时 每N毫秒间隔 判断目标是否在攻击范围 , 如果是, 攻击, 如果否,切换回 RUN。
当进入 ATTACK时 每N毫秒间隔 判断目标是否死亡, 如果是, 切换至 RESET, 如果否, 保持 ATTACK。
当进入 RESET 时 AI 重置(移动)到出生点,刷新状态后,切换至 WANDER

当上述状态转换过程中,将会出现一种临界状态,即目标刚好在索敌区域边缘,而目标同时在移动, 会导致AI反复进入ATTACK后,由于目标反复脱离 攻击范围,导致 AI 反复追击停顿,无法成功攻击。

解决方案可以为, 当进入 ATTACK 时,已知是 RUN 状态切换过来的,因此此时目标肯定在攻击范围内, 所以进入状态后先进行一次攻击后,再做范围判断。

下面是 攻击型 AI的实现伪代码

[挖个坑,每日填]

在3D引擎中,影响到性能的主要是材质和面,大量的高分辨率的高色彩的材质十分占用内存,而大量的面会影响CPU的计算速度。
这一次只讨论如何来削减面数。

看到很多朋友削减面数的方式都是从模型身上下手,削减多余的面,看不见的面。那么即使如此,如果这个模型需要旋转,那么模型的背后的面肯定不能剔除。
那么,这时候就可以考虑从3D引擎的底层渲染机制下手了。

才3D引擎中,摄像机捕捉的画面实际上是由一个 近截面 和 一个 远截面 构成的一个多边形,所有近于近截面的物体不渲染,所有远与远截面的物体不渲染。 因此,从此部开始就可以把视野外的物体全部移除, 但这还不够。

我们为什么不能把,即使在视野内,但是此刻看不到的面也移除呢?

摄像机的本质就是向量,而 向量 * 顶点 有这么一个性质:
1。 当向量 U 和 顶点 V 的夹角为 90°时, 他们的乘积为0
2。 当向量 U 和 顶点 V 的夹角大于 90°时,乘积<0 3。 当向量 U 和 顶点 V 的夹角小于 90°时,乘积>0

那么对于一个立方体(8个顶点) 可以做如下判断,来知道哪个顶点是可视的
[cc lang=”actionscript3″ nowrap=”false”]
var viewList : Vector. = new Vector.();
for each(var v : Point3D in Cube)
{
if(v * u > 0) viewList.push(v);
}
[/cc]
当取得所有可见顶点后,就可以把他们关联的面推入待渲染列表了。

而对于一个处于临界区域的多边形来说,上面的方式是不够的。 那么可以以该多边形的中心点为圆心,最远顶点长度为半径构建一个球体。然后判断该球体是否与 近截面 和 远截面 构成的多边形相交,如果不相交,则整个多边形完全不渲染。
对于相交区域再次采用上面的向量算法来判断。

傍晚逛了下论坛,发现了几个帖子在争论 Html5, Unity3D 和 Flash

参与者是 “nickly8989”, “Sliz 国内stage3D引擎 are2D的开发者” 和 “俺”

nickly8989 的观点是 积极学习新技术,如果新技术更成熟,就选择用更成熟的技术

Slize 观点是 Flash 能做,还要其他干嘛

对于这个,我真心有很多话要说,且本人就是一个不崇拜权威的人,就算你会开发 stage3D的引擎又怎样? 并且,本人从来不把一门语言死抱着不放,本人追求的就是先进的思想,成熟的解决方案, 所以我的观点基本同意 nickly8989

下面是帖子引用,于最后我在帖子中发表的观点。

 
Continue reading

用Unity3d 实现一个简易的任务系统,任务都所有状态都在npc身上。 任务物品收集状态是绑定在摄像机上的,二者通过 GameObject.Find 找到对方,然后通过pulic function 进行赋值。

由于MonoDevelop 对中文支持性很差,必须为Unidecode编码才能显示,否则就是乱码,因此为了方便,对话全部用了英文。
Continue reading


渐渐的熟悉之后,就开始跳着看书了。越到后面越发现,很多东西都时曾相识呢。
Untiy3D的播放模式,跟Flare3D的播放模式居然一模一样,比如那个倒播居然都是叫 Ping Pong 模式,是潜规则吗?(笑)。
而模型的动作分块机制也是一模一样的。
Continue reading

=。=
第一周《Unity3D游戏开发》 300+页,本周内可以看完。
第二周继续研究下Away3D,以此来评估下Flare3D。 Flare3D目前的插件只有30天试用,貌似只能装载Max2010上,之后都要收费,试用版的Explore很多模型又看不来,购买授权对我这个个人开发者来说有难度…. Away3D 这块似乎有优势。。总之还是要最后评估下
第三周把这两本看完《人工智能游戏编程真言》,《AI游戏引擎程序设计》 这两本都是很不错的讲解思路的书,代码量很少,正好适合俺这种有点基础,缺点想法的人了。
第四周《3DS MAX 2012 从入门到精通》 配合Unity3D 学的,也算是为之后Stage3D 修改模型打基础吧。

一年后的今天,我终于如期踏上3D的旅程了。。。 既然Unity3D也能输出flash格式,且有自己的webPlayer,并且底层调用,高效率,高性能,跨平台,我们为什么还要坚持Flash来制作3D游戏呢? 这个答案大概7月底我就能知晓了吧~

话说Unity3D 最近花了很多的时间学,还特地买了一本书 《Unity游戏开发实战》 梅纳德(Menard M.)、史晓明、 李强 机械工业出版社 (平装 – 2012-04出版)。 还没买的童鞋可以不要买了,翻译的很烂,上下文翻得都不连贯,基本要靠我自己猜,我觉得翻译者自己根本就没有使用过Unity软件,就在那瞎猜。 嘛~ 全当我49元买了素材光盘好了。。。

嘛嘛~不过基本掌握了,地形绘制,高地图绘制,贴图,摄像机,绑定代码。。。 后面的继续慢慢挖吧。

再说Flare3D 做了一个Demo,角色动作切换,移动,摄像机越肩视角。 但是发现一个问题,就是Flare3dLoader 似乎不支持从外部网络加载f3d模型文件,会出现“错误的文件格式”,我以为是我空间的问题,于是在换了N个空间,再把空间上的文件重载下来验证,都不知道错误在哪,于是为了制作Loading…就把f3d文件嵌入一个swf中当作资源文件。 然后主文件加载这个swf做进度提示。。

像这样…

 
Continue reading