[LayaAir 1.0]1.0 骨骼drawcall优化猥琐方法
适合那些这辈子都不可能把项目迁移到2.0的童鞋
先说下1.0里骨骼渲染大致流程:
大概是从BoneSlot开始,draw方法中大体上会把部件分为两种,
一种是简单贴图,没有作蒙皮的,这个最终blablabla是通过SubmitTexture提交渲染的,SubmitTexture对drawcall是有优化的,它会通过WebGLContext2D里的字段_renderKey(一个私有字段到处全局赋值也是醉了),去检查当前待渲染贴图和上一张贴图是否符合优化条件,去决定是否在一个Submit里塞上多份绘制数据 ;
所以如果动画部件是连续的简单贴图,那dawcall是可以合并的;
然后就是蒙皮的部件了,1.0里面每个BoneSlot的draw里如果发现需要绘制的是带蒙皮的部件,就会创建一个Submit,这里没有诸如SubmitTexture一样的猥琐合批操作,
所以我们可以自己魔改啊ヾ(=゚・゚=)ノ喵♪
思路大致上是这样的,先贴一下SkinMesh里相关方法:
public function render(context:*, x:Number, y:Number):void {
if (Render.isWebGL && mTexture) {
context._renderKey = 0;
context._shader2D.glTexture = null;
SkinMeshBuffer.getInstance().addSkinMesh(this);
// todo : 这是是不是可以合并下同一贴图的submit?
var tempSubmit:Submit = Submit.createShape(context, mIBBuffer, mVBBuffer, mEleNum, _indexStart, Value2D.create(ShaderDefines2D.SKINMESH, 0));
transform || (transform = Matrix.EMPTY);
transform.translate(x, y);
Matrix.mul(transform, context._curMat, _tempMatrix);
transform.translate( -x, -y);
//此处每次都创建新的数组,应该可以改成使用对象池
var tShaderValue:SkinSV = tempSubmit.shaderValue as SkinSV;
var tArray:Array = tShaderValue.u_mmat2||RenderState2D.getMatrArray();
RenderState2D.mat2MatArray(_tempMatrix, tArray);
tShaderValue.textureHost = mTexture;
tShaderValue.offsetX = 0;
tShaderValue.offsetY = 0;
tShaderValue.u_mmat2 = tArray;
tShaderValue.ALPHA = context._shader2D.ALPHA;
context._submits[context._submits._length++] = tempSubmit;
}
else if (Render.isConchApp&&mTexture)
{
transform || (transform=Matrix.EMPTY);
context.setSkinMesh&&context.setSkinMesh(x, y, _ps, mVBData, mEleNum, 0, mTexture,this.transform );
}
}
要做的就是当发现当前绘制的贴图符合合批条件时,不要新建Submit了,而是直接把绘制数据塞上一个Submit里去,
这里主要是要处理一下u_mmat2,把变换这步从shader里挪出来,在这里
private function _initMyData():void
{
var vsI:int=0;
var vI:int=0;
var vLen:int= _verticles.length;
var tempVLen:int = vLen * 4;
_vs = _tempVS;
var insertNew:Boolean=false;
if (Render.isConchNode || Render.isConchApp)
{
_vs.length = tempVLen;
insertNew = true;
}else
{
if (_vs.length < tempVLen)
{
_vs.length = tempVLen;
insertNew = true;
}
}
_tVSLen = tempVLen;
if (insertNew)
{
while (vsI < tempVLen)
{
_vs[vsI] = _verticles[vI];
_vs[vsI + 1] = _verticles[vI + 1];
_vs[vsI + 2] = _uvs[vI];
_vs[vsI + 3] = _uvs[vI + 1];
_vs[vsI + 4] = 1;
_vs[vsI + 5] = 1;
_vs[vsI + 6] = 1;
_vs[vsI + 7] = 1;
vsI += 8;
vI += 2;
}
}else
{
while (vsI < tempVLen)
{
_vs[vsI] = _verticles[vI];
_vs[vsI + 1] = _verticles[vI + 1];
_vs[vsI + 2] = _uvs[vI];
_vs[vsI + 3] = _uvs[vI + 1];
vsI += 8;
vI += 2;
}
}
}
处理掉,具体怎么处理Matrix类里有现成的,就懒得说啦XD
再然后,贴一下Submit里的相关方法
/*
create方法只传对submit设置的值
*/
public static function createSubmit(context:WebGLContext2D, ib:IndexBuffer2D, vb:VertexBuffer2D, pos:int, sv:Value2D):Submit {
var o:Submit = _cache._length ? _cache[--_cache._length] : new Submit();
if (vb == null) {
vb = o._selfVb || (o._selfVb = VertexBuffer2D.create(-1));
vb.clear();
pos = 0;
}
o._ib = ib;
o._vb = vb;
o._startIdx = pos * CONST3D2D.BYTES_PIDX;
o._numEle = 0;
var blendType:int = context._nBlendType;
o._blendFn = context._targets ? BlendMode.targetFns[blendType] : BlendMode.fns[blendType];
o.shaderValue = sv;
o.shaderValue.setValue(context._shader2D);
var filters:Array = context._shader2D.filters;
filters && o.shaderValue.setFilters(filters);
return o;
}
在创建的时候,如果发现本帧中,上一个ISubmit是Submit,并且使用的 贴图是一样的,那么就不创建新的Submit了,直接把上一个Submit的_numEle加一下这次要创建的顶点数就好了;
再再然后怎么判断上一个ISubmit,就自己各显神通啦,我自己是在每个submit类里创建时候赋值一下全局变量lastSubmit来辅助判断的
完
先说下1.0里骨骼渲染大致流程:
大概是从BoneSlot开始,draw方法中大体上会把部件分为两种,
一种是简单贴图,没有作蒙皮的,这个最终blablabla是通过SubmitTexture提交渲染的,SubmitTexture对drawcall是有优化的,它会通过WebGLContext2D里的字段_renderKey(一个私有字段到处全局赋值也是醉了),去检查当前待渲染贴图和上一张贴图是否符合优化条件,去决定是否在一个Submit里塞上多份绘制数据 ;
所以如果动画部件是连续的简单贴图,那dawcall是可以合并的;
然后就是蒙皮的部件了,1.0里面每个BoneSlot的draw里如果发现需要绘制的是带蒙皮的部件,就会创建一个Submit,这里没有诸如SubmitTexture一样的猥琐合批操作,
所以我们可以自己魔改啊ヾ(=゚・゚=)ノ喵♪
思路大致上是这样的,先贴一下SkinMesh里相关方法:
public function render(context:*, x:Number, y:Number):void {
if (Render.isWebGL && mTexture) {
context._renderKey = 0;
context._shader2D.glTexture = null;
SkinMeshBuffer.getInstance().addSkinMesh(this);
// todo : 这是是不是可以合并下同一贴图的submit?
var tempSubmit:Submit = Submit.createShape(context, mIBBuffer, mVBBuffer, mEleNum, _indexStart, Value2D.create(ShaderDefines2D.SKINMESH, 0));
transform || (transform = Matrix.EMPTY);
transform.translate(x, y);
Matrix.mul(transform, context._curMat, _tempMatrix);
transform.translate( -x, -y);
//此处每次都创建新的数组,应该可以改成使用对象池
var tShaderValue:SkinSV = tempSubmit.shaderValue as SkinSV;
var tArray:Array = tShaderValue.u_mmat2||RenderState2D.getMatrArray();
RenderState2D.mat2MatArray(_tempMatrix, tArray);
tShaderValue.textureHost = mTexture;
tShaderValue.offsetX = 0;
tShaderValue.offsetY = 0;
tShaderValue.u_mmat2 = tArray;
tShaderValue.ALPHA = context._shader2D.ALPHA;
context._submits[context._submits._length++] = tempSubmit;
}
else if (Render.isConchApp&&mTexture)
{
transform || (transform=Matrix.EMPTY);
context.setSkinMesh&&context.setSkinMesh(x, y, _ps, mVBData, mEleNum, 0, mTexture,this.transform );
}
}
要做的就是当发现当前绘制的贴图符合合批条件时,不要新建Submit了,而是直接把绘制数据塞上一个Submit里去,
这里主要是要处理一下u_mmat2,把变换这步从shader里挪出来,在这里
private function _initMyData():void
{
var vsI:int=0;
var vI:int=0;
var vLen:int= _verticles.length;
var tempVLen:int = vLen * 4;
_vs = _tempVS;
var insertNew:Boolean=false;
if (Render.isConchNode || Render.isConchApp)
{
_vs.length = tempVLen;
insertNew = true;
}else
{
if (_vs.length < tempVLen)
{
_vs.length = tempVLen;
insertNew = true;
}
}
_tVSLen = tempVLen;
if (insertNew)
{
while (vsI < tempVLen)
{
_vs[vsI] = _verticles[vI];
_vs[vsI + 1] = _verticles[vI + 1];
_vs[vsI + 2] = _uvs[vI];
_vs[vsI + 3] = _uvs[vI + 1];
_vs[vsI + 4] = 1;
_vs[vsI + 5] = 1;
_vs[vsI + 6] = 1;
_vs[vsI + 7] = 1;
vsI += 8;
vI += 2;
}
}else
{
while (vsI < tempVLen)
{
_vs[vsI] = _verticles[vI];
_vs[vsI + 1] = _verticles[vI + 1];
_vs[vsI + 2] = _uvs[vI];
_vs[vsI + 3] = _uvs[vI + 1];
vsI += 8;
vI += 2;
}
}
}
处理掉,具体怎么处理Matrix类里有现成的,就懒得说啦XD
再然后,贴一下Submit里的相关方法
/*
create方法只传对submit设置的值
*/
public static function createSubmit(context:WebGLContext2D, ib:IndexBuffer2D, vb:VertexBuffer2D, pos:int, sv:Value2D):Submit {
var o:Submit = _cache._length ? _cache[--_cache._length] : new Submit();
if (vb == null) {
vb = o._selfVb || (o._selfVb = VertexBuffer2D.create(-1));
vb.clear();
pos = 0;
}
o._ib = ib;
o._vb = vb;
o._startIdx = pos * CONST3D2D.BYTES_PIDX;
o._numEle = 0;
var blendType:int = context._nBlendType;
o._blendFn = context._targets ? BlendMode.targetFns[blendType] : BlendMode.fns[blendType];
o.shaderValue = sv;
o.shaderValue.setValue(context._shader2D);
var filters:Array = context._shader2D.filters;
filters && o.shaderValue.setFilters(filters);
return o;
}
在创建的时候,如果发现本帧中,上一个ISubmit是Submit,并且使用的 贴图是一样的,那么就不创建新的Submit了,直接把上一个Submit的_numEle加一下这次要创建的顶点数就好了;
再再然后怎么判断上一个ISubmit,就自己各显神通啦,我自己是在每个submit类里创建时候赋值一下全局变量lastSubmit来辅助判断的
完
没有找到相关结果
已邀请:
要回复问题请先登录
4 个回复
yc999999
赞同来自:
yc999999
赞同来自:
182*****089
赞同来自:
victor3345
赞同来自: