• Overview
  • 创建 LayerColor
    • 更新 Unifrom
    • 更新 Vertex buffer
    • addCommand

    Overview

    本范例以创建 LayerColor 为例,演示如何使用 CustomCommand,以帮助开发者熟悉和理解 V4 API 使用。

    创建 LayerColor

    1. auto layerColor = LayerColor::create(Color4B::RED,
    2. visibleSize.width,
    3. visibleSize.height);

    接下来进入到 LayerColor 类内部,看看与 V3 相比,发生了哪些变化。

    在 V3,创建 shader 过程如下:

    1. setGLProgramState(GLProgramState::getOrCreateWithGLProgramName(GLProgram::SHADER_NAME_POSITION_COLOR_NO_MVP));

    与范例1一样,在初始化阶段,V4 需要完成以下几个步骤:

    • 创建 backend::ProgramState
    1. auto& pipelineDescriptor = _customCommand.getPipelineDescriptor();
    2. _programState = new (std::nothrow) backend::ProgramState(positionColor_vert,
    3. positionColor_frag);
    4. pipelineDescriptor.programState = _programState;
    5. _mvpMatrixLocation = pipelineDescriptor.programState->getUniformLocation("u_MVPMatrix");
    • 创建 backend::VertexLayout
    1. auto& vertexLayout = _customCommand.getPipelineDescriptor().vertexLayout;
    2. const auto& attributeInfo = _programState->getProgram()->getActiveAttributes();
    3. auto iter = attributeInfo.find("a_position");
    4. if(iter != attributeInfo.end())
    5. {
    6. vertexLayout.setAttribute("a_position",
    7. iter->second.location,
    8. backend::VertexFormat::FLOAT3,
    9. 0,
    10. false);
    11. }
    12. iter = attributeInfo.find("a_color");
    13. if(iter != attributeInfo.end())
    14. {
    15. vertexLayout.setAttribute("a_color",
    16. iter->second.location,
    17. backend::VertexFormat::FLOAT4,
    18. sizeof(_vertexData[0].vertices),
    19. false);
    20. }
    21. vertexLayout.setLayout(sizeof(_vertexData[0]), backend::VertexStepMode::VERTEX);
    • 创建 backend::BlendDescriptor

    CustomCommand 常见的初始化方式有两种:CustomCommand::init(float globalZOrder)CustomCommand::init(float globalZOrder, const BlendFunc& blendFunc)。因此对于第一种,你需要在手动设置 Blend 状态:

    1. backend::BlendDescriptor& blendDescriptor = _customCommand.getPipelineDescriptor().blendDescriptor;
    2. blendDescriptor.blendEnabled = true;
    3. if (_blendFunc == BlendFunc::ALPHA_NON_PREMULTIPLIED)
    4. {
    5. blendDescriptor.sourceRGBBlendFactor = backend::BlendFactor::SRC_ALPHA;
    6. blendDescriptor.destinationRGBBlendFactor = backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
    7. blendDescriptor.sourceAlphaBlendFactor = backend::BlendFactor::SRC_ALPHA;
    8. blendDescriptor.destinationAlphaBlendFactor = backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
    9. }
    10. else
    11. {
    12. blendDescriptor.sourceRGBBlendFactor = backend::BlendFactor::ONE;
    13. blendDescriptor.destinationRGBBlendFactor = backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
    14. blendDescriptor.sourceAlphaBlendFactor = backend::BlendFactor::ONE;
    15. blendDescriptor.destinationAlphaBlendFactor = backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
    16. }

    对于第二种初始化方式,需要指定 BlendFunc 即可,CustomCommand 初始化函数会根据 BlendFunc 设置对应的 Blend 状态。

    1. _blendFunc = BlendFunc::ALPHA_PREMULTIPLIED;
    2. _customCommand.init(_globalZOrder, _blendFunc);
    • 创建 backend::Buffer
    1. _customCommand.createIndexBuffer(CustomCommand::IndexFormat::U_SHORT, //index type format
    2. 6, //index count
    3. CustomCommand::BufferUsage::STATIC);
    4. unsigned short indices[] = {0, 1, 2, 2, 1, 3};
    5. _customCommand.updateIndexBuffer(indices, sizeof(indices));
    6. _customCommand.createVertexBuffer(sizeof(_vertexData[0]), //vertex size
    7. 4, //vertex count
    8. CustomCommand::BufferUsage::DYNAMIC);
    9. _customCommand.setDrawType(CustomCommand::DrawType::ELEMENT);
    10. _customCommand.setPrimitiveType(CustomCommand::PrimitiveType::TRIANGLE);

    因为 index 数据在运行过程中并不会改变,所以在创建 index buffer 时,指定 bufferUsage 为 static,并在初始化阶段更新 index buffer。vertex buffer 数据需要动态更新,参考更新 Vertex buffer。

    更新 Unifrom

    1. cocos2d::Mat4 projectionMat = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
    2. auto& pipelineDescriptor = _customCommand.getPipelineDescriptor();
    3. pipelineDescriptor.programState->setUniform(_mvpMatrixLocation,
    4. projectionMat.m,
    5. sizeof(projectionMat.m));

    更新 Vertex buffer

    CommandBuffer 提供了 updateVertexBuffer 接口用于更新顶点缓冲区数据。

    1. _customCommand.updateVertexBuffer(_vertexData, sizeof(_vertexData));

    如果需要更新 vertex buffer 的子块,可以使用 CustomCommand::updateVertexBuffer(void* data, unsigned int offset, unsigned int length) 传入偏移量即可。

    addCommand

    1. _customCommand.init(_globalZOrder, _blendFunc);
    2. renderer->addCommand(&_customCommand);