class CC_DLL MeshCommand : public RenderCommand
{
public:
MeshCommand();
virtual ~MeshCommand();
void init(float globalZOrder, Material* material, GLuint vertexBuffer, GLuint indexBuffer, GLenum primitive, GLenum indexFormat, ssize_t indexCount, const Mat4 &mv, uint32_t flags);
void init(float globalZOrder, GLuint textureID, GLProgramState* glProgramState, RenderState::StateBlock* stateBlock, GLuint vertexBuffer, GLuint indexBuffer, GLenum primitive, GLenum indexFormat, ssize_t indexCount, const Mat4 &mv, uint32_t flags);
void setDisplayColor(const Vec4& color);
void setMatrixPalette(const Vec4* matrixPalette);
void setMatrixPaletteSize(int size);
void setLightMask(unsigned int lightmask);
void execute();
//used for batch
void preBatchDraw();
void batchDraw();
void postBatchDraw();
void genMaterialID(GLuint texID, void* glProgramState, GLuint vertexBuffer, GLuint indexBuffer, BlendFunc blend);
uint32_t getMaterialID() const;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
void listenRendererRecreated(EventCustom* event);
#endif
protected:
//build & release vao
void buildVAO();
void releaseVAO();
// apply renderstate, not used when using material
void applyRenderState();
Vec4 _displayColor; // in order to support tint and fade in fade out
// used for skin
const Vec4* _matrixPalette;
int _matrixPaletteSize;
uint32_t _materialID; //material ID
GLuint _vao; //use vao if possible
GLuint _vertexBuffer;
GLuint _indexBuffer;
GLenum _primitive;
GLenum _indexFormat;
ssize_t _indexCount;
// States, default value all false
// ModelView transform
Mat4 _mv;
// Mode A: Material
// weak ref
Material* _material;
// Mode B: StateBlock
// weak ref
GLProgramState* _glProgramState;
RenderState::StateBlock* _stateBlock;
GLuint _textureID;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
EventListenerCustom* _rendererRecreatedListener;
#endif
};
##1.1 setDisplayColor 设置显示颜色
void MeshCommand::setDisplayColor(const Vec4& color)
{
CCASSERT(!_material, "If using material, you should set the color as a uniform: use u_color");
_displayColor = color;
}
##1.2 setMatrixPalette 设置调色板
void MeshCommand::setMatrixPalette(const Vec4* matrixPalette)
{
CCASSERT(!_material, "If using material, you should set the color as a uniform: use u_matrixPalette");
_matrixPalette = matrixPalette;
}
##1.3 setMatrixPaletteSize 设置调色板的数量
void MeshCommand::setMatrixPaletteSize(int size)
{
CCASSERT(!_material, "If using material, you should set the color as a uniform: use u_matrixPalette with its size");
_matrixPaletteSize = size;
}
##1.4 applyRenderState 提交渲染状态
void MeshCommand::applyRenderState()
{
CCASSERT(!_material, "Must not be called when using materials");
CCASSERT(_stateBlock, "StateBlock must be non null");
// blend and texture
GL::bindTexture2D(_textureID);
//如果有_bits 枚举位 就根据_bits 重置state的值, 否则按defaultState重置
_stateBlock->bind();
}
##1.5 batch 系列函数
//
void MeshCommand::preBatchDraw()
{
// Do nothing if using material since each pass needs to bind its own VAO
if (!_material)
{
if (Configuration::getInstance()->supportsShareableVAO() && _vao == 0)
buildVAO();
if (_vao)
{
GL::bindVAO(_vao);
}
else
{
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
// FIXME: Assumes that all the passes in the Material share the same Vertex Attribs
GLProgramState* programState = _material
? _material->_currentTechnique->_passes.at(0)->getGLProgramState()
: _glProgramState;
programState->applyAttributes();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
}
}
}
void MeshCommand::batchDraw()
{
if (_material)
{
for(const auto& pass: _material->_currentTechnique->_passes)
{
pass->bind(_mv);
glDrawElements(_primitive, (GLsizei)_indexCount, _indexFormat, 0);
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, _indexCount);
pass->unbind();
}
}
else
{
_glProgramState->applyGLProgram(_mv);
// set render state
applyRenderState();
// Draw
glDrawElements(_primitive, (GLsizei)_indexCount, _indexFormat, 0);
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, _indexCount);
}
}
void MeshCommand::postBatchDraw()
{
// when using material, unbind is after draw
if (!_material)
{
if (_vao)
{
GL::bindVAO(0);
}
else
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
// restore the default state since we don't know
// if the next command will need the default state or not
RenderState::StateBlock::restore(0);
}
}
##1.6 execute函数 在 isSkipBatching的情况下调用
void MeshCommand::execute()
{
// Draw without VAO
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
if (_material)
{
for(const auto& pass: _material->_currentTechnique->_passes)
{
pass->bind(_mv, true);
glDrawElements(_primitive, (GLsizei)_indexCount, _indexFormat, 0);
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, _indexCount);
pass->unbind();
}
}
else
{
// set render state
_glProgramState->apply(_mv);
applyRenderState();
// Draw
glDrawElements(_primitive, (GLsizei)_indexCount, _indexFormat, 0);
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, _indexCount);
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
##1.7 这里用到的主要是Pass的 bind()函数
void Pass::bind(const Mat4& modelView, bool bindAttributes)
{
// vertex attribs
if (bindAttributes && _vertexAttribBinding)
_vertexAttribBinding->bind();
auto glprogramstate = _glProgramState ? _glProgramState : getTarget()->getGLProgramState();
glprogramstate->applyGLProgram(modelView);
glprogramstate->applyUniforms();
//set render state
RenderState::bind(this);
}
void VertexAttribBinding::bind()
{
if (_handle)
{
// hardware
GL::bindVAO(_handle);
}
else
{
// software
//看来3d的还是牵连到很多其他类的感觉这个是第三方框架生成的
auto meshVertexData = _meshIndexData->getMeshVertexData();
glBindBuffer(GL_ARRAY_BUFFER, meshVertexData->getVertexBuffer()->getVBO());
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _meshIndexData->getIndexBuffer()->getVBO());
// Software mode
//根据位枚举的值设置 顶点属性的开关
GL::enableVertexAttribs(_vertexAttribsFlags);
// set attributes
for(auto &attribute : _attributes)
{
//second实质上是一个vertexAttribValue
attribute.second.apply();
}
}
}