Android – 在libGDX中的慢速模型批处理渲染

前端之家收集整理的这篇文章主要介绍了Android – 在libGDX中的慢速模型批处理渲染前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个问题是否有一个特殊的模式来分组模型在libGDX.我创建了一个实现ApplicationListener的简单类,显示了我的问题.我正在使用libGDX的夜间版本.

我读了两个使用相同纹理的不同的模型.该应用程序分别呈现每种类型的250种型号.这是渲染代码的一部分如何:

  1. mModelBatch.begin(camera);
  2. for(int y=0; y<50; y++)
  3. {
  4. for(int x=-5; x<5; x++)
  5. {
  6. ModelInstance instance;
  7. if(x%2 == 0) instance = modelInstance1;
  8. else instance = modelInstance2;
  9.  
  10. instance.transform.setToTranslation(x,-y);
  11. mModelBatch.render(instance);
  12. }
  13.  
  14. }
  15.  
  16. mModelBatch.end();

我试图找到一个很好的解决方案,所以我写了另一个测试代码

  1. public void getRenderables(Array<Renderable> renderables,Pool<Renderable> pool)
  2. {
  3. for(int y=0; y<50; y++)
  4. {
  5. for(int x=-5; x<5; x++)
  6. {
  7. ModelInstance instance;
  8. if(x%2 == 0) instance = modelInstance1;
  9. else instance = modelInstance2;
  10.  
  11. instance.transform.setToTranslation(x,y%3,-y);
  12.  
  13. Renderable renderable = pool.obtain();
  14. renderable = instance.getRenderable(renderable);
  15. renderables.add(renderable);
  16. }
  17. }

}

我使用它,如下所示:

  1. mModelBatch.begin(camera);
  2. mModelBatch.render(testRenderProvider);
  3. mModelBatch.end();

但是它仍然给了我13 FPS.
同时做另一个测试,我在混合器中创建与之前程序中相同的地图.接下来,我将所有内容分组在一个对象中(没有任何其他版本).这样我就创建了一个大小接近1MB的BIG对象,可以从Blender的屏幕截图中看到.

我改变了测试程序,只能画出一个BIG对象:

  1. mModelBatch.begin(camera);
  2. modelInstance1.transform.setToTranslation(0,0);
  3. mModelBatch.render(modelInstance1);
  4. mModelBatch.end();

我做的下一件事是我在手机上启动了程序(Sony XPeria Mini Pro – 与之前相同)和iPod 5g,我已经… 60 FPS!

可以在一个绘图调用中渲染一切吗?

解决方法

问题解决了!我在一个低端移动设备上实现了60个FPS.游戏运行平稳.我发现如何将多个Meshes合并成一个网格,以便可以使用VBO机制. libGDX中有一个错误,导致网格复制方法无法使用多个网格.变更后,地图划分为小部分.每个扇区由具有相同z轴值的网格构成,如下图所示:

VBO机制是非常有限的,因此不能一次绘制多个顶点,这就是为什么这些部门必须相当小.
必须编写新的渲染器才能正确处理渲染.并且渲染器的部分动态地合并网格(没有任何单独的工具,例如blender).

  1. public static Mesh mergeMeshes(AbstractList<Mesh> meshes,AbstractList<Matrix4> transformations)
  2. {
  3. if(meshes.size() == 0) return null;
  4.  
  5. int vertexArrayTotalSize = 0;
  6. int indexArrayTotalSize = 0;
  7.  
  8. VertexAttributes va = meshes.get(0).getVertexAttributes();
  9. int vaA[] = new int [va.size()];
  10. for(int i=0; i<va.size(); i++)
  11. {
  12. vaA[i] = va.get(i).usage;
  13. }
  14.  
  15. for(int i=0; i<meshes.size(); i++)
  16. {
  17. Mesh mesh = meshes.get(i);
  18. if(mesh.getVertexAttributes().size() != va.size())
  19. {
  20. meshes.set(i,copyMesh(mesh,true,false,vaA));
  21. }
  22.  
  23. vertexArrayTotalSize += mesh.getNumVertices() * mesh.getVertexSize() / 4;
  24. indexArrayTotalSize += mesh.getNumIndices();
  25. }
  26.  
  27. final float vertices[] = new float[vertexArrayTotalSize];
  28. final short indices[] = new short[indexArrayTotalSize];
  29.  
  30. int indexOffset = 0;
  31. int vertexOffset = 0;
  32. int vertexSizeOffset = 0;
  33. int vertexSize = 0;
  34.  
  35. for(int i=0; i<meshes.size(); i++)
  36. {
  37. Mesh mesh = meshes.get(i);
  38.  
  39. int numIndices = mesh.getNumIndices();
  40. int numVertices = mesh.getNumVertices();
  41. vertexSize = mesh.getVertexSize() / 4;
  42. int baseSize = numVertices * vertexSize;
  43. VertexAttribute posAttr = mesh.getVertexAttribute(Usage.Position);
  44. int offset = posAttr.offset / 4;
  45. int numComponents = posAttr.numComponents;
  46.  
  47. { //uzupelnianie tablicy indeksow
  48. mesh.getIndices(indices,indexOffset);
  49. for(int c = indexOffset; c < (indexOffset + numIndices); c++)
  50. {
  51. indices[c] += vertexOffset;
  52. }
  53. indexOffset += numIndices;
  54. }
  55.  
  56. mesh.getVertices(0,baseSize,vertices,vertexSizeOffset);
  57. Mesh.transform(transformations.get(i),vertexSize,offset,numComponents,vertexOffset,numVertices);
  58. vertexOffset += numVertices;
  59. vertexSizeOffset += baseSize;
  60. }
  61.  
  62. Mesh result = new Mesh(true,indices.length,meshes.get(0).getVertexAttributes());
  63. result.setVertices(vertices);
  64. result.setIndices(indices);
  65. return result;
  66. }
  67.  
  68. public static Mesh copyMesh(Mesh meshToCopy,boolean isStatic,boolean removeDuplicates,final int[] usage) {
  69. // TODO move this to a copy constructor?
  70. // TODO duplicate the buffers without double copying the data if possible.
  71. // TODO perhaps move this code to JNI if it turns out being too slow.
  72. final int vertexSize = meshToCopy.getVertexSize() / 4;
  73. int numVertices = meshToCopy.getNumVertices();
  74. float[] vertices = new float[numVertices * vertexSize];
  75. meshToCopy.getVertices(0,vertices.length,vertices);
  76. short[] checks = null;
  77. VertexAttribute[] attrs = null;
  78. int newVertexSize = 0;
  79. if (usage != null) {
  80. int size = 0;
  81. int as = 0;
  82. for (int i = 0; i < usage.length; i++)
  83. if (meshToCopy.getVertexAttribute(usage[i]) != null) {
  84. size += meshToCopy.getVertexAttribute(usage[i]).numComponents;
  85. as++;
  86. }
  87. if (size > 0) {
  88. attrs = new VertexAttribute[as];
  89. checks = new short[size];
  90. int idx = -1;
  91. int ai = -1;
  92. for (int i = 0; i < usage.length; i++) {
  93. VertexAttribute a = meshToCopy.getVertexAttribute(usage[i]);
  94. if (a == null)
  95. continue;
  96. for (int j = 0; j < a.numComponents; j++)
  97. checks[++idx] = (short)(a.offset/4 + j);
  98. attrs[++ai] = new VertexAttribute(a.usage,a.numComponents,a.alias);
  99. newVertexSize += a.numComponents;
  100. }
  101. }
  102. }
  103. if (checks == null) {
  104. checks = new short[vertexSize];
  105. for (short i = 0; i < vertexSize; i++)
  106. checks[i] = i;
  107. newVertexSize = vertexSize;
  108. }
  109.  
  110. int numIndices = meshToCopy.getNumIndices();
  111. short[] indices = null;
  112. if (numIndices > 0) {
  113. indices = new short[numIndices];
  114. meshToCopy.getIndices(indices);
  115. if (removeDuplicates || newVertexSize != vertexSize) {
  116. float[] tmp = new float[vertices.length];
  117. int size = 0;
  118. for (int i = 0; i < numIndices; i++) {
  119. final int idx1 = indices[i] * vertexSize;
  120. short newIndex = -1;
  121. if (removeDuplicates) {
  122. for (short j = 0; j < size && newIndex < 0; j++) {
  123. final int idx2 = j*newVertexSize;
  124. boolean found = true;
  125. for (int k = 0; k < checks.length && found; k++) {
  126. if (tmp[idx2+k] != vertices[idx1+checks[k]])
  127. found = false;
  128. }
  129. if (found)
  130. newIndex = j;
  131. }
  132. }
  133. if (newIndex > 0)
  134. indices[i] = newIndex;
  135. else {
  136. final int idx = size * newVertexSize;
  137. for (int j = 0; j < checks.length; j++)
  138. tmp[idx+j] = vertices[idx1+checks[j]];
  139. indices[i] = (short)size;
  140. size++;
  141. }
  142. }
  143. vertices = tmp;
  144. numVertices = size;
  145. }
  146. }
  147.  
  148. Mesh result;
  149. if (attrs == null)
  150. result = new Mesh(isStatic,numVertices,indices == null ? 0 : indices.length,meshToCopy.getVertexAttributes());
  151. else
  152. result = new Mesh(isStatic,attrs);
  153. result.setVertices(vertices,numVertices * newVertexSize);
  154. result.setIndices(indices);
  155. return result;
  156. }

这对于尝试在libGDX中编写自己的3D游戏的人来说可能非常有用.没有这种机制,写出比几种型号更多的编辑是不可能的.

猜你在找的Android相关文章