一、测试用例
如果场景中有大量重复显示对象,并且使用的图片纹理相同,使用Graphics的drawTexture或drawTextures有奇效。以下测试代码中,只有一个作为父容器的sprite,无论添加多少个显示对象(可以是不同图集的texture),sprite数量不会再增加,仅仅增加一个drawcall。
import WebGL = Laya.WebGL;
// 程序入口
class GameMain {
constructor() {
Laya.init(750, 1334, WebGL);
Laya.Stat.show();
Laya.loader.load(["res/atlas/apes.atlas", "res/atlas/comp.atlas"],
Laya.Handler.create(this, this.loadComp));
}
private loadComp(): void {
var t: Laya.Texture = Laya.loader.getRes("apes/monkey2.png");
var p: Laya.Sprite = new Laya.Sprite();
this.createImages1(p, t);
// this.createImages2(p, t);
Laya.stage.addChild(p);
}
//sprite:21,drawcall:1,curmem:19.97M
private createImages1(p: Laya.Sprite, t: Laya.Texture): void {
for (var i: number = 0; i < 20; i++) {
var img: Laya.Image = new Laya.Image();
img.graphics.drawTexture(t);
img.pos(50, i * 50);
p.addChild(img);
}
//cachAs=bitmap导致curmem变为20.58M
p.cacheAs = "bitmap";
}
//sprite:1,drawcall:2,curmem:19.97M
private createImages2(p: Laya.Sprite, t: Laya.Texture): void {
var pos: any[] = [];
for (var i: number = 0; i < 20; i++) {
pos.push(50, i * 50);
}
p.graphics.drawTextures(t, pos);
var t3: Laya.Texture = Laya.loader.getRes("comp/image.png");
for (i = 0; i < 20; i++) {
p.graphics.drawTexture(t3, 250, i * 50);
}
}
}
new GameMain();
看一下引擎的源代码:
//Graphics.as:
/**
* 批量绘制同样纹理。
* @param tex 纹理。
* @param pos 绘制坐标。
*/
public function drawTextures(tex:Texture, pos:Array):void {
if (!tex) return;
_saveToCmd(Render._context._drawTextures, [tex, pos]);
}
//RenderContext.as
public function _drawTextures(x:Number, y:Number, args:Array):void
{
if (args[0].loaded) this.ctx.drawTextures(args[0], args[1], x+this.x, y+this.y);
}
//WebGLContext2D.as
public override function drawTextures(tex:Texture, pos:Array, tx:Number, ty:Number):void {
if (!(tex.loaded && tex.bitmap && tex.source)) //source内调用tex.active();
{
sprite && Laya.timer.callLater(this, _repaintSprite);
return;
}
var pre:Rectangle = _clipRect;
_clipRect = MAXCLIPRECT;
if (!_drawTextureM(tex, pos[0], pos[1], tex.width, tex.height, tx, ty, null, 1)) {
alert("drawTextures err");
return;
}
_clipRect = pre;
Stat.drawCall++;//= pos.length / 2;
if (pos.length < 4)
return;
var finalVB:VertexBuffer2D = _curSubmit._vb || _vb;
var sx:Number = _curMat.a, sy:Number = _curMat.d;
for (var i:int = 2, sz:int = pos.length; i < sz; i += 2) {
GlUtils.copyPreImgVb(finalVB,
(pos[i] - pos[i - 2]) * sx, (pos[i + 1] - pos[i - 1]) * sy);
_curSubmit._numEle += 6;
}
_maxNumEle = Math.max(_maxNumEle, _curSubmit._numEle);
}
其中有一行Stat.drawCall++;//= pos.length / 2;
至于GlUtils.copyPreImgVb怎么画的,没看懂
二、与cacheAs = "bitmap";的区别
cacheAs=bitmap也能把drawcall降到1,但是CurMem会上升。在上述测试代码中,会从19.97M上升至20.58M