Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.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
Android libGDX中的慢速模型批渲染_Android_Performance_Opengl Es_Rendering_Libgdx - Fatal编程技术网

Android libGDX中的慢速模型批渲染

Android libGDX中的慢速模型批渲染,android,performance,opengl-es,rendering,libgdx,Android,Performance,Opengl Es,Rendering,Libgdx,我有一个问题,在libGDX中是否有用于分组模型的特殊模式。我创建了一个实现ApplicationListener的简单类,它显示了我的问题。我正在使用libGDX的夜间构建 我读了两个使用相同纹理的不同模型。应用程序分别渲染每种类型的250个模型。这是渲染代码部分的外观: mModelBatch.begin(camera); for(int y=0; y<50; y++) { for(int x=-5; x<5; x++) { Mod

我有一个问题,在libGDX中是否有用于分组模型的特殊模式。我创建了一个实现
ApplicationListener
的简单类,它显示了我的问题。我正在使用libGDX的夜间构建

我读了两个使用相同纹理的不同模型。应用程序分别渲染每种类型的250个模型。这是渲染代码部分的外观:

  mModelBatch.begin(camera);
  for(int y=0; y<50; y++)
  {
     for(int x=-5; x<5; x++)
     {
        ModelInstance instance;
        if(x%2 == 0) instance = modelInstance1;
        else instance = modelInstance2;

        instance.transform.setToTranslation(x, 0, -y);
        mModelBatch.render(instance);
     }

  }

  mModelBatch.end(); 
然而,它仍然给了我13帧。 同时,为了进行另一个测试,我在blender中创建了与前一个程序相同的映射。接下来,我将所有内容分组到一个对象中(没有任何附加版本)。通过这种方式,我创建了一个大小接近1MB的大对象,它可以在blender的屏幕截图上看到

我更改了测试程序,使其仅绘制一个大对象:

mModelBatch.begin(camera);
      modelInstance1.transform.setToTranslation(0, 0, 0);
      mModelBatch.render(modelInstance1);
mModelBatch.end();
接下来我做的就是在我的手机(Sony XPeria Mini Pro-和以前一样)和iPod 5g上启动了这个程序,我得到了。。。每秒60帧!


是否可以在一次绘图调用中渲染所有内容?

问题已解决!我在ver低端移动设备上实现了60 FPS。比赛进行得很顺利。我了解了如何将多个网格合并为一个网格,以便可以使用VBO mechanizms。libGDX中存在一个错误,导致网格复制方法无法用于多个网格。更改后,地图被划分为小部分。每个扇区由具有相同z轴值的网格组成,如下图所示:

VBO机制非常有限,因此一次可以绘制的顶点不多,这就是扇区必须非常小的原因。 必须编写新的渲染器才能正确处理渲染。渲染器的各个部分正在动态地合并网格(没有任何单独的工具,例如blender)

公共静态网格合并网格(AbstractList网格、AbstractList变换)
{
如果(meshes.size()==0)返回null;
int vertexArrayTotalSize=0;
int indexArrayTotalSize=0;
VertexAttributes va=mesh.get(0.getVertexAttributes();
int vaA[]=新的int[va.size()];
对于(int i=0;i 0)
指数[i]=新指数;
否则{
最终int idx=大小*新顶点大小;
对于(int j=0;j

这对于试图用libGDX编写自己的3D游戏的人来说非常有用。如果没有这种机制,就不可能编写比几个模型更复杂的东西

我还没有使用libgdxfor3d,上一次使用OpenGL也是几年前的事了。但我稍微记得,如果要多次渲染同一对象,应该使用顶点缓冲区对象()。我认为问题不在于纹理绑定,因为我假设modelBatch以一种智能的方式处理它自己。试着分析代码以了解什么是最耗时的。马里奥在这里有一些关于这个主题的幻灯片:我知道所有的事情都应该在一次抽签中完成。它应该只使用一个纹理,所有的模型应该一次渲染。我不知道如何在libgdx中启用适当的绘图模式(如果存在)。或者我必须编写自己的渲染器部分来解决这个问题。有没有人遇到过类似的问题,可以和我分享经验?答案不错,请毫不犹豫地接受。接受你自己的答案没关系:)嗨,帕维。每秒60帧真是太棒了!我想知道你是如何使用这种方法的?我是libgdx的初学者,我的游戏fps经常下降到8。查看了libgdx代码,发现SpriteBatch使用VertexArray而不是VertexBufferObject创建网格。我读到VBO是实现良好性能的一种方法。我在网格中将forceVBO tp设置为true,但没有明显差异。如果你能帮我的话,我会继续讲更多的细节。感谢您的帮助。当然我会帮助您,但这并不简单,因为您需要编写自己的libGDX部分。这是因为libGDX代码有bug,您不能使用它。诀窍是将您的模型(我假设您在3D中使用它们)分成小块,然后使用VBO(强制VBO适用于一个单独的模型)。因此,技巧是将每个网格连接起来,创建一个更大(但不要太大)的网格,然后使用VBO进行渲染。如果您需要更复杂的答案(包括代码片段),请告诉我,我将非常乐意帮助您。我相信我也有同样的问题,但我不确定如何使用
mergemesh()
方法。你介意举一个使用它的代码的例子吗?基本上,我不知道从哪里获得作为参数传递的
AbstractList网格
mModelBatch.begin(camera);      
mModelBatch.render(testRenderProvider);
mModelBatch.end();
mModelBatch.begin(camera);
      modelInstance1.transform.setToTranslation(0, 0, 0);
      mModelBatch.render(modelInstance1);
mModelBatch.end();
public static Mesh mergeMeshes(AbstractList<Mesh> meshes, AbstractList<Matrix4> transformations)
{
    if(meshes.size() == 0) return null;

    int vertexArrayTotalSize = 0;
    int indexArrayTotalSize = 0;

    VertexAttributes va = meshes.get(0).getVertexAttributes();
    int vaA[] = new int [va.size()];
    for(int i=0; i<va.size(); i++)
    {
        vaA[i] = va.get(i).usage;
    }

    for(int i=0; i<meshes.size(); i++)
    {
        Mesh mesh = meshes.get(i);
        if(mesh.getVertexAttributes().size() != va.size()) 
        {
            meshes.set(i, copyMesh(mesh, true, false, vaA));
        }

        vertexArrayTotalSize += mesh.getNumVertices() * mesh.getVertexSize() / 4;
        indexArrayTotalSize += mesh.getNumIndices();
    }

    final float vertices[] = new float[vertexArrayTotalSize];
    final short indices[] = new short[indexArrayTotalSize];

    int indexOffset = 0;
    int vertexOffset = 0;
    int vertexSizeOffset = 0;
    int vertexSize = 0;

    for(int i=0; i<meshes.size(); i++)
    {
        Mesh mesh = meshes.get(i);

        int numIndices = mesh.getNumIndices();
        int numVertices = mesh.getNumVertices();
        vertexSize = mesh.getVertexSize() / 4;
        int baseSize = numVertices * vertexSize;
        VertexAttribute posAttr = mesh.getVertexAttribute(Usage.Position);
        int offset = posAttr.offset / 4;
        int numComponents = posAttr.numComponents;

        { //uzupelnianie tablicy indeksow
            mesh.getIndices(indices, indexOffset);
            for(int c = indexOffset; c < (indexOffset + numIndices); c++)
            {
                indices[c] += vertexOffset;
            }
            indexOffset += numIndices;
        }

        mesh.getVertices(0, baseSize, vertices, vertexSizeOffset);
        Mesh.transform(transformations.get(i), vertices, vertexSize, offset, numComponents, vertexOffset, numVertices);
        vertexOffset += numVertices;
        vertexSizeOffset += baseSize;
    }

    Mesh result = new Mesh(true, vertexOffset, indices.length, meshes.get(0).getVertexAttributes());
    result.setVertices(vertices);
    result.setIndices(indices);
    return result;
} 

    public static Mesh copyMesh(Mesh meshToCopy, boolean isStatic, boolean removeDuplicates, final int[] usage) {
    // TODO move this to a copy constructor?
    // TODO duplicate the buffers without double copying the data if possible.
    // TODO perhaps move this code to JNI if it turns out being too slow.
    final int vertexSize = meshToCopy.getVertexSize() / 4;
    int numVertices = meshToCopy.getNumVertices();
    float[] vertices = new float[numVertices * vertexSize];
    meshToCopy.getVertices(0, vertices.length, vertices);
    short[] checks = null;
    VertexAttribute[] attrs = null;
    int newVertexSize = 0;
    if (usage != null) {
        int size = 0;
        int as = 0;
        for (int i = 0; i < usage.length; i++)
            if (meshToCopy.getVertexAttribute(usage[i]) != null) {
                size += meshToCopy.getVertexAttribute(usage[i]).numComponents;
                as++;
            }
        if (size > 0) {
            attrs = new VertexAttribute[as];
            checks = new short[size];
            int idx = -1;
            int ai = -1;
            for (int i = 0; i < usage.length; i++) {
                VertexAttribute a = meshToCopy.getVertexAttribute(usage[i]);
                if (a == null)
                    continue;
                for (int j = 0; j < a.numComponents; j++)
                    checks[++idx] = (short)(a.offset/4 + j);
                attrs[++ai] = new VertexAttribute(a.usage, a.numComponents, a.alias);
                newVertexSize += a.numComponents;
            }
        }
    }
    if (checks == null) {
        checks = new short[vertexSize];
        for (short i = 0; i < vertexSize; i++)
            checks[i] = i;
        newVertexSize = vertexSize;
    }

    int numIndices = meshToCopy.getNumIndices();
    short[] indices = null; 
    if (numIndices > 0) {
        indices = new short[numIndices];
        meshToCopy.getIndices(indices);
        if (removeDuplicates || newVertexSize != vertexSize) {
            float[] tmp = new float[vertices.length];
            int size = 0;
            for (int i = 0; i < numIndices; i++) {
                final int idx1 = indices[i] * vertexSize;
                short newIndex = -1;
                if (removeDuplicates) {
                    for (short j = 0; j < size && newIndex < 0; j++) {
                        final int idx2 = j*newVertexSize;
                        boolean found = true;
                        for (int k = 0; k < checks.length && found; k++) {
                            if (tmp[idx2+k] != vertices[idx1+checks[k]])
                                found = false;
                        }
                        if (found)
                            newIndex = j;
                    }
                }
                if (newIndex > 0)
                    indices[i] = newIndex;
                else {
                    final int idx = size * newVertexSize;
                    for (int j = 0; j < checks.length; j++)
                        tmp[idx+j] = vertices[idx1+checks[j]];
                    indices[i] = (short)size;
                    size++;
                }
            }
            vertices = tmp;
            numVertices = size;
        }
    }

    Mesh result;
    if (attrs == null)
        result = new Mesh(isStatic, numVertices, indices == null ? 0 : indices.length, meshToCopy.getVertexAttributes());
    else
        result = new Mesh(isStatic, numVertices, indices == null ? 0 : indices.length, attrs);
    result.setVertices(vertices, 0, numVertices * newVertexSize);
    result.setIndices(indices);
    return result;
}