在Starling中创建3D模型 widhout Away3D

好久没有写教程神马的了,最近比较忙的说。

回到正题,最近打算在游戏中创建一个3D模型,由于游戏是Starling 2D游戏,因此打算把模型丢到UI里,3D模型出现在2D游戏里的话一定是高端大气上档次!

之前老外写的教程都是 Starling 和 Away3D 杂交, 但是仅仅在UI上摆一个3D模型就整合一个Away3D 实在是大材小用,也可以说是浪费性能, 索性自己来写一个。

先上个图。

一切以兼容为主, 实现一个类 DisplayObject3D 继承自 Starling 的显示对象 DisplayObject

之后override 其的 render 方法

1
public override function render(support:RenderSupport, parentAlpha:Number):void

do you see that? ?这里我们能获取到一个 ?RenderSupport.

这可是一个好东西, 我们能从中获取到 mvpMatrix 即 模型视图投影矩阵, 有3d 和 2d 2个版本。

然后,我们可以从 Starling.current.context 获取到 GPU的 API模组, 有了这些东西,想干啥都行了。

接下来开始干正事

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public function DisplayObject3D(modelData : ByteArray = null)
{
if(null == modelData) return;

init(modelData);
}

public function init(modelData : ByteArray) : void
{
m_context = Starling.current.context;

m_modelData = modelData;
m_meshList = new Vector.<Md5Mesh>();

createTexture();
m_md5MeshParser = new MD5MeshParser();
m_md5MeshParser.addEventListener(Event.COMPLETE, onMeshLoaded);
m_md5MeshParser.load(m_modelData);

registerPrograms(m_context);
}

我们首先在构造函数中传入一个 modelData 其内容是 md5 模型的 二进制文件了,本子就是一堆字符串, 之后在 init中对字符串进行解析,解析出其中的 顶点,索引等等

m_md5MeshParser ?的下载地址在之前的 git上

1
2
3
4
5
6
7
8
9
10
private function createTexture() : void
{
var len : int = m_textureCache.length;
for(var i : int = 0; i < len; i++){
var data : Bitmap = m_textureCache.shift();
var t : Texture = m_context.createTexture(data.width,data.height,Context3DTextureFormat.BGRA,false);
t.uploadFromBitmapData(data.bitmapData);
m_textureCache.push(t);
}
}

之后我们要将模型用到的图片转换成纹理,可以用 Starling 的 Texture.FromBitmap, 但是本人偷懒,就自己随便写个了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
private static function registerPrograms(context : Context3D) : void
{
var assembler : AGALMiniAssembler = new AGALMiniAssembler();
var vertexProgramCode : String;
var fragmentProgramCode : String;

// this is the input data we'll pass to the shaders:
//
// va0 -> position
// va1 -> color
// va2 -> texCoords
// vc0 -> alpha
// vc1 -> mvpMatrix
// fs0 -> texture

vertexProgramCode =
"m44 op va0 vc0n" +
"mov v0 va1n";

fragmentProgramCode =
"tex ft0 v0 fs0<2d,linear,repeat>n"+
"mov oc ft0 n";

m_program = context.createProgram();
m_program.upload(assembler.assemble(Context3DProgramType.VERTEX,vertexProgramCode),
assembler.assemble(Context3DProgramType.FRAGMENT,fragmentProgramCode));
}

Starling 的所有 program3D 都是有缓存的,=。= 还是因为我懒,也不缓存了。 又由于 DisplayObject3D 是可能有多个的,因此这里使用静态方法来创建这个?program3D

最后是就是 具体的 render 方法了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public override function render(support:RenderSupport, parentAlpha:Number):void
{

m_context.setCulling(Context3DTriangleFace.BACK);
m_context.setDepthTest(true, Context3DCompareMode.LESS);
if(m_meshNum)
{
if(null == m_proj)updateViewToClip();

if (m_context == null) throw new MissingContextError();
renderCuston(m_context,support);
}
m_context.setCulling(Context3DTriangleFace.NONE);
m_context.setDepthTest(false, Context3DCompareMode.ALWAYS);
}

由于 Starling 是一个2D框架,默认是关闭三角面剔除以及深度测试的,因此我们在绘制三角形前先将这两个选项打开,待渲染完毕后再将其关闭的说。

最后的最后,如果发现模型的前后像素出现错位的情况,请打开 Starling.as

找到?configureBackBuffer 函数

将??var methodArgs:Array = [width, height, antiAlias, false]; 的第4个参数, 改为 true, 由于Starling 不需要深度和模板所以默认关闭了,这里要将其打开,使深度可写

最后的最后放上这个md5扩展的git 地址

https://github.com/dreamfairy/Starling3D

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.