2015-04-13 3 views
0

В основном, что я делаю, это простой инструмент для рисования пальцев. У меня есть один класс, который принимает входные точки касания и делает всю забавную работу по превращению этих точек касания в кривые Безье, вычисление вершин из них и т. Д. Это все работает нормально.Откат кадров при рисовании нескольких текстур в OpenGL ES iOS

Единственное интересное ограничение, с которым я работаю, это то, что мне нужны штрихи, чтобы накладываться друг на друга, но не с собой. Представьте, что у вас есть строчная строка, которая пересекает себя и имеет 50% непрозрачность. Там, где линия пересекает себя, не должно быть видимого смешения (все они должны быть одного цвета). Тем не менее, линия СЛЕДУЕТ смешиваться с остальной частью рисунка ниже.

Для этого я использую две текстуры. Обратная текстура и текстура царапины. В то время как линия активно обновляется (во время хода), я отключу смешение, нарисую вершины на текстуре царапины, затем включит смешение и нарисую текстуру обратной связи и текстуру царапины в свой буфер кадров. Когда штрих закончен, я рисую текстуру царапины в текстуру назад, и мы готовы начать следующий удар.

Все это работает очень плавно на более новом устройстве, но на более старых устройствах частота кадров резко падает. Из некоторых тестов кажется, что наибольший успех в производительности заключается в рисовании текстур в буфере кадров, потому что они относительно большие текстуры (из-за разрешения сетчатки iPhone). Есть ли у кого-нибудь какие-либо намеки на некоторые стратегии, чтобы обойти это? Я рад предоставить более подробную информацию или код, я просто не знаю, с чего начать.

Я использую OpenGL ES 2.0, нацеливание IOS 7.0, но тестирование на iPhone 4S

Ниже приведен код, я использую, чтобы рисовать в фреймбуферов:

- (void)drawRect:(CGRect)rect 
{ 
    [self drawRect:rect 
     ofTexture:_backTex 
     withOpacity:1.0]; 

    if (_activeSpriteStroke) 
    { 
     [self drawStroke:_activeSpriteStroke 
     intoFrameBuffer:0]; 
    } 
} 

Те полагаются на следующие несколько методов:

- (void)drawRect:(CGRect)rect 
     ofTexture:(GLuint)tex 
    withOpacity:(CGFloat)opacity 
{ 
    _texShader.color = GLKVector4Make(1.0, 1.0, 1.0, opacity); 

    [_texShader prepareToDraw]; 

    glBindTexture(GL_TEXTURE_2D, tex); 
    glBindVertexArrayOES(_texVertexVAO); 
    glBindBuffer(GL_ARRAY_BUFFER, _texVertexVBO); 

    [self bufferTexCoordsForRect:rect]; 

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 

    glBindVertexArrayOES(0); 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 
    glBindTexture(GL_TEXTURE_2D, tex); 
} 

- (void)drawStroke:(AHSpriteStroke *)stroke 
    intoFrameBuffer:(GLuint)frameBuffer 
{ 
    glEnable(GL_BLEND); 
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 

    [self renderStroke:stroke 
      ontoTexture:_scratchTex 
     inFrameBuffer:_scratchFrameBuffer]; 

    if (frameBuffer == 0) 
    { 
     [self bindDrawable]; 
    } 
    else 
    { 
     glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer); 
    } 

    [self setScissorRect:_activeSpriteStroke.boundingRect]; 
    glEnable(GL_SCISSOR_TEST); 

    [self drawRect:self.bounds 
     ofTexture:_scratchTex 
     withOpacity:stroke.lineOpacity]; 

    glDisable(GL_SCISSOR_TEST); 

    glDisable(GL_BLEND); 
} 

- (void)renderStroke:(AHSpriteStroke *)stroke 
     ontoTexture:(GLuint)tex 
     inFrameBuffer:(GLuint)framebuffer 
{ 
    glBindFramebuffer(GL_FRAMEBUFFER, _msFrameBuffer); 
    glBindTexture(GL_TEXTURE_2D, tex); 

    glClearColor(0.0, 0.0, 0.0, 0.0); 
    glClear(GL_COLOR_BUFFER_BIT); 

    [stroke render]; 

    glBindFramebuffer(GL_DRAW_FRAMEBUFFER_APPLE, framebuffer); 
    glBindFramebuffer(GL_READ_FRAMEBUFFER_APPLE, _msFrameBuffer); 
    glResolveMultisampleFramebufferAPPLE(); 

    const GLenum discards[] = { GL_COLOR_ATTACHMENT0 }; 
    glDiscardFramebufferEXT(GL_READ_FRAMEBUFFER_APPLE, 1, discards); 

    glBindTexture(GL_TEXTURE_2D, 0); 
    glBindFramebuffer(GL_FRAMEBUFFER, 0); 
} 

и пару вспомогательных методов только для полноты, так что вы можете следовать за ним:

+0

> «и нарисуйте текстуру обратной связи и текстуру царапины в буфер кадра» ... как именно вы делаете эту часть? – gbuzogany

+0

Я добавил немного кода выше, чтобы дать еще несколько примеров того, как я рисую эти фреймбуферы. Не стесняйтесь смотреть, и дайте мне знать, что вы думаете или у вас есть какие-либо вопросы! Любая помощь будет принята с благодарностью! – Herm

ответ

0

Из того, что, как я понимаю, вы рисуете каждый квад в отдельном призыве рисования. Если ваш удар состоит из большого количества квадов (от выборки кривой безье), ваш код будет делать много вызовов рисования за кадр.

Имея много вызовов вызова в OpenGL ES 2 на более старых устройствах iOS, вероятно, будет генерировать горло бутылки на процессоре. Причина в том, что призыв к обращению в OpenGL ES 2 может иметь много накладных расходов в драйвере. Драйвер пытается организовать обратные призывы, которые вы делаете во что-то, что может переварить GPU, и он использует эту организацию с использованием CPU.

Если вы намереваетесь нарисовать много квадов, чтобы имитировать ход кисти, вы должны обновить буфер вершин, чтобы содержать много квадов, а затем нарисовать его одним призывом к призыву, вместо того, чтобы сделать призыв на призы на квад.

Вы можете проверить, что ваша горло бутылки находится в CPU с прибором Time Profiler. Затем вы можете проверить, проводит ли центральный процессор большую часть времени на методах вызова OpenGL или, скорее, на ваши собственные функции.

Если процессор затрачивает большую часть времени на методы вызова вызова OpenGL, это, скорее всего, потому, что вы делаете слишком много обратных вызовов на кадр.

+0

Спасибо за вдумчивый ответ, но это не совсем то, что происходит. Ни один из приведенных выше кодов не показывает какой-либо из фактического кода чертежа, который принимает входные точки касания и превращает его в кривые Безье, а затем вершины из кривых Безье. Я довольно хорошо тестировал весь этот код с помощью инструмента таймера и инструмента OpenGL, и это, похоже, не является узким местом. Узкое место, безусловно, где-то в текстурировании. – Herm

+0

"Текстурирование"? Вы имеете в виду визуализацию? Если ваш рендеринг ниже целевого FPS, анализатор кадров OpenGL xcode обычно скажет вам, что такое ваша шея бутылки. Попытайтесь захватить снимок OpenGL, пока вы проведите пальцем по экрану и посмотрите, не указали ли вы под прицелом? – user1097185

+0

Вы знаете, что вы можете увидеть, сколько CPU/GPU вы используете (даже сколько вы используете), нажав на FPS-метр? – user1097185

Смежные вопросы