mirror of https://github.com/axmolengine/axmol.git
improvement for fast tmx rendering
This commit is contained in:
parent
a04b5fc5d5
commit
6292ed05be
|
@ -141,16 +141,11 @@ FastTMXLayer::~FastTMXLayer()
|
|||
}
|
||||
}
|
||||
|
||||
bool sortQuadCommand(const V3F_C4B_T2F_Quad& a, const V3F_C4B_T2F_Quad& b)
|
||||
{
|
||||
return a.bl.vertices.z < b.bl.vertices.z;
|
||||
}
|
||||
|
||||
void FastTMXLayer::draw(Renderer *renderer, const Mat4& transform, uint32_t flags)
|
||||
{
|
||||
updateTotalQuads();
|
||||
|
||||
if( flags != 0 || _dirty )
|
||||
if( flags != 0 || _dirty || _quadsDirty )
|
||||
{
|
||||
Size s = Director::getInstance()->getWinSize();
|
||||
auto rect = Rect(0, 0, s.width, s.height);
|
||||
|
@ -160,44 +155,47 @@ void FastTMXLayer::draw(Renderer *renderer, const Mat4& transform, uint32_t flag
|
|||
rect = RectApplyTransform(rect, inv);
|
||||
|
||||
_verticesToDraw = updateTiles(rect);
|
||||
updateIndexBuffer();
|
||||
// don't draw more than 65535 vertices since we are using GL_UNSIGNED_SHORT for indices
|
||||
_verticesToDraw = std::min(_verticesToDraw, 65535);
|
||||
_dirty = false;
|
||||
}
|
||||
|
||||
if(_renderCommands.size() < _quadsIndices.size())
|
||||
if(_renderCommands.size() < _indicesVertexZNumber.size())
|
||||
{
|
||||
_renderCommands.resize(_quadsIndices.size());
|
||||
_renderCommands.resize(_indicesVertexZNumber.size());
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
for(const auto& iter : _quadsIndices)
|
||||
for(const auto& iter : _indicesVertexZNumber)
|
||||
{
|
||||
auto& cmd = _renderCommands[index++];
|
||||
|
||||
cmd.init(iter.first);
|
||||
cmd.func = CC_CALLBACK_0(FastTMXLayer::onDraw, this, &iter.second);
|
||||
cmd.func = CC_CALLBACK_0(FastTMXLayer::onDraw, this, _indicesVertexZOffsets[iter.first], iter.second);
|
||||
renderer->addCommand(&cmd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void FastTMXLayer::onDraw(const std::vector<int> *indices)
|
||||
void FastTMXLayer::onDraw(int offset, int count)
|
||||
{
|
||||
GL::bindTexture2D(_texture->getName());
|
||||
getGLProgramState()->apply(_modelViewTransform);
|
||||
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0]);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]);
|
||||
|
||||
glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION);
|
||||
glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_COLOR);
|
||||
glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_TEX_COORD);
|
||||
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B_T2F), &_totalQuads[0]);
|
||||
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V3F_C4B_T2F), ((char*)&_totalQuads[0]) + offsetof(V3F_C4B_T2F, colors));
|
||||
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B_T2F), ((char*)&_totalQuads[0]) + offsetof(V3F_C4B_T2F, texCoords));
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)indices->size(), GL_UNSIGNED_INT, &(*indices)[0]);
|
||||
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B_T2F), (GLvoid*)0);
|
||||
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V3F_C4B_T2F), (GLvoid*)offsetof(V3F_C4B_T2F, colors));
|
||||
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B_T2F), (GLvoid*)offsetof(V3F_C4B_T2F, texCoords));
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)count * 6, GL_UNSIGNED_INT, (GLvoid*)(offset * 6));
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
int FastTMXLayer::updateTiles(const Rect& culledRect)
|
||||
|
@ -243,9 +241,12 @@ int FastTMXLayer::updateTiles(const Rect& culledRect)
|
|||
tilesOverY = ceil(overTileRect.origin.y + overTileRect.size.height) - floor(overTileRect.origin.y);
|
||||
}
|
||||
|
||||
_quadsIndices.clear();
|
||||
|
||||
//clear quadsNumber
|
||||
_indicesVertexZNumber.clear();
|
||||
|
||||
for(const auto& iter : _indicesVertexZOffsets)
|
||||
{
|
||||
_indicesVertexZNumber[iter.first] = iter.second;
|
||||
}
|
||||
|
||||
int tilesUsed = 0;
|
||||
for (int y = visibleTiles.origin.y - tilesOverY; y < visibleTiles.origin.y + visibleTiles.size.height + tilesOverY; ++y)
|
||||
|
@ -261,20 +262,19 @@ int FastTMXLayer::updateTiles(const Rect& culledRect)
|
|||
if(_tiles[tileIndex] == 0) continue;
|
||||
|
||||
int vertexZ = getVertexZForPos(Vec2(x,y));
|
||||
auto& indices = _quadsIndices[vertexZ];
|
||||
if(indices.capacity() == indices.size())
|
||||
{
|
||||
indices.reserve(indices.size() + 4096 * 6);
|
||||
}
|
||||
auto iter = _indicesVertexZNumber.find(vertexZ);
|
||||
int offset = iter->second;
|
||||
iter->second++;
|
||||
|
||||
CC_ASSERT(_tileToQuadIndex.find(tileIndex) != _tileToQuadIndex.end() && _tileToQuadIndex[tileIndex] <= _totalQuads.size()-1);
|
||||
//CC_ASSERT(_tileToQuadIndex.find(tileIndex) != _tileToQuadIndex.end() && _tileToQuadIndex[tileIndex] <= _totalQuads.size()-1);
|
||||
int quadIndex = (int)_tileToQuadIndex[tileIndex];
|
||||
indices.push_back(quadIndex * 4);
|
||||
indices.push_back(quadIndex * 4 + 1);
|
||||
indices.push_back(quadIndex * 4 + 2);
|
||||
indices.push_back(quadIndex * 4 + 3);
|
||||
indices.push_back(quadIndex * 4 + 2);
|
||||
indices.push_back(quadIndex * 4 + 1);
|
||||
|
||||
_indices[6 * offset + 0] = quadIndex * 4 + 0;
|
||||
_indices[6 * offset + 1] = quadIndex * 4 + 1;
|
||||
_indices[6 * offset + 2] = quadIndex * 4 + 2;
|
||||
_indices[6 * offset + 3] = quadIndex * 4 + 3;
|
||||
_indices[6 * offset + 4] = quadIndex * 4 + 2;
|
||||
_indices[6 * offset + 5] = quadIndex * 4 + 1;
|
||||
|
||||
if (tilesUsed >= MAX_QUADS_COUNT)
|
||||
{
|
||||
|
@ -287,7 +287,16 @@ int FastTMXLayer::updateTiles(const Rect& culledRect)
|
|||
break;
|
||||
}
|
||||
} // for y
|
||||
|
||||
|
||||
for(const auto& iter : _indicesVertexZOffsets)
|
||||
{
|
||||
_indicesVertexZNumber[iter.first] -= iter.second;
|
||||
if(_indicesVertexZNumber[iter.first] == 0)
|
||||
{
|
||||
_indicesVertexZNumber.erase(iter.first);
|
||||
}
|
||||
}
|
||||
|
||||
return tilesUsed * 6;
|
||||
}
|
||||
|
||||
|
@ -300,13 +309,20 @@ void FastTMXLayer::updateVertexBuffer()
|
|||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0]);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(V3F_C4B_T2F_Quad) * _quads.size(), (GLvoid*)&_quads[0], GL_STATIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(V3F_C4B_T2F_Quad) * _totalQuads.size(), (GLvoid*)&_totalQuads[0], GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
//void FastTMXLayer::updateIndexBuffer()
|
||||
//{
|
||||
//}
|
||||
void FastTMXLayer::updateIndexBuffer()
|
||||
{
|
||||
if(!glIsBuffer(_buffersVBO[1]))
|
||||
{
|
||||
glGenBuffers(1, &_buffersVBO[1]);
|
||||
}
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * _indices.size(), &_indices[0], GL_DYNAMIC_DRAW);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
//void FastTMXLayer::setupVBO()
|
||||
//{
|
||||
|
@ -421,6 +437,8 @@ void FastTMXLayer::updateTotalQuads()
|
|||
Size texSize = _tileSet->_imageSize;
|
||||
_tileToQuadIndex.clear();
|
||||
_totalQuads.resize(int(_layerSize.width * _layerSize.height));
|
||||
_indices.resize(6 * int(_layerSize.width * _layerSize.height));
|
||||
_indicesVertexZOffsets.clear();
|
||||
|
||||
int quadIndex = 0;
|
||||
for(int y = 0; y < _layerSize.height; ++y)
|
||||
|
@ -442,7 +460,15 @@ void FastTMXLayer::updateTotalQuads()
|
|||
float left, right, top, bottom, z;
|
||||
|
||||
z = getVertexZForPos(Vec2(x, y));
|
||||
|
||||
auto iter = _indicesVertexZOffsets.find(z);
|
||||
if(iter == _indicesVertexZOffsets.end())
|
||||
{
|
||||
_indicesVertexZOffsets[z] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->second++;
|
||||
}
|
||||
// vertices
|
||||
if (tileGID & kTMXTileDiagonalFlag)
|
||||
{
|
||||
|
@ -521,6 +547,12 @@ void FastTMXLayer::updateTotalQuads()
|
|||
}
|
||||
}
|
||||
|
||||
int offset = 0;
|
||||
for(auto iter = _indicesVertexZOffsets.begin(); iter != _indicesVertexZOffsets.end(); ++iter)
|
||||
{
|
||||
std::swap(offset, iter->second);
|
||||
offset += iter->second;
|
||||
}
|
||||
updateVertexBuffer();
|
||||
|
||||
_quadsDirty = false;
|
||||
|
|
|
@ -205,12 +205,12 @@ protected:
|
|||
//
|
||||
void updateTotalQuads();
|
||||
|
||||
void onDraw(const std::vector<int>* indices);
|
||||
void onDraw(int offset, int count);
|
||||
|
||||
inline int getTileIndexByPos(int x, int y) const { return x + y * (int) _layerSize.width; }
|
||||
|
||||
void updateVertexBuffer();
|
||||
//void updateIndexBuffer();
|
||||
void updateIndexBuffer();
|
||||
protected:
|
||||
|
||||
//! name of the layer
|
||||
|
@ -248,11 +248,11 @@ protected:
|
|||
Mat4 _tileToNodeTransform;
|
||||
/** quads to be rendered */
|
||||
bool _quadsDirty;
|
||||
std::map<ssize_t, ssize_t> _tileToQuadIndex;
|
||||
std::unordered_map<ssize_t, ssize_t> _tileToQuadIndex;
|
||||
std::vector<V3F_C4B_T2F_Quad> _totalQuads;
|
||||
std::map<int/*zorder*/, std::vector<int>> _quadsIndices;
|
||||
std::vector<V3F_C4B_T2F_Quad> _quads;
|
||||
std::map<int/*zorder*/, ssize_t/*number*/> _quadsNumber;
|
||||
std::vector<int> _indices;
|
||||
std::map<int/*vertexZ*/, int/*offset to _indices by quads*/> _indicesVertexZOffsets;
|
||||
std::unordered_map<int/*vertexZ*/, int/*number to quads*/> _indicesVertexZNumber;
|
||||
std::vector<CustomCommand> _renderCommands;
|
||||
bool _dirty;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue