i noticed that draw node does not use glDrawElements to draw polygons and it always uses glDrawArrays which is called in DrawNode::onDraw method
so the question is how to draw polygons using opengl Indexed VBO in cocos2d-x.
some talked about using cocos2d::Primitive but others said its dangeres and not good when it comes to performance?
another thing … is it possible to just overide DrawNode::onDraw and use glDrawElements instead … has any one tried it before?
because my attempts to do that failed when i wanted to try it on just draw solid rect?
here is how i tried to override:
// class CustomDrawNode : public cocos2d::DrawNode
void drawSolidRect(const Vec2 &origin, const Vec2 &destination, const Color4F &col1, const Color4F &col2, const Color4F &col3, const Color4F &col4) override
{
Vec2 vertices[] = {
origin,
Vec2(destination.x, origin.y),
destination,
Vec2(origin.x, destination.y)
};
int count = 4;
const Vec2 *verts = vertices;
bool outline = false;
auto triangle_count = outline ? (3 * count - 2) : (count - 2);
auto vertex_count = 3 * triangle_count;
ensureCapacity(vertex_count);
V2F_C4B_T2F_Triangle *triangles = (V2F_C4B_T2F_Triangle *)(_buffer + _bufferCount);
V2F_C4B_T2F_Triangle *cursor = triangles;
// rect of two triangles
*cursor++ = {
{ verts[0], Color4B(col1), __t(Vec2::ZERO) },
{ verts[1], Color4B(col2), __t(Vec2::ZERO) },
{ verts[2], Color4B(col3), __t(Vec2::ZERO) }
};
*cursor++ = {
{ verts[0], Color4B(col1), __t(Vec2::ZERO) },
{ verts[2], Color4B(col3), __t(Vec2::ZERO) },
{ verts[3], Color4B(col4), __t(Vec2::ZERO) }
};
_bufferCount += vertex_count;
_dirty = true;
}
void onDraw(const Mat4 &transform, uint32_t) override
{
getGLProgramState()->apply(transform);
GL::blendFunc(_blendFunc.src, _blendFunc.dst);
if (_dirty)
{
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)*_bufferCapacity, _buffer, GL_STREAM_DRAW);
_dirty = false;
}
if (Configuration::getInstance()->supportsShareableVAO())
{
GL::bindVAO(_vao);
}
else
{
GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
// vertex
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, vertices));
// color
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, colors));
// texcood
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, texCoords));
}
GLuint indices[] = {
0, 1, 2,
0, 2, 3
//0, 1, 2,
//2, 3, 0
};
// only draws one triangle
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, indices);
glBindBuffer(GL_ARRAY_BUFFER, 0);
if (Configuration::getInstance()->supportsShareableVAO())
{
GL::bindVAO(0);
}
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, _bufferCount);
CHECK_GL_ERROR_DEBUG();
}
for the sake of testing i am providing an indices array that will only work for rects and that’s fine by me because i just wanna test it only on rects first then move on from there.
PS: i prefer using draw node to accomplish this!