diff --git a/cocos/renderer/CCQuadCommand.cpp b/cocos/renderer/CCQuadCommand.cpp index d5cff627f6..1b12e06f0b 100644 --- a/cocos/renderer/CCQuadCommand.cpp +++ b/cocos/renderer/CCQuadCommand.cpp @@ -29,15 +29,78 @@ #include "renderer/CCGLProgram.h" #include "renderer/CCGLProgramState.h" #include "xxhash.h" +#include "renderer/CCRenderer.h" NS_CC_BEGIN - -QuadCommand::QuadCommand() +TrianglesCommand::TrianglesCommand() :_materialID(0) ,_textureID(0) ,_glProgramState(nullptr) ,_blendType(BlendFunc::DISABLE) +{ + _type = RenderCommand::Type::TRIANGLES_COMMAND; +} + +void TrianglesCommand::init(float globalOrder, GLuint textureID, GLProgramState* glProgramState, BlendFunc blendType, const Triangles& triangles,const Mat4& mv) +{ + CCASSERT(glProgramState, "Invalid GLProgramState"); + CCASSERT(glProgramState->getVertexAttribsFlags() == 0, "No custom attributes are supported in QuadCommand"); + + _globalOrder = globalOrder; + + _triangles = triangles; + if(_triangles.indexCount % 3 != 0) + { + ssize_t count = _triangles.indexCount; + _triangles.indexCount = count / 3 * 3; + CCLOGERROR("Resize indexCount from %zd to %zd, size must be multiple times of 3", count, _triangles.indexCount); + } + _mv = mv; + + if( _textureID != textureID || _blendType.src != blendType.src || _blendType.dst != blendType.dst || _glProgramState != glProgramState) { + + _textureID = textureID; + _blendType = blendType; + _glProgramState = glProgramState; + + generateMaterialID(); + } +} + +TrianglesCommand::~TrianglesCommand() +{ +} + +void TrianglesCommand::generateMaterialID() +{ + + if(_glProgramState->getUniformCount() > 0) + { + _materialID = TrianglesCommand::MATERIAL_ID_DO_NOT_BATCH; + } + else + { + int glProgram = (int)_glProgramState->getGLProgram()->getProgram(); + int intArray[4] = { glProgram, (int)_textureID, (int)_blendType.src, (int)_blendType.dst}; + + _materialID = XXH32((const void*)intArray, sizeof(intArray), 0); + } +} + +void TrianglesCommand::useMaterial() const +{ + //Set texture + GL::bindTexture2D(_textureID); + + //set blend mode + GL::blendFunc(_blendType.src, _blendType.dst); + + _glProgramState->apply(_mv); +} + +QuadCommand::QuadCommand() +:TrianglesCommand() ,_quads(nullptr) ,_quadsCount(0) { @@ -53,6 +116,29 @@ void QuadCommand::init(float globalOrder, GLuint textureID, GLProgramState* glPr _quadsCount = quadCount; _quads = quad; + + //generate triangles + { + static std::vector QUADINDICESMAX; + if(QUADINDICESMAX.size() == 0) + { + QUADINDICESMAX.resize(Renderer::INDEX_VBO_SIZE); + for(ssize_t i = 0; i < Renderer::INDEX_VBO_SIZE / 6; ++i) + { + QUADINDICESMAX[ 6 * i + 0] = 4 * i + 0; + QUADINDICESMAX[ 6 * i + 1] = 4 * i + 1; + QUADINDICESMAX[ 6 * i + 2] = 4 * i + 2; + QUADINDICESMAX[ 6 * i + 3] = 4 * i + 3; + QUADINDICESMAX[ 6 * i + 4] = 4 * i + 2; + QUADINDICESMAX[ 6 * i + 5] = 4 * i + 1; + } + } + + _triangles.vertCount = quadCount * 4; + _triangles.indexCount = quadCount * 6; + _triangles.indices = &QUADINDICESMAX[0]; + _triangles.verts = &quad->tl; + } _mv = mv; @@ -70,31 +156,4 @@ QuadCommand::~QuadCommand() { } -void QuadCommand::generateMaterialID() -{ - - if(_glProgramState->getUniformCount() > 0) - { - _materialID = QuadCommand::MATERIAL_ID_DO_NOT_BATCH; - } - else - { - int glProgram = (int)_glProgramState->getGLProgram()->getProgram(); - int intArray[4] = { glProgram, (int)_textureID, (int)_blendType.src, (int)_blendType.dst}; - - _materialID = XXH32((const void*)intArray, sizeof(intArray), 0); - } -} - -void QuadCommand::useMaterial() const -{ - //Set texture - GL::bindTexture2D(_textureID); - - //set blend mode - GL::blendFunc(_blendType.src, _blendType.dst); - - _glProgramState->apply(_mv); -} - NS_CC_END diff --git a/cocos/renderer/CCQuadCommand.h b/cocos/renderer/CCQuadCommand.h index 5c731b784b..549df94c8c 100644 --- a/cocos/renderer/CCQuadCommand.h +++ b/cocos/renderer/CCQuadCommand.h @@ -30,13 +30,56 @@ #include "renderer/CCRenderCommandPool.h" NS_CC_BEGIN - -/** Command used to render one or more Quads */ -class CC_DLL QuadCommand : public RenderCommand +class CC_DLL TrianglesCommand : public RenderCommand { public: static const int MATERIAL_ID_DO_NOT_BATCH = 0; +public: + struct Triangles + { + V3F_C4B_T2F* verts; + unsigned short* indices; + ssize_t vertCount; + ssize_t indexCount; + }; + + TrianglesCommand(); + ~TrianglesCommand(); + + /** Initializes the command with a globalZOrder, a texture ID, a `GLProgram`, a blending function, a pointer to triangles, + * quantity of quads, and the Model View transform to be used for the quads */ + void init(float globalOrder, GLuint textureID, GLProgramState* glProgramState, BlendFunc blendType, const Triangles& triangles,const Mat4& mv); + + void useMaterial() const; + + inline uint32_t getMaterialID() const { return _materialID; } + inline GLuint getTextureID() const { return _textureID; } + inline const Triangles& getTriangles() const { return _triangles; } + inline ssize_t getVertexCount() const { return _triangles.vertCount; } + inline ssize_t getIndexCount() const { return _triangles.indexCount; } + inline const V3F_C4B_T2F* getVertices() const { return _triangles.verts; } + inline const unsigned short* getIndices() const { return _triangles.indices; } + inline GLProgramState* getGLProgramState() const { return _glProgramState; } + inline BlendFunc getBlendType() const { return _blendType; } + inline const Mat4& getModelView() const { return _mv; } + +protected: + void generateMaterialID(); + + uint32_t _materialID; + GLuint _textureID; + GLProgramState* _glProgramState; + BlendFunc _blendType; + Triangles _triangles; + Mat4 _mv; +}; + +/** Command used to render one or more Quads */ +class CC_DLL QuadCommand : public TrianglesCommand +{ +public: + QuadCommand(); ~QuadCommand(); @@ -45,26 +88,12 @@ public: void init(float globalOrder, GLuint texutreID, GLProgramState* shader, BlendFunc blendType, V3F_C4B_T2F_Quad* quads, ssize_t quadCount, const Mat4& mv); - void useMaterial() const; - - inline uint32_t getMaterialID() const { return _materialID; } - inline GLuint getTextureID() const { return _textureID; } - inline V3F_C4B_T2F_Quad* getQuads() const { return _quads; } + inline const V3F_C4B_T2F_Quad* getQuads() const { return _quads; } inline ssize_t getQuadCount() const { return _quadsCount; } - inline GLProgramState* getGLProgramState() const { return _glProgramState; } - inline BlendFunc getBlendType() const { return _blendType; } - inline const Mat4& getModelView() const { return _mv; } protected: - void generateMaterialID(); - - uint32_t _materialID; - GLuint _textureID; - GLProgramState* _glProgramState; - BlendFunc _blendType; V3F_C4B_T2F_Quad* _quads; ssize_t _quadsCount; - Mat4 _mv; }; NS_CC_END diff --git a/cocos/renderer/CCRenderCommand.h b/cocos/renderer/CCRenderCommand.h index 77332e01b0..882cc3518e 100644 --- a/cocos/renderer/CCRenderCommand.h +++ b/cocos/renderer/CCRenderCommand.h @@ -50,6 +50,7 @@ public: GROUP_COMMAND, MESH_COMMAND, PRIMITIVE_COMMAND, + TRIANGLES_COMMAND }; /** Get Render Command Id */ diff --git a/cocos/renderer/CCRenderer.cpp b/cocos/renderer/CCRenderer.cpp index a7509a1c1f..179013d11e 100644 --- a/cocos/renderer/CCRenderer.cpp +++ b/cocos/renderer/CCRenderer.cpp @@ -274,10 +274,10 @@ void Renderer::visitRenderQueue(const RenderQueue& queue) flush3D(); auto cmd = static_cast(command); //Batch quads - if( _filledVertex + cmd->getQuadCount() * 4 > VBO_SIZE || _filledIndex + cmd->getQuadCount() * 6 > INDEX_VBO_SIZE) + if( _filledVertex + cmd->getVertexCount() > VBO_SIZE || _filledIndex + cmd->getIndexCount() > INDEX_VBO_SIZE) { - CCASSERT(cmd->getQuadCount()>= 0 && cmd->getQuadCount() < VBO_SIZE, "VBO is not big enough for quad data, please break the quad data down or use customized render command"); - + CCASSERT(cmd->getVertexCount()>= 0 && cmd->getVertexCount() < VBO_SIZE, "VBO for vertex is not big enough, please break the data down or use customized render command"); + CCASSERT(cmd->getIndexCount()>= 0 && cmd->getIndexCount() < INDEX_VBO_SIZE, "VBO for index is not big enough, please break the data down or use customized render command"); //Draw batched quads if VBO is full drawBatchedQuads(); } @@ -383,29 +383,25 @@ void Renderer::clean() void Renderer::fillQuadVertices(const QuadCommand* cmd) { - memcpy(_verts + _filledVertex, cmd->getQuads(), sizeof(V3F_C4B_T2F) * cmd->getQuadCount() * 4); + memcpy(_verts + _filledVertex, cmd->getQuads(), sizeof(V3F_C4B_T2F) * cmd->getVertexCount()); const Mat4& modelView = cmd->getModelView(); - for(ssize_t i=0; i< cmd->getQuadCount() * 4; ++i) + for(ssize_t i=0; i< cmd->getVertexCount(); ++i) { V3F_C4B_T2F *q = &_verts[i + _filledVertex]; Vec3 *vec1 = (Vec3*)&q->vertices; modelView.transformPoint(vec1); } + const unsigned short* indices = cmd->getIndices(); //fill index - for(ssize_t i=0; i< cmd->getQuadCount(); ++i) + for(ssize_t i=0; i< cmd->getIndexCount(); ++i) { - _indices[_filledIndex + i * 6 + 0] = _filledVertex + i * 4 + 0; - _indices[_filledIndex + i * 6 + 1] = _filledVertex + i * 4 + 1; - _indices[_filledIndex + i * 6 + 2] = _filledVertex + i * 4 + 2; - _indices[_filledIndex + i * 6 + 3] = _filledVertex + i * 4 + 3; - _indices[_filledIndex + i * 6 + 4] = _filledVertex + i * 4 + 2; - _indices[_filledIndex + i * 6 + 5] = _filledVertex + i * 4 + 1; + _indices[_filledIndex + i] = _filledVertex + indices[i]; } - _filledVertex += cmd->getQuadCount() * 4; - _filledIndex += cmd->getQuadCount() * 6; + _filledVertex += cmd->getVertexCount(); + _filledIndex += cmd->getIndexCount(); } void Renderer::drawBatchedQuads() @@ -491,7 +487,7 @@ void Renderer::drawBatchedQuads() _lastMaterialID = newMaterialID; } - indexToDraw += cmd->getQuadCount() * 6; + indexToDraw += cmd->getIndexCount(); } //Draw any remaining quad