2012-05-29 53 views
9

我想用OpenGL ES 2.0在Android上批量绘制一堆线,我需要知道最好的方法来做到这一点。Android上的OpenGL ES 2.0中的快速动态顶点

现在我创建了一个名为LineEngine的类,它建立了一个FloatBuffer,用于绘制所有的顶点,然后一次绘制所有的线。问题在于,显然FloatBuffer.put()非常慢,并且像疯了似的吞噬CPU时间。

这里是我的类

public class LineEngine { 
    private static final float[] IDENTIY = new float[16]; 
    private FloatBuffer mLinePoints; 
    private FloatBuffer mLineColors; 
    private int mCount; 

    public LineEngine(int maxLines) { 
     Matrix.setIdentityM(IDENTIY, 0); 

     ByteBuffer byteBuf = ByteBuffer.allocateDirect(maxLines * 2 * 4 * 4); 
     byteBuf.order(ByteOrder.nativeOrder()); 
     mLinePoints = byteBuf.asFloatBuffer(); 

     byteBuf = ByteBuffer.allocateDirect(maxLines * 2 * 4 * 4); 
     byteBuf.order(ByteOrder.nativeOrder()); 
     mLineColors = byteBuf.asFloatBuffer(); 

     reset(); 
    } 

    public void addLine(float[] position, float[] color){ 
     mLinePoints.put(position, 0, 8); //These lines 
     mLineColors.put(color, 0, 4); // are taking 
     mLineColors.put(color, 0, 4); // the longest! 
     mCount++; 
    } 

    public void reset(){ 
     mLinePoints.position(0); 
     mLineColors.position(0); 
     mCount = 0; 
    } 

    public void draw(){ 
     mLinePoints.position(0); 
     mLineColors.position(0); 
     GraphicsEngine.setMMatrix(IDENTIY); 
     GraphicsEngine.setColors(mLineColors); 
     GraphicsEngine.setVertices4d(mLinePoints); 
     GraphicsEngine.disableTexture(); 
     GLES20.glDrawArrays(GLES20.GL_LINES, 0, mCount * 2); 
     GraphicsEngine.disableColors(); 
     reset(); 
    } 
} 

有批量所有这些线一起更好的办法?

+0

哪个android版本是设备运行? [有关FloatBuffer的问题](http://www.badlogicgames.com/wordpress/?p=899)。 GLES20要求API等级8,所以它至少是Froyo。你可以在运行Honeycomb的设备上测试吗? –

+0

我在Galaxy Nexus的ICS上运行它。我会仔细检查它确实需要很长时间。 – EmbMicro

+0

我刚刚测试了批量生产线,未在我的Galaxy Nexus和EVO 4G上进行批量生产。 EVO将FPS从28.8提高到30,Galaxy Nexus保持在58.4。然而,在方法分析器中,它显示绘图函数(包括FloatBuffer.put和实际的OpenGL绘图调用)占用了更多时间。它从CPU时间的31.5%降至53.1%。这只是探查器搞乱了事情吗? – EmbMicro

回答

1

你要做的就是所谓的SpriteBatching。如果你想让你的程序在openGL es中稳健运行,你必须检查以下内容(一个让程序变慢的列表):

- 改变许多opengl ES状态。

-Enable // Dissable(纹理等)一次又一次。一旦你启用了一些你不需要再做的事情,它就会自动应用它的框架。

- 使用许多资产,而不是spriteSheets。是的,这会对性能产生巨大的影响。例如,如果您有10个图像,则必须为每个图像加载不同的纹理,即SLOW。更好的方法是创建一个spriteSheet(你可以检查谷歌免费的spriteSheet创建者)。

- 您的图像质量很高。是!检查你的分辨率和文件扩展名。首选.png文件。

- 支持api 8浮点缓冲区错误(您必须使用int缓冲区来修复该错误)。

- 使用java容器。如果你使用字符串连接(这不是一个容器,但它每次都会返回一个新字符串),或者是一个List或任何其他容器,这是最大的陷阱,因为垃圾回收会导致程序运行缓慢。对于输入处理,我建议你搜索一个名为池类的teqnique。它的用途是回收对象而不是创建新对象。垃圾收集器是大敌,试图让他高兴,并避免任何可能称他的编程技术。

- 在运行中不加载事物,而是创建加载器类并在应用程序的开始加载所有必需的资源。

如果你确实实现了这个列表,那么你的机会将会很强大。

最后一次加入。什么是精灵分配器? spriteBatcher是一个使用单个纹理渲染多个对象的类。它会自动创建顶点,索引,颜色,U - V坐标,并将它们作为一个批处理。这种模式将节省GPU功耗以及CPU功耗。从你的发布代码,我不能确定是什么导致CPU减速,但从我的经验是由于我以前提到的列表中的一个(或更多)的东西。检查列表,按照它搜索谷歌spriteBatching,我相信你的程序将运行得很快。希望我帮助!

编辑:我想我找到了什么原因导致你的程序减速,你不要翻转缓冲区!你只需重置位置。您只需添加添加更多对象,并导致缓冲区过载。在重置方法中,只需翻转缓冲区。 mLineColors.flip mLinePaints.flip将完成这项工作。如果每个帧都发送新的版本,请确保每帧都称为它们。

+0

我早就停止了这段代码的工作,但你的回答有很多很好的信息,如果翻转缓冲区有了很大的改进,我也不会感到惊讶。由于旧点将被覆盖,不会有溢出吗?或者缓冲区不能以这种方式工作? – EmbMicro

+0

嘿,抱歉,我花了很长时间才回答我离开了。所以,第一件事情首先是圣诞快乐!现在你的问题,一个缓冲区是一个临时存储大量信息的数组,它需要被处理,而不是逐个处理相同的信息直到结束。当你翻转一个缓冲区时,它会自动调整大小,所以你不必担心重载它(除非你提供了一个非常大的尺寸)。重载意味着如果缓冲区有10个int的容量,只要你不给11就可以了。如果你给11,那么你将有一个缓冲区溢出。 – KostasRim

+0

覆盖内存位置不会超载。只记得你改变了内存的价值,你不要求你的程序保留相同的内存加上新的点。你只是渲染当前帧点(旧点不再存在!)。希望我帮助,祝新年快乐:)! – KostasRim

0

FloatBuffer.put(float [])具有相对较大的float数组应该快得多。单次put(float)调用有很多开销。

0

只要去一个非常简单的本地函数,它将从你的类中调用。您可以直接将float[]添加到OpenGL中,无需使用愚蠢的缓冲区界面来杀死CPU时间。