cocos2dx源码分析:渲染指令BatchCommand

BatchCommand是批次渲染指令,一次可以渲染多个三角形(GL_TRIANGLES),目前仅被粒子系统使用(ParticleBatchNode)
初始化参数

float globalOrder, 全局zorder,决定渲染属性
GLProgram* shader, 着色程序
BlendFunc blendType, 混合函数
TextureAtlas *textureAtlas, 需要渲染的三角形数据
const Mat4& modelViewTransform, 坐标转换矩阵
uint32_t flags,标志位

BatchCommand初始化时,保存了初始化参数

void BatchCommand::init(float globalOrder, GLProgram* shader, BlendFunc blendType, TextureAtlas *textureAtlas, const Mat4& modelViewTransform, uint32_t flags)
{
    CCASSERT(shader, "shader cannot be null");
    CCASSERT(textureAtlas, "textureAtlas cannot be null");

    RenderCommand::init(globalOrder, modelViewTransform, flags);
    _textureID = textureAtlas->getTexture()->getName();
    _blendType = blendType;
    _shader = shader;

    _textureAtlas = textureAtlas;

    _mv = modelViewTransform;
}

在处理BatchCommand时,是通过_textureAtlas->drawQuads()进行绘制的

void BatchCommand::execute()
{
    /*设置着色器脚本和纹理*/
    // Set material
    _shader->use();
    _shader->setUniformsForBuiltins(_mv);
    GL::bindTexture2D(_textureID);
    GL::blendFunc(_blendType.src, _blendType.dst);

    // Draw
    _textureAtlas->drawQuads();
}

最后通过drawNumberOfQuads进行渲染操作

void TextureAtlas::drawQuads()
{
    this->drawNumberOfQuads(_totalQuads, 0);
}
void TextureAtlas::drawNumberOfQuads(ssize_t numberOfQuads, ssize_t start)
{
    CCASSERT(numberOfQuads>=0 && start>=0, "numberOfQuads and start must be >= 0");

    if(!numberOfQuads)
        return;
    /*绑定纹理*/
    GL::bindTexture2D(_texture->getName());
    /*是否使用vao进行不同处理,vao是渲染优化,opengles2.0不支持,3.0支持*/
    if (Configuration::getInstance()->supportsShareableVAO()) { // // Using VBO and VAO // // FIXME:: update is done in draw... perhaps it should be done in a timer if (_dirty) { /*渲染数据更新*/ glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0]); // option 1: subdata // glBufferSubData(GL_ARRAY_BUFFER, sizeof(_quads[0])*start, sizeof(_quads[0]) * n , &_quads[start] ); // option 2: data // glBufferData(GL_ARRAY_BUFFER, sizeof(quads_[0]) * (n-start), &quads_[start], GL_DYNAMIC_DRAW); // option 3: orphaning + glMapBuffer glBufferData(GL_ARRAY_BUFFER, sizeof(_quads[0]) * _capacity, nullptr, GL_DYNAMIC_DRAW); void *buf = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); memcpy(buf, _quads, sizeof(_quads[0])* _totalQuads); glUnmapBuffer(GL_ARRAY_BUFFER); glBindBuffer(GL_ARRAY_BUFFER, 0); _dirty = false; } GL::bindVAO(_VAOname); #if CC_REBIND_INDICES_BUFFER glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]); #endif /*绘制三角形*/ glDrawElements(GL_TRIANGLES, (GLsizei) numberOfQuads*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(_indices[0])) ); GL::bindVAO(0); #if CC_REBIND_INDICES_BUFFER glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); #endif // glBindVertexArray(0); } else { // // Using VBO without VAO // /*渲染数据更新*/ #define kQuadSize sizeof(_quads[0].bl) glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0]); // FIXME:: update is done in draw... perhaps it should be done in a timer if (_dirty) { glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(_quads[0]) * _totalQuads , &_quads[0] ); _dirty = false; } GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX); // 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]); /*绘制三角形*/ glDrawElements(GL_TRIANGLES, (GLsizei)numberOfQuads*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(_indices[0]))); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,numberOfQuads*6); CHECK_GL_ERROR_DEBUG(); }

你可能感兴趣的:(cocos2d-x)