我有一个问题是否有一个特殊的模式来分组模型在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,-y);
- mModelBatch.render(instance);
- }
- }
- mModelBatch.end();
- public void getRenderables(Array<Renderable> renderables,Pool<Renderable> pool)
- {
- 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,y%3,-y);
- Renderable renderable = pool.obtain();
- renderable = instance.getRenderable(renderable);
- renderables.add(renderable);
- }
- }
}
我使用它,如下所示:
- mModelBatch.begin(camera);
- mModelBatch.render(testRenderProvider);
- mModelBatch.end();
但是它仍然给了我13 FPS.
同时做另一个测试,我在混合器中创建与之前程序中相同的地图.接下来,我将所有内容分组在一个对象中(没有任何其他版本).这样我就创建了一个大小接近1MB的BIG对象,可以从Blender的屏幕截图中看到.
我改变了测试程序,只能画出一个BIG对象:
- mModelBatch.begin(camera);
- modelInstance1.transform.setToTranslation(0,0);
- mModelBatch.render(modelInstance1);
- mModelBatch.end();
我做的下一件事是我在手机上启动了程序(Sony XPeria Mini Pro – 与之前相同)和iPod 5g,我已经… 60 FPS!
可以在一个绘图调用中渲染一切吗?
解决方法
问题解决了!我在一个低端移动设备上实现了60个FPS.游戏运行平稳.我发现如何将多个Meshes合并成一个网格,以便可以使用VBO机制. libGDX中有一个错误,导致网格复制方法无法使用多个网格.变更后,地图划分为小部分.每个扇区由具有相同z轴值的网格构成,如下图所示:
VBO机制是非常有限的,因此不能一次绘制多个顶点,这就是为什么这些部门必须相当小.
必须编写新的渲染器才能正确处理渲染.并且渲染器的部分动态地合并网格(没有任何单独的工具,例如blender).
- 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),vertexSize,offset,numComponents,vertexOffset,numVertices);
- vertexOffset += numVertices;
- vertexSizeOffset += baseSize;
- }
- Mesh result = new Mesh(true,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,attrs);
- result.setVertices(vertices,numVertices * newVertexSize);
- result.setIndices(indices);
- return result;
- }
这对于尝试在libGDX中编写自己的3D游戏的人来说可能非常有用.没有这种机制,写出比几种型号更多的编辑是不可能的.