Grids in Unity merge with material balls

Source: Internet
Author: User

51517860

Many times we need to combine material balls with the same shader to reduce the drawcall.   

For example, in the Kowloon War, a character with 10 parts, 10 parts of each from different FBX files, plus the body, there are 11 of material balls, accounting for 11 drawcall. If there are 10 characters running in the main city, the light figure takes up 110 drawcall! So the material ball merging is necessary at this time.

(Multi-part facelift effect in Kowloon War)

Material ball Merge, divided the following steps to go, first we discuss the common meshrenderer material ball merge, and then discuss the skinnedmeshrenderer of the material ball merge.

Common meshrenderer material balls are combined:

1. Combine all the textures that the ball is carrying, create a new material ball, and assign the merged map to the new material ball.

2. Record the rect of each merged map in the new map, and save it with a rect[] array.

3. Merge the meshes and brush the Uvs of each mesh that need to be merged, according to the rect[of the 2nd step].

4. Give the new material ball to the merged mesh, and only 1 drawcall.

Here is the key code:

  1. void Combinemesh ()
  2. {
  3. meshfilter[] Mfchildren = getcomponentsinchildren<meshfilter> ();
  4. Combineinstance[] Combine = new combineinstance[mfchildren.length];
  5. meshrenderer[] Mrchildren = getcomponentsinchildren<meshrenderer> ();
  6. material[] Materials = new material[mrchildren.length];
  7. Meshrenderer mrself = gameobject.addcomponent<meshrenderer> ();
  8. Meshfilter mfself = gameobject.addcomponent<meshfilter> ();
  9. texture2d[] Textures = new texture2d[mrchildren.length];
  10. For (int i = 0; i < mrchildren.length; i++)
  11. {
  12. if (Mrchildren[i].transform = = transform)
  13. {
  14. continue;
  15. }
  16. Materials[i] = mrchildren[i].sharedmaterial;
  17. Texture2d tx = Materials[i]. GetTexture ("_maintex") as texture2d;
  18. Texture2d tx2d = new Texture2d (Tx.width, Tx.height, Textureformat.argb32, false);
  19. Tx2d.setpixels (TX. Getpixels (0, 0, Tx.width, tx.height));
  20. Tx2d.apply ();
  21. Textures[i] = tx2d;
  22. }
  23. Material materialnew = new Material (materials[0].shader);
  24. Materialnew.copypropertiesfrommaterial (materials[0]);
  25. Mrself.sharedmaterial = materialnew;
  26. Texture2d texture = new Texture2d (1024x768, 1024x768);
  27. Materialnew.settexture ("_maintex", texture);
  28. rect[] rects = texture. Packtextures (Textures, ten, 1024x768);
  29. For (int i = 0; i < mfchildren.length; i++)
  30. {
  31. if (Mfchildren[i].transform = = transform)
  32. {
  33. continue;
  34. }
  35. Rect rect = rects[i];
  36. Mesh meshcombine = Mfchildren[i].mesh;
  37. vector2[] Uvs = new Vector2[meshcombine.uv.length];
  38. //The UV of the grid is brushed over the map's rect
  39. For (int j = 0; j < Uvs. Length; J + +)
  40. {
  41. uvs[j].x = rect.x + meshcombine.uv[j].x * rect.width;
  42. UVS[J].Y = Rect.y + meshcombine.uv[j].y * rect.height;
  43. }
  44. MESHCOMBINE.UV = Uvs;
  45. Combine[i].mesh = Meshcombine;
  46. Combine[i].transform = Mfchildren[i].transform.localtoworldmatrix;
  47. Mfchildren[i].gameobject.setactive (false);
  48. }
  49. Mesh Newmesh = new Mesh ();
  50. Newmesh.combinemeshes (Combine, true,true); Merging grids
  51. Mfself.mesh = Newmesh;
  52. }

Pre-merger Drawcall:

Drawcall after merging:

Merged grid:

Merge the good stickers:

Below we will discuss the merger of Skinnedmeshrenderer.

Skinnedmeshrenderer is a little bit more troublesome than meshrenderer because skinnedmeshrenderer to deal with bones.

Here are the steps:

1. Combine all the textures that the ball is carrying, create a new material ball, and assign the merged map to the new material ball.

2. Record the rect of each merged map in the new map, and save it with a rect[] array.

3. Record the bones of the skinnedmeshrenderer that need to be merged.

4. Merge the meshes and brush the Uvs of each mesh that need to be merged, according to the rect[of the 2nd step].

5. Assign the merged grid to the new Skinnedmeshrenderer and give the new Skinnedmeshrenderer the bones recorded in the 3rd step.

6. Give the new material ball to the merged mesh, and only 1 drawcall.

The steps in the red section above are different from the meshrenderer.

Here is the key code:

  1. void Combinemesh ()
  2. {
  3. skinnedmeshrenderer[] SMRs = getcomponentsinchildren<skinnedmeshrenderer> ();
  4. Combineinstance[] Combine = new Combineinstance[smrs. Length];
  5. material[] Materials = new Material[smrs. Length];
  6. texture2d[] Textures = new Texture2d[smrs. Length];
  7. Skinnedmeshrenderer smrcombine = combinemesh.gameobject.addcomponent<skinnedmeshrenderer> ();
  8. Smrcombine.shadowcastingmode = UNITYENGINE.RENDERING.SHADOWCASTINGMODE.OFF;
  9. Smrcombine.receiveshadows = false;
  10. For (int i = 0; i < SMRs. Length; i++)
  11. {
  12. Materials[i] = smrs[i].sharedmaterial;
  13. Texture2d tx = Materials[i]. GetTexture ("_maintex") as texture2d;
  14. Texture2d tx2d = new Texture2d (Tx.width, Tx.height, Textureformat.argb32, false);
  15. Tx2d.setpixels (TX. Getpixels (0, 0, Tx.width, tx.height));
  16. Tx2d.apply ();
  17. Textures[i] = tx2d;
  18. }
  19. Material materialnew = new Material (materials[0].shader);
  20. Materialnew.copypropertiesfrommaterial (materials[0]);
  21. Texture2d texture = new Texture2d (1024x768, 1024x768);
  22. rect[] rects = texture. Packtextures (Textures, ten, 1024x768);
  23. Materialnew.settexture ("_maintex", texture);
  24. list<transform> bonetmp = new list<transform> ();
  25. For (int i = 0; i < SMRs. Length; i++)
  26. {
  27. if (Smrs[i].transform = = transform)
  28. {
  29. continue;
  30. }
  31. Rect rect = rects[i];
  32. Mesh meshcombine = Creatmeshwithmesh (Smrs[i].sharedmesh);
  33. vector2[] Uvs = new Vector2[meshcombine.uv.length];
  34. For (int j = 0; j < Uvs. Length; J + +)
  35. {
  36. uvs[j].x = rect.x + meshcombine.uv[j].x * rect.width;
  37. UVS[J].Y = Rect.y + meshcombine.uv[j].y * rect.height;
  38. }
  39. Bonetmp.addrange (Smrs[i].bones);
  40. MESHCOMBINE.UV = Uvs;
  41. Combine[i].mesh = Meshcombine;
  42. Combine[i].transform = Smrs[i].transform.localtoworldmatrix;
  43. Gameobject.destroy (Smrs[i].gameobject);
  44. }
  45. Mesh Newmesh = new Mesh ();
  46. Newmesh.combinemeshes (Combine, true, true);
  47. Smrcombine.bones = Bonetmp.toarray ();
  48. Smrcombine.rootbone = Rootbone;
  49. Smrcombine.sharedmesh = Newmesh;
  50. Smrcombine.sharedmaterial = materialnew;
  51. }
  52. mesh creatmeshwithmesh (mesh mesh)
  53. {
  54. Mesh mtmp = new Mesh ();
  55. Mtmp.vertices = mesh.vertices;
  56. Mtmp.name = Mesh.name;
  57. MTMP.UV = MESH.UV;
  58. Mtmp.uv2 = Mesh.uv2;
  59. Mtmp.uv2 = Mesh.uv2;
  60. mtmp.bindposes = mesh.bindposes;
  61. Mtmp.boneweights = mesh.boneweights;
  62. Mtmp.bounds = Mesh.bounds;
  63. Mtmp.colors = mesh.colors;
  64. Mtmp.colors32 = MESH.COLORS32;
  65. Mtmp.normals = mesh.normals;
  66. Mtmp.submeshcount = Mesh.submeshcount;
  67. Mtmp.tangents = mesh.tangents;
  68. Mtmp.triangles = Mesh.triangles;
  69. return mtmp;
  70. }

Before merging, there are two meshes, which occupy 2drawcall, respectively, the mesh and material balls of the characters and knives.



After merging, it takes only 1 drawcall, and Animationcontroller and its animations work:

Merged grid:

Merge the good stickers:

The above is the merger of mesh and material content, currently only focus on implementation, but also can be further optimized, there are the following points to note:

1. The combined material ball needs to use the same shader, if more than one material ball uses the different shader, must do the further classification processing.

2. The Read/write enable option of the texture file used for the material ball is ticked.

Project's GitHub address: Https://github.com/arBao/MeshMaterialCombine

Original articles, reproduced please specify the source: http://blog.csdn.net/dardgen2015/article/details/51517860

Grids in Unity merge with material balls

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.