Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java LibGDX 3D增强性能_Java_Android_Opengl Es_3d_Libgdx - Fatal编程技术网

Java LibGDX 3D增强性能

Java LibGDX 3D增强性能,java,android,opengl-es,3d,libgdx,Java,Android,Opengl Es,3d,Libgdx,我正在做一个3D游戏 游戏需要大约100个立方体才能工作,所有立方体都是动态的 我真的不知道像这样的游戏需要多少性能,但我正在用一个GPU,1GB内存,1.5GHz双核测试。我知道如何在一个网格中渲染所有立方体,但我无法单独移动所有立方体 这个设置给了我一个非常摇摆不定的fps。在20到50岁之间跳跃,大多在30岁以下。(在模拟器10-15中) 当游戏开始时,我构建了一个模型实例的arraylist,它们都使用相同的模型 model = new ModelBuilder().createBox(

我正在做一个3D游戏

游戏需要大约100个立方体才能工作,所有立方体都是动态的

我真的不知道像这样的游戏需要多少性能,但我正在用一个GPU,1GB内存,1.5GHz双核测试。我知道如何在一个网格中渲染所有立方体,但我无法单独移动所有立方体

这个设置给了我一个非常摇摆不定的fps。在20到50岁之间跳跃,大多在30岁以下。(在模拟器10-15中)

当游戏开始时,我构建了一个模型实例的arraylist,它们都使用相同的模型

model = new ModelBuilder().createBox(1f, 1f, 1f, new Material(ColorAttribute.createDiffuse(Color.GREEN)), Usage.Position | Usage.Normal);

// width,height,length = 5, creating a total of 125 cubes

for (int x = 0; x < width; x++) {
    for (int y = 0; y < height; y++) {
        for (int z = 0; z < length; z++) {
            if (this.map[x][y][z] > 0) {
                this.modelInstances.add(instance = new ModelInstance(model));
                instance.transform.translate(x, -(y * 1.5f), -z);
            }
        }
    }
}
摄像机正在初始化:

camera3D = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera3D.position.set(0f, 8f, 5f);
camera3D.lookAt(0, 0, 0);
camera3D.near = 1f;
camera3D.far = 300f;
camera3D.update();
  • 如何提高性能
  • 对于这样的游戏来说,平板电脑太弱了吗?或者问题在于代码
编辑:


也对webGL做了一些测试,同样的平板电脑,使用chrome,渲染125个立方体:稳定的40-50 fps

您可以将所有立方体批处理到单个模型和模型实例中,如下所示:

int width = 5;
int height = 5;
int length = 5;
int numCubes = width*height*length;

ModelBuilder mb = new ModelBuilder();
mb.begin();
MeshPartBuilder mpb = mb.part("cubes", GL20.GL_TRIANGLES, (Usage.Position | Usage.Normal), new Material(ColorAttribute.createDiffuse(Color.GREEN)));
for (int i=0; i<numCubes; i++){
    mpb.box(1, 1, 1); 
}
Model model = mb.end();
mBatchedCubesModelInstance = new ModelInstance(model);
现在CPU顶点操纵不如着色器顶点操纵有效,所以如果在每一帧周围移动所有立方体,这可能会限制CPU。如果不经常旋转它们,那么为旋转创建一个单独的“脏”变量可能会有所帮助,并且只有在更新方法中需要时才旋转


编辑:从更新

如果希望具有透明度,则多维数据集必须是可排序的,以便可以从远到近进行排序以进行绘制。它们的
索引
值必须更新为新的顺序,因为这是它们在网格中排序的方式。这是一个支持排序的多维数据集类(现在必须独立跟踪颜色,因为多维数据集可能会移动到网格的不同部分)


宽度、高度和长度的值是多少?它们总共渲染了5125个立方体。看起来不错。这就是您在
render()
中所做的一切吗?@noone我有几行代码可以将fps写入屏幕,但这不是问题所在,如果我对“mb.render(this.modelsinstances)”进行注释,fps将稳定到55-60,我可以确认这是一个问题。与您的故事相同:使用ModelBuilder创建长方体,在我的例子中,大约有100-120个。将它们放在ModelInstance数组中并渲染它们。在galaxy note 2上每秒30帧。我的多维数据集是实时动态生成的,但一旦它们出现,它们就永远不会移动(没有应用任何变换)。我更新了它,以支持为每个多维数据集设置颜色,并使其对各种顶点属性使用组合更具鲁棒性。然而,如果您想支持alpha通道,它会变得更复杂。每当立方体移动时,您必须将它们从远到近进行排序。通过排序,我的意思是更改它们的
索引
参数,使最远的参数为0,然后从那里继续。更改索引参数时,
dirty
也应标记为true。我为
index
添加了一个setter,用于标记颜色和变换dirty,因为如果索引更改,它将始终需要更新。需要明确的是,它们在存储它们的任何数组中的顺序都无关紧要。只有它们的
索引
参数值对它们的排序很重要。我没有在环境中测试过它——OP使用的是纯色立方体,所以我只是复制了它。因此,是的,您需要更改用法以使其作出反应。您使用的是半透明颜色吗?如果是的话,这会变得非常复杂,因为你必须在每一帧从后到前对立方体进行排序。还要确保背面消隐已启用,否则还必须根据立方体相对于摄影机视图的旋转方式对立方体的面进行排序!当你说一些边缺失时,听起来好像深度测试已经关闭了,所以立方体的背面在正面的前面画。每个面只画一条线<代码>Gdx.gl.glEnable(GL20.gl深度测试)
Gdx.gl.glCullFace(GL20.glu-BACK)。将它们放入着色器子类的
begin
方法中取而代之。
int width = 5;
int height = 5;
int length = 5;
int numCubes = width*height*length;

ModelBuilder mb = new ModelBuilder();
mb.begin();
MeshPartBuilder mpb = mb.part("cubes", GL20.GL_TRIANGLES, (Usage.Position | Usage.Normal), new Material(ColorAttribute.createDiffuse(Color.GREEN)));
for (int i=0; i<numCubes; i++){
    mpb.box(1, 1, 1); 
}
Model model = mb.end();
mBatchedCubesModelInstance = new ModelInstance(model);
public class Cube {

    private int index;
    int vertexFloatSize;
    int posOffset;
    int norOffset;
    boolean hasColor;
    int colOffset;
    private Vector3 position = new Vector3();
    private Matrix4 rotationTransform = new Matrix4().idt();
    private Color color = new Color();
    public float halfWidth, halfHeight, halfDepth;
    private boolean transformDirty = false;
    private boolean colorDirty = false;

    static final Vector3 CORNER000 = new Vector3();
    static final Vector3 CORNER010 = new Vector3();
    static final Vector3 CORNER100 = new Vector3();
    static final Vector3 CORNER110 = new Vector3();
    static final Vector3 CORNER001 = new Vector3();
    static final Vector3 CORNER011 = new Vector3();
    static final Vector3 CORNER101 = new Vector3();
    static final Vector3 CORNER111 = new Vector3();

    static final Vector3[] FACE0 = {CORNER000, CORNER100, CORNER110, CORNER010};
    static final Vector3[] FACE1 = {CORNER101, CORNER001, CORNER011, CORNER111};
    static final Vector3[] FACE2 = {CORNER000, CORNER010, CORNER011, CORNER001};
    static final Vector3[] FACE3 = {CORNER101, CORNER111, CORNER110, CORNER100};
    static final Vector3[] FACE4 = {CORNER101, CORNER100, CORNER000, CORNER001};
    static final Vector3[] FACE5 = {CORNER110, CORNER111, CORNER011, CORNER010};
    static final Vector3[][] FACES = {FACE0, FACE1, FACE2, FACE3, FACE4, FACE5};

    static final Vector3 NORMAL0 = new Vector3();
    static final Vector3 NORMAL1 = new Vector3();
    static final Vector3 NORMAL2 = new Vector3();
    static final Vector3 NORMAL3 = new Vector3();
    static final Vector3 NORMAL4 = new Vector3();
    static final Vector3 NORMAL5 = new Vector3();
    static final Vector3[] NORMALS = {NORMAL0, NORMAL1, NORMAL2, NORMAL3, NORMAL4, NORMAL5};

    public Cube(float x, float y, float z, float width, float height, float depth, int index, 
            VertexAttributes vertexAttributes, float[] meshVertices){
        position.set(x,y,z);
        this.halfWidth = width/2;
        this.halfHeight = height/2;
        this.halfDepth = depth/2;
        this.index = index;


        vertexFloatSize = vertexAttributes.vertexSize/4; //4 bytes per float
        posOffset = getVertexAttribute(Usage.Position, vertexAttributes).offset/4;
        norOffset = getVertexAttribute(Usage.Normal, vertexAttributes).offset/4;

        VertexAttribute colorAttribute = getVertexAttribute(Usage.Color, vertexAttributes);
        hasColor = colorAttribute!=null;
        if (hasColor){
            colOffset = colorAttribute.offset/4;
            this.setColor(Color.WHITE, meshVertices);
        }
        transformDirty = true;
    }

    public void setIndex(int index){
        this.index = index;
        transformDirty = true;
        colorDirty = true;
    }

    /**
     * Call this after moving and/or rotating.
     */
    public void update(float[] meshVertices){
        if (colorDirty && hasColor){
            for (int faceIndex= 0; faceIndex<6; faceIndex++){
                int baseVertexIndex = (index*24 + faceIndex*4)*vertexFloatSize;//24 unique vertices per cube, 4 unique vertices per face
                for (int cornerIndex=0; cornerIndex<4; cornerIndex++){
                    int vertexIndex = baseVertexIndex + cornerIndex*vertexFloatSize + colOffset;
                    meshVertices[vertexIndex] = color.r;
                    meshVertices[++vertexIndex] = color.g;
                    meshVertices[++vertexIndex] = color.b;
                    meshVertices[++vertexIndex] = color.a;
                }
            }
            colorDirty = false;
        }


        if (!transformDirty){
            return;
        }
        transformDirty = false;

        CORNER000.set(-halfWidth,-halfHeight,-halfDepth).rot(rotationTransform).add(position);
        CORNER010.set(-halfWidth,halfHeight,-halfDepth).rot(rotationTransform).add(position);
        CORNER100.set(halfWidth,-halfHeight,-halfDepth).rot(rotationTransform).add(position);
        CORNER110.set(halfWidth,halfHeight,-halfDepth).rot(rotationTransform).add(position);
        CORNER001.set(-halfWidth,-halfHeight,halfDepth).rot(rotationTransform).add(position);
        CORNER011.set(-halfWidth,halfHeight,halfDepth).rot(rotationTransform).add(position);
        CORNER101.set(halfWidth,-halfHeight,halfDepth).rot(rotationTransform).add(position);
        CORNER111.set(halfWidth,halfHeight,halfDepth).rot(rotationTransform).add(position);

        NORMAL0.set(0,0,-1).rot(rotationTransform);
        NORMAL1.set(0,0,1).rot(rotationTransform);
        NORMAL2.set(-1,0,0).rot(rotationTransform);
        NORMAL3.set(1,0,0).rot(rotationTransform);
        NORMAL4.set(0,-1,0).rot(rotationTransform);
        NORMAL5.set(0,1,0).rot(rotationTransform);

        for (int faceIndex= 0; faceIndex<6; faceIndex++){
            int baseVertexIndex = (index*24 + faceIndex*4)*vertexFloatSize;//24 unique vertices per cube, 4 unique vertices per face
            for (int cornerIndex=0; cornerIndex<4; cornerIndex++){
                int vertexIndex = baseVertexIndex + cornerIndex*vertexFloatSize + posOffset;
                meshVertices[vertexIndex] = FACES[faceIndex][cornerIndex].x;
                meshVertices[++vertexIndex] = FACES[faceIndex][cornerIndex].y;
                meshVertices[++vertexIndex] = FACES[faceIndex][cornerIndex].z;

                vertexIndex = baseVertexIndex + cornerIndex*vertexFloatSize + norOffset;
                meshVertices[vertexIndex] = NORMALS[faceIndex].x;
                meshVertices[++vertexIndex] = NORMALS[faceIndex].y;
                meshVertices[++vertexIndex] = NORMALS[faceIndex].z;
            }
        }
    }

    public Cube setColor(Color color){
        if (hasColor){
            this.color.set(color);
            colorDirty = true;
        }
        return this;
    }

    public Cube translate(float x, float y, float z){
        position.add(x,y,z);
        transformDirty = true;
        return this;
    }

    public Cube translateTo(float x, float y, float z){
        position.set(x,y,z);
        transformDirty = true;
        return this;
    }

    public Cube rotate(float axisX, float axisY, float axisZ, float degrees){
        rotationTransform.rotate(axisX, axisY, axisZ, degrees);
        transformDirty = true;
        return this;
    }

    public Cube rotateTo(float axisX, float axisY, float axisZ, float degrees){
        rotationTransform.idt();
        rotationTransform.rotate(axisX, axisY, axisZ, degrees);
        transformDirty = true;
        return this;
    }

    public VertexAttribute getVertexAttribute (int usage, VertexAttributes attributes) {
        int len = attributes.size();
        for (int i = 0; i < len; i++)
            if (attributes.get(i).usage == usage) return attributes.get(i);

        return null;
    }
}
    mBatchedCubesMesh = model.meshes.get(0);
    VertexAttributes vertexAttributes = mBatchedCubesMesh.getVertexAttributes();
    int vertexFloatSize = vertexAttributes .vertexSize / 4; //4 bytes per float
    mBatchedCubesVertices = new float[numCubes * 24 * vertexFloatSize]; //24 unique vertices per cube
    mBatchedCubesMesh.getVertices(mBatchedCubesVertices);

    mBatchedCubes = new Array<Cube>(numCubes);
    int cubeNum = 0;
    for (int x = 0; x < width; x++) {
        for (int y = 0; y < height; y++) {
            for (int z = 0; z < length; z++) {
                mBatchedCubes.add(new Cube((x-(width/2f))*1.5f, -((y-(height/2f)) * 1.5f), -(z-(length/2f))*1.5f, 1,1,1, cubeNum++, vertexAttributes, mBatchedCubesVertices ));
            }
        }
    }
mBatchedCubes.get(0).rotate(1, 1, 1, 180*delta); //example manipulation of a single cube

for (Cube cube : mBatchedCubes){ //must update any changed cubes. 
    cube.update(mBatchedCubesVertices);
}
mBatchedCubesMesh.setVertices(mBatchedCubesVertices); //apply changes to mesh

...

modelBatch.begin(camera);
modelBatch.render(mBatchedCubesModelInstance);
modelBatch.end();
public class Cube implements Comparable<Cube>{

    private int index;
    int vertexFloatSize;
    int posOffset;
    int norOffset;
    boolean hasColor;
    int colOffset;
    private Vector3 position = new Vector3();
    private Matrix4 rotationTransform = new Matrix4().idt();
    public float halfWidth, halfHeight, halfDepth;
    private boolean transformDirty = false;
    private boolean colorDirty = false;
    private Color color = new Color();
    float camDistSquared;

    static final Vector3 CORNER000 = new Vector3();
    static final Vector3 CORNER010 = new Vector3();
    static final Vector3 CORNER100 = new Vector3();
    static final Vector3 CORNER110 = new Vector3();
    static final Vector3 CORNER001 = new Vector3();
    static final Vector3 CORNER011 = new Vector3();
    static final Vector3 CORNER101 = new Vector3();
    static final Vector3 CORNER111 = new Vector3();

    static final Vector3[] FACE0 = {CORNER000, CORNER100, CORNER110, CORNER010};
    static final Vector3[] FACE1 = {CORNER101, CORNER001, CORNER011, CORNER111};
    static final Vector3[] FACE2 = {CORNER000, CORNER010, CORNER011, CORNER001};
    static final Vector3[] FACE3 = {CORNER101, CORNER111, CORNER110, CORNER100};
    static final Vector3[] FACE4 = {CORNER101, CORNER100, CORNER000, CORNER001};
    static final Vector3[] FACE5 = {CORNER110, CORNER111, CORNER011, CORNER010};
    static final Vector3[][] FACES = {FACE0, FACE1, FACE2, FACE3, FACE4, FACE5};

    static final Vector3 NORMAL0 = new Vector3();
    static final Vector3 NORMAL1 = new Vector3();
    static final Vector3 NORMAL2 = new Vector3();
    static final Vector3 NORMAL3 = new Vector3();
    static final Vector3 NORMAL4 = new Vector3();
    static final Vector3 NORMAL5 = new Vector3();
    static final Vector3[] NORMALS = {NORMAL0, NORMAL1, NORMAL2, NORMAL3, NORMAL4, NORMAL5};

    public Cube(float x, float y, float z, float width, float height, float depth, int index, 
        VertexAttributes vertexAttributes, float[] meshVertices){
    position.set(x,y,z);
    this.halfWidth = width/2;
    this.halfHeight = height/2;
    this.halfDepth = depth/2;
    this.index = index;


    vertexFloatSize = vertexAttributes.vertexSize/4; //4 bytes per float
    posOffset = getVertexAttribute(Usage.Position, vertexAttributes).offset/4;
    norOffset = getVertexAttribute(Usage.Normal, vertexAttributes).offset/4;

    VertexAttribute colorAttribute = getVertexAttribute(Usage.Color, vertexAttributes);
    hasColor = colorAttribute!=null;
    if (hasColor){
        colOffset = colorAttribute.offset/4;
        this.setColor(Color.WHITE, meshVertices);
    }
    transformDirty = true;
    }

    public void updateCameraDistance(Camera cam){
    camDistSquared = cam.position.dst2(position);
    }

    /**
     * Call this after moving and/or rotating.
     */
    public void update(float[] meshVertices){

    if (transformDirty){
        transformDirty = false;

        CORNER000.set(-halfWidth,-halfHeight,-halfDepth).rot(rotationTransform).add(position);
        CORNER010.set(-halfWidth,halfHeight,-halfDepth).rot(rotationTransform).add(position);
        CORNER100.set(halfWidth,-halfHeight,-halfDepth).rot(rotationTransform).add(position);
        CORNER110.set(halfWidth,halfHeight,-halfDepth).rot(rotationTransform).add(position);
        CORNER001.set(-halfWidth,-halfHeight,halfDepth).rot(rotationTransform).add(position);
        CORNER011.set(-halfWidth,halfHeight,halfDepth).rot(rotationTransform).add(position);
        CORNER101.set(halfWidth,-halfHeight,halfDepth).rot(rotationTransform).add(position);
        CORNER111.set(halfWidth,halfHeight,halfDepth).rot(rotationTransform).add(position);

        NORMAL0.set(0,0,-1).rot(rotationTransform);
        NORMAL1.set(0,0,1).rot(rotationTransform);
        NORMAL2.set(-1,0,0).rot(rotationTransform);
        NORMAL3.set(1,0,0).rot(rotationTransform);
        NORMAL4.set(0,-1,0).rot(rotationTransform);
        NORMAL5.set(0,1,0).rot(rotationTransform);

        for (int faceIndex= 0; faceIndex<6; faceIndex++){
        int baseVertexIndex = (index*24 + faceIndex*4)*vertexFloatSize;//24 unique vertices per cube, 4 unique vertices per face
        for (int cornerIndex=0; cornerIndex<4; cornerIndex++){
            int vertexIndex = baseVertexIndex + cornerIndex*vertexFloatSize + posOffset;
            meshVertices[vertexIndex] = FACES[faceIndex][cornerIndex].x;
            meshVertices[++vertexIndex] = FACES[faceIndex][cornerIndex].y;
            meshVertices[++vertexIndex] = FACES[faceIndex][cornerIndex].z;

            vertexIndex = baseVertexIndex + cornerIndex*vertexFloatSize + norOffset;
            meshVertices[vertexIndex] = NORMALS[faceIndex].x;
            meshVertices[++vertexIndex] = NORMALS[faceIndex].y;
            meshVertices[++vertexIndex] = NORMALS[faceIndex].z;
        }
        }
    }

    if (colorDirty){
        colorDirty = false;

        for (int faceIndex= 0; faceIndex<6; faceIndex++){
        int baseVertexIndex = (index*24 + faceIndex*4)*vertexFloatSize;//24 unique vertices per cube, 4 unique vertices per face
        for (int cornerIndex=0; cornerIndex<4; cornerIndex++){
            int vertexIndex = baseVertexIndex + cornerIndex*vertexFloatSize + colOffset;
            meshVertices[vertexIndex] = color.r;
            meshVertices[++vertexIndex] = color.g;
            meshVertices[++vertexIndex] = color.b;
            meshVertices[++vertexIndex] = color.a;
        }
        }
    }
    }

    public Cube setColor(Color color, float[] meshVertices){
    if (hasColor){
        this.color.set(color);
        colorDirty = true;

    }
    return this;
    }

    public void setIndex(int index){
    if (this.index != index){
        transformDirty = true;
        colorDirty = true;
        this.index = index;
    }
    }

    public Cube translate(float x, float y, float z){
    position.add(x,y,z);
    transformDirty = true;
    return this;
    }

    public Cube translateTo(float x, float y, float z){
    position.set(x,y,z);
    transformDirty = true;
    return this;
    }

    public Cube rotate(float axisX, float axisY, float axisZ, float degrees){
    rotationTransform.rotate(axisX, axisY, axisZ, degrees);
    transformDirty = true;
    return this;
    }

    public Cube rotateTo(float axisX, float axisY, float axisZ, float degrees){
    rotationTransform.idt();
    rotationTransform.rotate(axisX, axisY, axisZ, degrees);
    transformDirty = true;
    return this;
    }

    public VertexAttribute getVertexAttribute (int usage, VertexAttributes attributes) {
    int len = attributes.size();
    for (int i = 0; i < len; i++)
        if (attributes.get(i).usage == usage) return attributes.get(i);

    return null;
    }

    @Override
    public int compareTo(Cube other) {
    //This is a simple sort based on center point distance to camera. A more 
    //sophisticated sorting method might be required if the cubes are not all the same 
    //size (such as calculating which of the 8 vertices is closest to the camera
    //and using that instead of the center point).
    if (camDistSquared>other.camDistSquared)
        return -1;
    return camDistSquared<other.camDistSquared ? 1 : 0;
    }
}
for (Cube cube : mBatchedCubes){
    cube.updateCameraDistance(camera);
}
mBatchedCubes.sort();
int index = 0;
for (Cube cube : mBatchedCubes){
    cube.setIndex(index++);
}