void RenderingEngine::DrawImagesForTexture(simnode<Drawable>* from, simnode<Drawable>* to, int numSquares)
{
    if(from == to){
        return;
    }
    GLuint textureID = from->data->Texture()->Name;
    if(textureID != _currentTexture->Name){
        glBindTexture(GL_TEXTURE_2D, textureID);
        glEnableVertexAttribArray(_attributes.Position);
        glEnableVertexAttribArray(_attributes.TextureCoord);
        glEnableVertexAttribArray(_attributes.Color);
        glUniform1i(_uniforms.IsParticle, GL_FALSE);
        
        //glUniform1f(_uniforms.PointSize, 10.0f);
        //glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
        SetBlendFunc(_defaultSfactor, _defaultDfactor);
        //glBlendFunc(GL_SRC_ALPHA, GL_ONE);
        
        _currentTexture = from->data->Texture();
    }
    int numVertices = 6 * numSquares;
    int numVars = numVertices * 2;
 
    PointArrays* imageArrays = GetPointArraysByTextureID(_currentTexture->ID, numVars);

    int index = 0;
    bool hasColorChange = false;
    
    while (from != to) {
        Drawable* d = from->data;

//Image* img = static_cast<Image*>(d);
//cout << img->Name() << "|" << _currentTextureID << endl;
        
        if(!d->isOutOfScreen && d->IsVisible()){
            
            if(d->sfactor == 0 && d->dfactor == 0){
                if(_isDefaultChanged){
                    SetBlendFunc(_defaultSfactor, _defaultDfactor);
                    _isDefaultChanged = false;
                }
            }else if(_currentSfactor != d->sfactor || _currentDfactor != d->dfactor){
                _isDefaultChanged = true;
                SetBlendFunc(d->sfactor, d->dfactor);
            }
            
            if(d->IsColorChanged()) hasColorChange = true;
            
            index = d->FillArrays(imageArrays, 0, index);
        }
        from = from->next;
    }
    glUniform1i(_uniforms.HasColorChange, hasColorChange ? GL_TRUE : GL_FALSE);
    glVertexAttribPointer(_attributes.Position, 2, GL_FLOAT, GL_FALSE, 0, imageArrays->vertices);
    glVertexAttribPointer(_attributes.TextureCoord, 2, GL_FLOAT, GL_FALSE, 0, imageArrays->texCoord);
    glVertexAttribPointer(_attributes.Color, 4, GL_FLOAT, GL_TRUE, 0, imageArrays->colors);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices);
}
void RenderingEngine::Render()
{
    if(_isEnteredBackground) return;
    
    ++_frame;
    /*if(_isMultisamplingEnabled) glBindFramebuffer(GL_FRAMEBUFFER, _framebuffers.Msaa);
    else*/ glBindFramebuffer(GL_FRAMEBUFFER, _framebuffers.Resolve);
    //glViewport(0, 0, _screenSize.x, _screenSize.y);
    
    glClearColor(0, 251.0/255.0, 98.0/255.0, 82.0/255.0);
    glClear(GL_COLOR_BUFFER_BIT/*| GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT*/);

    
    
    
    // erase expired check each 4 frames
    
    if(_factory->forceClearExpired ||  _frame % 10 == 0){
        _factory->forceClearExpired = false;
        ClearExpired();
    }
    
    // proces non expired
    GLuint lastTextureID = 0;
    int lastTextureGroup = 0;
    int numSquares = 0;
    
    simnode<Drawable>* curr = _drawables->head;
    simnode<Drawable>* from = curr;
    while (curr != NULL) {
        Drawable* d = curr->data;
        if(d->isOutOfScreen || !d->IsVisible()){
            curr = curr->next;
            continue;
        }
        GLuint texID = d->Texture()->Name;
        int texGroup = d->textureGroup;
        if(lastTextureID != 0 && (lastTextureID != texID || texGroup != lastTextureGroup)){
            DrawImagesForTexture(from, curr, numSquares);
            from = curr;
            numSquares = 0;
        }
        numSquares += d->NumberSquares();
        lastTextureID = texID;
        lastTextureGroup = texGroup;
        curr = curr->next;
    }
    DrawImagesForTexture(from, NULL, numSquares);
    
    if(!_factory->isPaused){
        DrawTouchTrail();
        DrawMapDots();
    }
    
//    if(_isMultisamplingEnabled){
//        //glDisable(GL_SCISSOR_TEST);
//        
//        glBindFramebuffer(GL_DRAW_FRAMEBUFFER_APPLE, _framebuffers.Resolve);
//        glBindFramebuffer(GL_READ_FRAMEBUFFER_APPLE, _framebuffers.Msaa);
//        glResolveMultisampleFramebufferAPPLE(); 
//    }
    
    const GLenum discards[]  = { GL_COLOR_ATTACHMENT0 };
    glDiscardFramebufferEXT(GL_READ_FRAMEBUFFER_APPLE, 1, discards);
    
    glBindRenderbuffer(GL_RENDERBUFFER, _renderbuffers.ResolveColor);
}