opengl粒子引擎最佳实践?

时间:2011-04-19 10:00:57

标签: android opengl-es particles

我正在开发一个简单的游戏,我目前正在从canvas切换到openGL。所以我的openGL经验非常有限。 我正在尝试创建一个简单的粒子引擎,它工作正常但是我当前的实现我必须在每个draw()调用[vertexBuffer.put(vertices); ]这真的很慢..有没有办法解决这个问题?

代码如下所示:

public class ParticlesTest {

    private float[] vertices;
    private short[] indices;


    private FloatBuffer vertexBuffer;


    private ShortBuffer indexBuffer;
    private ByteBuffer vbb;

    private int MAX_PARTICLES = 100;

    private ArrayList<Particle> particles;
    public ParticlesTest() {

        particles = new ArrayList<Particle>();

        vertices = new float[MAX_PARTICLES*6*3];
        indices = new short[MAX_PARTICLES*2];


        short cnt = 0;
        for(int i = 0; i < 60; i++){
            createParticle();

            indices[cnt] =  cnt;
            cnt++;
            indices[cnt] =  cnt;
            cnt++;

        }

        vbb = ByteBuffer.allocateDirect(vertices.length * 4);
        vbb.order(ByteOrder.nativeOrder());
        vertexBuffer = vbb.asFloatBuffer();
        vertexBuffer.put(vertices);
        vertexBuffer.position(0);

        ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
        ibb.order(ByteOrder.nativeOrder());
        indexBuffer = ibb.asShortBuffer();
        indexBuffer.put(indices);
        indexBuffer.position(0);



    }

    private void createParticle() {
        Particle particle = new Particle();
        particle.setSpeedX((float)(Math.random() * 20 - 10));
        particle.setSpeedY((float)(Math.random() * 20 - 10));
        particle.setX(100);
        particle.setY(100);

        particles.add(particle);


    }
    private void update(){

        int len = particles.size();

        for(int i = 0; i < len; i++){
            Particle particle = particles.get(i);

            float oldX = particle.getX();
            float oldY = particle.getY();
            float speedX = particle.getSpeedX();
            float speedY = particle.getSpeedY();

            oldX += speedX;
            oldY += speedY;

            particle.setX(oldX);
            particle.setY(oldY);

            if(oldX < 0 || oldX > 400 || oldY < 0 || oldY > 600){
                particles.remove(i);
                len--;
            }
        }

        if(len < MAX_PARTICLES){
            createParticle();
        }
    }


    private void translate(){


        int vcount = 0;
        short icount = 0;

        int clen = vertices.length;

        for(int c = 0; c < clen; c++){
            vertices[c] = 0f;
        }


        int len = particles.size();

        for(int i = 0; i < len; i++){
            Particle particle = particles.get(i);

            float oldX = particle.getX();
            float oldY = particle.getY();

            float speedX = particle.getSpeedX();
            float speedY = particle.getSpeedY();

            vertices[vcount] =oldX;
            vcount++;
            vertices[vcount] = oldY;
            vcount++;
            vertices[vcount] = 0f;
            vcount++;

            vertices[vcount] =oldX + speedX;
            vcount++;
            vertices[vcount] = oldY + speedY;
            vcount++;
            vertices[vcount] = 0f;
            vcount++;

            indices[icount] = icount;
            icount++;
            indices[icount] = icount;
            icount++;

        }
    }


    public void draw(GL10 gl,int w,int h) {

        update();
        translate();

        vertexBuffer.put(vertices);

        vertexBuffer.position(0);

        //GLFPS.VERTS = vertices.length;


        // rendering.
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);      
//      gl.glDrawElements(GL10.GL_LINE_STRIP, indices.length, GL10.GL_UNSIGNED_SHORT, indexBuffer);
        gl.glDrawElements(GL10.GL_LINES, indices.length, GL10.GL_UNSIGNED_SHORT, indexBuffer);



        // Disable the vertices buffer.
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    }
}

3 个答案:

答案 0 :(得分:1)

作为建议,创建如此大量对象的ArrayList可以创建大量的内存开销。另外,您是否考虑过使用GL ES 2.0而不是1?这样你就可以使用GLSL创建一个粒子着色器程序,这将允许你释放内存并在GPU上进行计算而不是CPU。那应该大大提高性能。

答案 1 :(得分:0)

  

有没有办法解决这个问题?

预先分配所有对象,并在游戏运行时继续重复使用。

请参阅我的其他帖子here

答案 2 :(得分:0)

好的,我现在找到了一个非常好的方法(我认为)。我没有使用浮点数的顶点缓冲区,而是使用了短脚本顶点缓冲区。现在我用23fps在星系S上运行15k粒子。