【问题标题】:opengl particle engine best practice?opengl粒子引擎最佳实践?
【发布时间】:2011-04-19 10:00:56
【问题描述】:

我正在开发一个简单的游戏,我目前正在从画布切换到 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);
    }
}

【问题讨论】:

    标签: android opengl-es particles


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

      见我的另一篇帖子here

      【讨论】:

      • 运行 gl.glDrawElements(GL10.GL_TRIANGLES, 3, GL10.GL_UNSIGNED_SHORT, mIndexBuffer) 真的是一个好方法吗?在每个粒子上?我只是想知道,因为我的测试表明这些调用中有太多非常昂贵(假设 1000 个粒子 + 应该绘制的所有其他内容......)还是?
      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-12-24
        • 2012-11-16
        • 2017-04-27
        • 1970-01-01
        • 2011-03-30
        • 2011-07-27
        • 1970-01-01
        • 2023-04-08
        相关资源
        最近更新 更多