之前实现了MultiTexture,想要在SpriteBatchNode中也使MultiTexture生效。
SpriteBatchNode细节
- SpriteBatchNode下边的
Child Sprite必须是使用相同的纹理 - 凡是加到SpriteBatchNode下边的children都不会被visit,所以也不用担心那些Sprite会提交RenderCommand了
// override visit
// don't call visit on it's children
void SpriteBatchNode::visit(Renderer *renderer, const Mat4 &parentTransform, uint32_t parentFlags)
{
}
因为SpriteBatchNode使用了BatchCommand,而BatchCommand是不能合批的。
要让SpriteBatchNode也受MultiTexture影响实现合批,2个思路:
-
BatchCommand迁徙到TrianglesCommand。
-
仅改造SpriteBatchNode就行了,这样的影响范围最小。
内存上限
realloc尝试重新调整之前调用 malloc 或 calloc 所分配的 ptr 所指向的内存块的大小。理论没有上限制
不需要自己额外申请内存,借用BatchCommand的TextureAtlas的即可
render的memory size问题
static const int VBO_SIZE = 65536;
V3F_C4B_T2F _verts[VBO_SIZE];// 直接申请了一个很大内存的空间,用来存放顶点数据
memcpy(&_verts[_filledVertex], cmd->getVertices(), sizeof(V3F_C4B_T2F) * cmd->getVertexCount());
如果超过了内存大小,就会提交一个批次,即使能够合批
测试数据
使用SpriteBatch会提升渲染性能,相反create性能有轻微的影响。
- windows: 3w个Sprite
| -- | batch | normal |
|---|---|---|
| fps | 21 | 11 |
| creat time | 1.43s | 1.36s |
- android: 1w个Spirite
| -- | batch | normal |
|---|---|---|
| fps | 13 | 13.7 |
| creat time | 0.75s | 0.82s |
shader
setGLProgramState(GLProgramState::getOrCreateWithGLProgramName(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP, texture));
setGLProgramState(GLProgramState::getOrCreateWithGLProgramName(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR, tex));
BatchCommand
batchCommand使用TextureAtlas进行了渲染。
- draw和TrianglesCommand的VertexAttributePointer是相同的,可以合并
// vertices
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, kQuadSize, (GLvoid*) offsetof(V3F_C4B_T2F, vertices));
// colors
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (GLvoid*) offsetof(V3F_C4B_T2F, colors));
// tex coords
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, kQuadSize, (GLvoid*) offsetof(V3F_C4B_T2F, texCoords));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]);
// GLAPI void GLAPIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
glDrawElements(GL_TRIANGLES, (GLsizei)numberOfQuads*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(_indices[0])));
是存放在
ssize_t _totalQuads; // 要绘制的四边形数量,一个四边形是由2个三角形组成
GLushort* _indices; // 索引数据,在确定容量后,直接对所有顶点索引数据进行了填充,只需要一次即可
V3F_C4B_T2F_Quad* _quads; // 顶点数据
| quad | vertex | indices |
|---|---|---|
| 1 | 4 | 6 |
| 2 | 8 | 12 |
| 3 | 12 | 18 |
合批示例
配置多纹理:
MultiTexturePackage(
plist1.png/plist2.png)
Node结构如下:
- Node
- SpriteBatchNode1(
plist1.png)- Sprite1(plist1-a.png)
- Sprite2(plist1-b.png)
- SpriteBatchNode2(
plist2.png)- Sprite1(plist2-a.png)
- Sprite2(plist2-b.png)
- SpriteBatchNode1(
此时就会触发多纹理和SpriteBatchNode进一步合批,DrawCall为1