繁体   English   中英

在OpenGL ES iOS中绘制多个纹理时帧速率下降

[英]Framerate dropping when drawing multiple textures in OpenGL ES iOS

基本上,我正在做的是制作一个简单的手指绘制应用程序。 我有一个单一的类,它接受输入的接触点,并完成将这些接触点转换为贝塞尔曲线,从这些接触点计算顶点等所有有趣的工作。一切都很好。

我正在使用的唯一有趣的约束条件是,我需要笔触在彼此之上进行融合,但不能彼此融合。 想象一下,有一条划线横穿自己并具有50%的不透明度。 线相交的地方应该没有可见的混合(看起来应该都是相同的颜色)。 但是,该线应与它下面的其余图形融合。

为此,我使用了两个纹理。 背部纹理和划痕纹理。 在动态更新线条时(在笔画过程中),我禁用混合,在暂存纹理上绘制顶点,然后启用混合,并将后部纹理和暂存纹理绘制到我的帧缓冲区中。 笔划完成后,我将划痕纹理绘制到背面纹理中,我们准备开始下一个笔划。

在较新的设备上,这一切都非常顺利,但是在较旧的设备上,帧频会受到严重影响。 从一些测试来看,似乎最大的性能影响在于将纹理绘制到帧缓冲区,因为它们是相对较大的纹理(由于iPhone的视网膜分辨率)。 有人对解决此问题的策略有任何暗示吗? 我很乐意提供更多细节或代码,只是不确定从哪里开始。

我正在使用面向iOS 7.0的OpenGL ES 2.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);
}

还有一些辅助方法只是为了保持完整性,因此您可以按照以下说明进行操作:

- (void)bufferTexCoordsForRect:(CGRect)rect
{
    AHTextureMap textureMaps[4] =
    {
        [self textureMapForPoint:CGPointMake(CGRectGetMinX(rect), CGRectGetMinY(rect))
                          inRect:self.bounds],
        [self textureMapForPoint:CGPointMake(CGRectGetMaxX(rect), CGRectGetMinY(rect))
                          inRect:self.bounds],
        [self textureMapForPoint:CGPointMake(CGRectGetMinX(rect), CGRectGetMaxY(rect))
                          inRect:self.bounds],
        [self textureMapForPoint:CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(rect))
                          inRect:self.bounds]
    };

    glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(AHTextureMap), textureMaps, GL_DYNAMIC_DRAW);
}

- (AHTextureMap)textureMapForPoint:(CGPoint)point
                            inRect:(CGRect)outerRect
{
    CGPoint pt = CGPointApplyAffineTransform(point, CGAffineTransformMakeScale(self.contentScaleFactor, self.contentScaleFactor));

    return (AHTextureMap) { { pt.x, pt.y }, { point.x / outerRect.size.width, 1.0 - (point.y / outerRect.size.height) } };
}

据我了解,您是在单独的绘制调用中绘制每个四边形。 如果笔划包含很多四边形(对贝塞尔曲线进行采样),则您的代码将每帧进行多次绘制调用。

在较旧的iOS设备上的OpenGL ES 2中进行多次绘制调用可能会在CPU上产生瓶颈。 原因是OpenGL ES 2中的绘图调用可能会在驱动程序中产生大量开销。 驱动程序尝试将您进行的绘图调用组织成GPU可以消化的内容,并使用CPU进行这种组织。

如果打算绘制多个四边形以模拟笔刷笔触,则应更新一个顶点缓冲区以包含多个四边形,然后使用一个绘制调用对其进行绘制,而不是每个四边形进行绘制调用。

您可以使用Time Profiler仪器验证瓶颈在CPU中。 然后,您可以检查CPU是否将大部分时间都花在了OpenGL draw调用方法上,或者是在您自己的函数上。

如果CPU将大部分时间都花在OpenGL绘图调用方法上,则可能是因为每帧进行的绘图调用过多。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM