代码之家  ›  专栏  ›  技术社区  ›  Lope

高效的sprite渲染opengl es 2.0

  •  1
  • Lope  · 技术社区  · 15 年前

    我正在开发一个ipad应用程序,它可以在每一帧上渲染数百个精灵(2d图像)。我使用修改后的绘图方法取自sdk的opengl模板,但问题是,我只有3fps,我甚至没有渲染我需要的一切。

    我尝试了一些简单的优化方法,比如使用纹理图集,最小化状态变化的数量,高级剪辑,甚至渲染按常用属性排序的精灵,比如使用的颜色或纹理,但似乎没有多大帮助。我不能使用pvr压缩,因为我的图像有很好的边缘和alpha通道,压缩时看起来很糟糕(我只在少数背景图像上使用它)。

    下面是我的渲染函数:

    - (void)RenderTexture:(GLTexture*)tex InRect:(CGRect)dest WithUV:(CGRect)uv Color:(LSColor*)color Effect:(SpriteEffect)effect Rotation:(float)rot AroundPoint:(CGPoint)rotCenter {
     if(tex.ID != mLastBoundTexture) {
       [tex bind];
       mLastBoundTexture = tex.ID;
     }
    
     mSquareVertices[2] = mSquareVertices[6] = dest.size.width;
     mSquareVertices[5] = mSquareVertices[7] = dest.size.height;
    
     mSquareUVs[0] = mSquareUVs[4] = uv.origin.x;
     mSquareUVs[1] = mSquareUVs[3] = uv.origin.y;
     mSquareUVs[2] = mSquareUVs[6] = uv.origin.x + uv.size.width;
     mSquareUVs[5] = mSquareUVs[7] = uv.origin.y + uv.size.height;
    
     mSquareColors[0] = mSquareColors[4] = mSquareColors[8] = mSquareColors[12] = color.red;
     mSquareColors[1] = mSquareColors[5] = mSquareColors[9] = mSquareColors[13] = color.green;
     mSquareColors[2] = mSquareColors[6] = mSquareColors[10] = mSquareColors[14] = color.blue;
     mSquareColors[3] = mSquareColors[7] = mSquareColors[11] = mSquareColors[15] = color.alpha;
    
     mat4f_LoadTranslation2f(rotCenter.x, rotCenter.y, mModelViewMatrix);
    
     mat4f_LoadTranslation2f(dest.origin.x, dest.origin.y, mModelViewMatrix);
     mat4f_MultiplyMat4f(mProjectionMatrix, mModelViewMatrix, mModelViewProjMatrix);
    
     if(mLastUsedShader != effect) {
       int program;
       if(effect == SENormal) {
         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
         program = mShaderNormal;
       }
       else if(effect == SEMultiply) {
         glBlendFunc(GL_DST_COLOR, GL_ZERO);
         program = mShaderMultiply;
       }  
     else {
       NSLog(@"Implement SpriteEffect %i", effect);
     }
    
     glUseProgram(program);
     mLastUsedShader = effect;
     } 
     glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEW_PROJECTION_MATRIX], 1, GL_FALSE, mModelViewProjMatrix);
    
     // Update attribute values
     glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, mSquareVertices);
     glVertexAttribPointer(ATTRIB_UV, 2, GL_FLOAT, 0, 0, mSquareUVs);
     glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, 1, 0, mSquareColors);
    
     glUniform4fv(uniforms[UNIFORM_POSTPROCES_PARAMS], 4, mPostprocessParams);
    
     // Draw
     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
     }
    

    你看到我可以提高帧率的其他地方了吗?我真的需要至少30帧

    编辑:原来我有太复杂的片段着色器。我觉得自己很愚蠢,因为我没有禁用它来测试它。看来我得跟我的去饱和功能说再见了。使用默认的片段着色器,我可以轻松地获得超过60帧/秒。

    3 回复  |  直到 15 年前
        1
  •  2
  •   Bahbar    15 年前

    我的直觉是你只是在满足利率限制。

    另一种选择是,你是着色器绑定。你的碎片着色器是做什么的?如果将其替换为简单的恒定颜色输出,会发生什么情况?

    归根结底,要查看性能,您需要使用性能分析工具。我不把自己和ipad做对比。SDK是否提供了分析性能的工具?

        2
  •  3
  •   Mario Zechner    15 年前

    你没有满足率限制(你可能是,但有一个更大的问题)。你说你有2000个精灵。对于每个单独设置顶点/片段着色器的对象,计算每个精灵的投影和其他矩阵,并且每次渲染调用仅渲染单个精灵。这样,无论您实际使用的是纹理/复杂着色器还是纯平面着色,都无法渲染相当数量的精灵。

    我应该提到的最后一件事是:您必须自己在CPU上进行转换,而不是为每个sprite设置一个新的矩阵,让CPU来完成这项工作。

    http://code.google.com/p/libgdx/source/browse/trunk/gdx/src/com/badlogic/gdx/graphics/SpriteBatch.java

    嗯,

        3
  •  0
  •   Dr. Snoopy    15 年前

    您可能希望查看点精灵以加速渲染。