使用六边形网格提高绘图性能

时间:2011-06-06 08:51:09

标签: android opengl-es hexagonal-tiles

我正在开发我的第一款openGL游戏,受到PlayStation网络游戏“Greed Corp”的启发。这是一款基于回合制的策略游戏,基于十六进制网格。每个六边形瓷砖都有自己的高度和纹理。

我正在根据我读过的一些示例和教程绘制六边形。这是我的六分类:

public class HexTile
{
    private float height;

    private int[] textures = new int[1];

    private float vertices[] = {     0.0f,   0.0f, 0.0f,    //center
                                     0.0f,   1.0f, 0.0f,    // top
                                    -1.0f,   0.5f, 0.0f,    // left top
                                    -1.0f,  -0.5f, 0.0f,    // left bottom
                                     0.0f,  -1.0f, 0.0f,    // bottom
                                     1.0f,  -0.5f, 0.0f,    // right bottom
                                     1.0f,  0.5f, 0.0f,     // right top
    };

    private short[] indices = {      0, 1, 2, 3, 4, 5, 6, 1};

    //private float texture[] = { };

    private FloatBuffer vertexBuffer;
    private ShortBuffer indexBuffer;
    //private FloatBuffer textureBuffer;    

    public HexTile()
    {
        ByteBuffer 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);

        /*ByteBuffer tbb = ByteBuffer.allocateDirect(texture.length * 4);
        tbb.order(ByteOrder.nativeOrder());
        textureBuffer = tbb.asFloatBuffer();
        textureBuffer.put(texture);
        textureBuffer.position(0);*/
    }

    public void setHeight(float h)
    {
        height = h;
    }
    public float getHeight()
    {
        return height;
    }

    public void draw(GL10 gl)
    {
        gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);

        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
        //gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);

        gl.glDrawElements(GL10.GL_TRIANGLE_FAN, indices.length, GL10.GL_UNSIGNED_SHORT, indexBuffer);
    }

    public void loadGLTexture(GL10 gl, Context context)
    {
        textures[0] = -1;
        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.hex);

        while(textures[0] <= 0)
            gl.glGenTextures(1, textures, 0); 

        gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);

        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

        bitmap.recycle();
    }
}

我正在循环遍历所有可见的瓷砖以绘制它们,即11 * 9个瓷砖MAX。然而,这会将我的帧速率降低到38,甚至没有在它们上绘制纹理,只有平坦的六边形。

现在我正试图弄清楚如何提高性能。我认为一次绘制整个网格可能会更快,但我不知道如何做到这一点,因为每个瓷砖可以有不同的高度,并且很可能具有与相邻瓷砖不同的纹理。

我真的很感激这方面的一些帮助,因为我想开始实际游戏^。^

2 个答案:

答案 0 :(得分:1)

假设您的六边形网格是静态的,您可以旋转所有六边形一次,生成它们的几何体,并将所有内容附加到一个(或更多,如果您有超过2 ^ 16个顶点)可以在一个中绘制的大VBO去。

就纹理而言,您可以使用texture atlas

答案 1 :(得分:0)

我目前正在学习OpenGL,我已经制作了一个名为“Cloud Stream&#39;”的Android OpenGL应用程序。在那里我发现了类似的性能问题。

作为对性能问题的一般回答,有一些方面可以提供帮助。在一次传递大量顶点时,硬件级别的Graphics的Vertex管道显然更有效。为每个Hex tile调用glVertexPointer不如使用所有tile的顶点调用它一样有效。

这会使代码变得更难,因为你实际上一次性绘制了所有的图块,但它似乎确实加快了速度。在我的应用程序中,所有的云都是在一次调用中绘制的。

尝试的其他途径是将Vertice位置保存在VBO中,我发现它非常棘手,至少在尝试满足2.1用户时是这样。这些天事情可能会更容易,我不确定。因此,我们的想法是将您的磁贴的Vertice数组保存到视频内存中,然后像使用纹理一样返回指针。可以想象,不是每个帧都向上发送Vertice数组缓冲区,每个平铺绘图都会加快一些速度。即使事情不是静止的,它也是一种很好的方法,因为我怀疑每一帧的情况都在发生变化。

我在网上遇到的另一个建议是使用Short而不是Float作为Vertices。然后更改已完成渲染的比例以获得所需的大小。这会降低你的顶点的大小,并加快一点...不是很大的数量,但我仍然值得尝试。

我想添加的最后一件事,如果您最终使用任何透明度...请注意,您必须回到前面才能使其工作,这也会对性能产生影响。如果从前到后绘制,渲染引擎会自动知道在坐标不可见时不绘制...绘制回到前面意味着绘制所有内容。记住这一点,并尽可能尝试从前到后绘制。

祝你好运,我很想知道你是怎么做的......我刚刚开始比赛,我很开心。如果你还没有遇到这个...我认为值得一读。 http://www.codeproject.com/KB/graphics/hexagonal_part1.aspx