Trouble batching cubes in libgdx

﹥>﹥吖頭↗ 提交于 2019-12-01 14:19:42

I see a couple problems:

  1. You have blending off and/or your shader isn't setting the alpha value

  2. You aren't culling back faces.

So when you create your new material, instead of just using new Material(), use:

new Material(
    IntAttribute.createCullFace(GL20.GL_FRONT),//For some reason, libgdx ModelBuilder makes boxes with faces wound in reverse, so cull FRONT
    new BlendingAttribute(1f), //opaque since multiplied by vertex color
    new DepthTestAttribute(false), //don't want depth mask or rear cubes might not show through
    ColorAttribute.createDiffuse(Color.WHITE) //white since multiplied by vertex color
    );

You will also need to sort the cubes by distance from camera to get their alphas to layer correctly. Here's an updated Cube class that supports sorting. It has to be able to track color independently from the vertices array in case its index changes:

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) {
    //the cube has a lower index than a cube that is closer to the camera
    if (camDistSquared>other.camDistSquared)
        return -1;
    return camDistSquared<other.camDistSquared ? 1 : 0;
    }
}

And you would sort it like this:

for (Cube cube : mBatchedCubes){
    cube.updateCameraDistance(camera);
}
mBatchedCubes.sort();
int index = 0;
for (Cube cube : mBatchedCubes){
    cube.setIndex(index++);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!