Если вы заботитесь о производительности, объединяйте меши

Программирование на Юнити.

Если вы заботитесь о производительности, объединяйте меши

Сообщение Sef 15 дек 2009, 16:56

Это кусок из справки:
http://docs.unity3d.ru/Manual/Optimizin ... mance.html

А как это делать и где? Просто у меня уровень собирается из разных кубиков и будет много Draw Call.
Надо бы вот как на скрине с форума:
Изображение
http://forum.unity3d.com/viewtopic.php? ... es&start=0
Аватара пользователя
Sef
Старожил
 
Сообщения: 595
Зарегистрирован: 29 окт 2009, 13:24
  • ICQ

Re: Если вы заботитесь о производительности, объединяйте меши

Сообщение eureka3D 15 дек 2009, 17:07

в Максе (max_sm) выделяется один Editable Mesh и кнопкой attach - привязываются другие Мешы. По крайней мере я так делал, только с материалами не напутайте. Я присваивал Multi-Sub материал для всего окончательного меша и назначал по полигонам разные материалы.
Аватара пользователя
eureka3D
UNец
 
Сообщения: 36
Зарегистрирован: 02 июн 2009, 11:39

Re: Если вы заботитесь о производительности, объединяйте меши

Сообщение Sef 15 дек 2009, 17:17

В макс не то... планируется что уровни будут собираться в едиторе юнити.
Дали ссылку, пока пробую:
http://unity3d.com/support/documentatio ... eshes.html
Аватара пользователя
Sef
Старожил
 
Сообщения: 595
Зарегистрирован: 29 окт 2009, 13:24
  • ICQ

Re: Если вы заботитесь о производительности, объединяйте меши

Сообщение Sef 15 дек 2009, 21:54

Пока не получается, может ещё что-то посоветуете, или направите? ;)
Аватара пользователя
Sef
Старожил
 
Сообщения: 595
Зарегистрирован: 29 окт 2009, 13:24
  • ICQ

Re: Если вы заботитесь о производительности, объединяйте меши

Сообщение Kann 15 дек 2009, 22:06

Ссылку правильно дали, что не получается ?
вот почитайте эту тему.
viewtopic.php?f=65&t=703
Kann
Старожил
 
Сообщения: 553
Зарегистрирован: 05 ноя 2009, 14:06

Re: Если вы заботитесь о производительности, объединяйте меши

Сообщение Sef 15 дек 2009, 22:26

Kann писал(а):Ссылку правильно дали, что не получается ?
вот почитайте эту тему.
viewtopic.php?f=65&t=703

Тот код глючит как на джаве, так и на шарп перевести ума не хватило :)
А по той ссылки увидел:
3. использовать скрипт из острова демки(что с проектом) combinechildrens.

Пошёл смотреть что там...
Аватара пользователя
Sef
Старожил
 
Сообщения: 595
Зарегистрирован: 29 окт 2009, 13:24
  • ICQ

Re: Если вы заботитесь о производительности, объединяйте меши

Сообщение Sef 15 дек 2009, 22:51

Получилось. А здоровенький такой скрипт(ы) :)
Кстати, а можно как-то в один DC сотню не статических 3Д объектов засунуть?
Аватара пользователя
Sef
Старожил
 
Сообщения: 595
Зарегистрирован: 29 окт 2009, 13:24
  • ICQ

Re: Если вы заботитесь о производительности, объединяйте меши

Сообщение Neodrop 15 дек 2009, 23:26

Кстати, у меня тоже не вышло с первого подхода. Справка в этом месте хуже худшего.
Если есть рабочий скрипт, буду признателен. То, что по ссылкам - палево нерабочее. :-?
Добавить neodrop в Skype
Изображение
"Спасибо!" нашему порталу, вы сможете сказать ЗДЕСЬ.
Если проблема не решается честно, нужно её обмануть! || Per stupiditas at Astra!
Страх порождает слабость. Бесстрашных поражают пули.
Протратившись на блядях байтах, на битах не экономят.
Аватара пользователя
Neodrop
Админ
 
Сообщения: 8480
Зарегистрирован: 08 окт 2008, 15:42
Откуда: Питер
Skype: neodrop
  • Сайт

Re: Если вы заботитесь о производительности, объединяйте меши

Сообщение Sef 16 дек 2009, 00:13

Это из острова:

CombineChildren.cs
Код: Выделить всё
using UnityEngine;
using System.Collections;
/*
Attach this script as a parent to some game objects. The script will then combine the meshes at startup.
This is useful as a performance optimization since it is faster to render one big mesh than many small meshes. See the docs on graphics performance optimization for more info.

Different materials will cause multiple meshes to be created, thus it is useful to share as many textures/material as you can.
*/

[AddComponentMenu("Mesh/Combine Children")]
public class CombineChildren : MonoBehaviour {
   
   /// Usually rendering with triangle strips is faster.
   /// However when combining objects with very low triangle counts, it can be faster to use triangles.
   /// Best is to try out which value is faster in practice.
   public bool generateTriangleStrips = true;
   
   /// This option has a far longer preprocessing time at startup but leads to better runtime performance.
   void Start () {
      Component[] filters  = GetComponentsInChildren(typeof(MeshFilter));
      Matrix4x4 myTransform = transform.worldToLocalMatrix;
      Hashtable materialToMesh= new Hashtable();
      
      for (int i=0;i<filters.Length;i++) {
         MeshFilter filter = (MeshFilter)filters[i];
         Renderer curRenderer  = filters[i].renderer;
         MeshCombineUtility.MeshInstance instance = new MeshCombineUtility.MeshInstance ();
         instance.mesh = filter.sharedMesh;
         if (curRenderer != null && curRenderer.enabled && instance.mesh != null) {
            instance.transform = myTransform * filter.transform.localToWorldMatrix;
            
            Material[] materials = curRenderer.sharedMaterials;
            for (int m=0;m<materials.Length;m++) {
               instance.subMeshIndex = System.Math.Min(m, instance.mesh.subMeshCount - 1);
   
               ArrayList objects = (ArrayList)materialToMesh[materials[m]];
               if (objects != null) {
                  objects.Add(instance);
               }
               else
               {
                  objects = new ArrayList ();
                  objects.Add(instance);
                  materialToMesh.Add(materials[m], objects);
               }
            }
            
            curRenderer.enabled = false;
         }
      }
   
      foreach (DictionaryEntry de  in materialToMesh) {
         ArrayList elements = (ArrayList)de.Value;
         MeshCombineUtility.MeshInstance[] instances = (MeshCombineUtility.MeshInstance[])elements.ToArray(typeof(MeshCombineUtility.MeshInstance));

         // We have a maximum of one material, so just attach the mesh to our own game object
         if (materialToMesh.Count == 1)
         {
            // Make sure we have a mesh filter & renderer
            if (GetComponent(typeof(MeshFilter)) == null)
               gameObject.AddComponent(typeof(MeshFilter));
            if (!GetComponent("MeshRenderer"))
               gameObject.AddComponent("MeshRenderer");
   
            MeshFilter filter = (MeshFilter)GetComponent(typeof(MeshFilter));
            filter.mesh = MeshCombineUtility.Combine(instances, generateTriangleStrips);
            renderer.material = (Material)de.Key;
            renderer.enabled = true;
         }
         // We have multiple materials to take care of, build one mesh / gameobject for each material
         // and parent it to this object
         else
         {
            GameObject go = new GameObject("Combined mesh");
            go.transform.parent = transform;
            go.transform.localScale = Vector3.one;
            go.transform.localRotation = Quaternion.identity;
            go.transform.localPosition = Vector3.zero;
            go.AddComponent(typeof(MeshFilter));
            go.AddComponent("MeshRenderer");
            go.renderer.material = (Material)de.Key;
            MeshFilter filter = (MeshFilter)go.GetComponent(typeof(MeshFilter));
            filter.mesh = MeshCombineUtility.Combine(instances, generateTriangleStrips);
         }
      }   
   }   
}


MeshCombineUtility.cs
Код: Выделить всё
using UnityEngine;
using System.Collections;

public class MeshCombineUtility {
   
   public struct MeshInstance
   {
      public Mesh      mesh;
      public int       subMeshIndex;           
      public Matrix4x4 transform;
   }
   
   public static Mesh Combine (MeshInstance[] combines, bool generateStrips)
   {
      int vertexCount = 0;
      int triangleCount = 0;
      int stripCount = 0;
      foreach( MeshInstance combine in combines )
      {
         if (combine.mesh)
         {
            vertexCount += combine.mesh.vertexCount;
            
            if (generateStrips)
            {
               // SUBOPTIMAL FOR PERFORMANCE
               int curStripCount = combine.mesh.GetTriangleStrip(combine.subMeshIndex).Length;
               if (curStripCount != 0)
               {
                  if( stripCount != 0 )
                  {
                     if ((stripCount & 1) == 1 )
                        stripCount += 3;
                     else
                        stripCount += 2;
                  }
                  stripCount += curStripCount;
               }
               else
               {
                  generateStrips = false;
               }
            }
         }
      }
      
      // Precomputed how many triangles we need instead
      if (!generateStrips)
      {
         foreach( MeshInstance combine in combines )
         {
            if (combine.mesh)
            {
               triangleCount += combine.mesh.GetTriangles(combine.subMeshIndex).Length;
            }
         }
      }
      
      Vector3[] vertices = new Vector3[vertexCount] ;
      Vector3[] normals = new Vector3[vertexCount] ;
      Vector4[] tangents = new Vector4[vertexCount] ;
      Vector2[] uv = new Vector2[vertexCount];
      Vector2[] uv1 = new Vector2[vertexCount];
      int[] triangles = new int[triangleCount];
      int[] strip = new int[stripCount];
      
      int offset;
      
      offset=0;
      foreach( MeshInstance combine in combines )
      {
         if (combine.mesh)
            Copy(combine.mesh.vertexCount, combine.mesh.vertices, vertices, ref offset, combine.transform);
      }

      offset=0;
      foreach( MeshInstance combine in combines )
      {
         if (combine.mesh)
         {
            Matrix4x4 invTranspose = combine.transform;
            invTranspose = invTranspose.inverse.transpose;
            CopyNormal(combine.mesh.vertexCount, combine.mesh.normals, normals, ref offset, invTranspose);
         }
            
      }
      offset=0;
      foreach( MeshInstance combine in combines )
      {
         if (combine.mesh)
         {
            Matrix4x4 invTranspose = combine.transform;
            invTranspose = invTranspose.inverse.transpose;
            CopyTangents(combine.mesh.vertexCount, combine.mesh.tangents, tangents, ref offset, invTranspose);
         }
            
      }
      offset=0;
      foreach( MeshInstance combine in combines )
      {
         if (combine.mesh)
            Copy(combine.mesh.vertexCount, combine.mesh.uv, uv, ref offset);
      }
      
      offset=0;
      foreach( MeshInstance combine in combines )
      {
         if (combine.mesh)
            Copy(combine.mesh.vertexCount, combine.mesh.uv1, uv1, ref offset);
      }
      
      int triangleOffset=0;
      int stripOffset=0;
      int vertexOffset=0;
      foreach( MeshInstance combine in combines )
      {
         if (combine.mesh)
         {
            if (generateStrips)
            {
               int[] inputstrip = combine.mesh.GetTriangleStrip(combine.subMeshIndex);
               if (stripOffset != 0)
               {
                  if ((stripOffset & 1) == 1)
                  {
                     strip[stripOffset+0] = strip[stripOffset-1];
                     strip[stripOffset+1] = inputstrip[0] + vertexOffset;
                     strip[stripOffset+2] = inputstrip[0] + vertexOffset;
                     stripOffset+=3;
                  }
                  else
                  {
                     strip[stripOffset+0] = strip[stripOffset-1];
                     strip[stripOffset+1] = inputstrip[0] + vertexOffset;
                     stripOffset+=2;
                  }
               }
               
               for (int i=0;i<inputstrip.Length;i++)
               {
                  strip[i+stripOffset] = inputstrip[i] + vertexOffset;
               }
               stripOffset += inputstrip.Length;
            }
            else
            {
               int[]  inputtriangles = combine.mesh.GetTriangles(combine.subMeshIndex);
               for (int i=0;i<inputtriangles.Length;i++)
               {
                  triangles[i+triangleOffset] = inputtriangles[i] + vertexOffset;
               }
               triangleOffset += inputtriangles.Length;
            }
            
            vertexOffset += combine.mesh.vertexCount;
         }
      }
      
      Mesh mesh = new Mesh();
      mesh.name = "Combined Mesh";
      mesh.vertices = vertices;
      mesh.normals = normals;
      mesh.tangents = tangents;
      mesh.uv = uv;
      mesh.uv1 = uv1;
      if (generateStrips)
         mesh.SetTriangleStrip(strip, 0);
      else
         mesh.triangles = triangles;
      
      return mesh;
   }
   
   static void Copy (int vertexcount, Vector3[] src, Vector3[] dst, ref int offset, Matrix4x4 transform)
   {
      for (int i=0;i<src.Length;i++)
         dst[i+offset] = transform.MultiplyPoint(src[i]);
      offset += vertexcount;
   }

   static void CopyNormal (int vertexcount, Vector3[] src, Vector3[] dst, ref int offset, Matrix4x4 transform)
   {
      for (int i=0;i<src.Length;i++)
         dst[i+offset] = transform.MultiplyVector(src[i]).normalized;
      offset += vertexcount;
   }

   static void Copy (int vertexcount, Vector2[] src, Vector2[] dst, ref int offset)
   {
      for (int i=0;i<src.Length;i++)
         dst[i+offset] = src[i];
      offset += vertexcount;
   }

   static void CopyTangents (int vertexcount, Vector4[] src, Vector4[] dst, ref int offset, Matrix4x4 transform)
   {
      for (int i=0;i<src.Length;i++)
      {
         Vector4 p4 = src[i];
         Vector3 p = new Vector3(p4.x, p4.y, p4.z);
         p = transform.MultiplyVector(p);
         dst[i+offset] = new Vector4(p.x, p.y, p.z, p4.w);
      }
         
      offset += vertexcount;
   }
}


Тут лишнего много?
Аватара пользователя
Sef
Старожил
 
Сообщения: 595
Зарегистрирован: 29 окт 2009, 13:24
  • ICQ

Re: Если вы заботитесь о производительности, объединяйте меши

Сообщение Kann 16 дек 2009, 01:19

мдя... не думал что в документации могет быть не рабочее.... 8()
вот накопал на форуме....
Код: Выделить всё
// This script should be put on an empty GameObject
// Objects to be combined should be children of the empty GameObject
@script RequireComponent(MeshFilter)
@script RequireComponent(MeshRenderer)

function Start () {
   for (var child in transform)
      child.position += transform.position;
   transform.position = Vector3.zero;
   transform.rotation = Quaternion.identity;
   
   var meshFilters = GetComponentsInChildren(MeshFilter);
   var combine : CombineInstance[] = new CombineInstance[meshFilters.Length-1];
   var index = 0;
   for (var i = 0; i < meshFilters.Length; i++)
   {
      if (meshFilters[i].sharedMesh == null) continue;
      combine[index].mesh = meshFilters[i].sharedMesh;
      combine[index++].transform = meshFilters[i].transform.localToWorldMatrix;
      meshFilters[i].renderer.enabled = false;
   }
   GetComponent(MeshFilter).mesh = new Mesh();
   GetComponent(MeshFilter).mesh.CombineMeshes (combine);
   renderer.material = meshFilters[0].renderer.sharedMaterial;
}
Kann
Старожил
 
Сообщения: 553
Зарегистрирован: 05 ноя 2009, 14:06

Re: Если вы заботитесь о производительности, объединяйте меши

Сообщение Neodrop 16 дек 2009, 01:32

Остров сильно устарел.
Вариант от Канна (не проверил) куда короче.
З. Ы. Старый вариант я сам использую успешно.
Добавить neodrop в Skype
Изображение
"Спасибо!" нашему порталу, вы сможете сказать ЗДЕСЬ.
Если проблема не решается честно, нужно её обмануть! || Per stupiditas at Astra!
Страх порождает слабость. Бесстрашных поражают пули.
Протратившись на блядях байтах, на битах не экономят.
Аватара пользователя
Neodrop
Админ
 
Сообщения: 8480
Зарегистрирован: 08 окт 2008, 15:42
Откуда: Питер
Skype: neodrop
  • Сайт

Re: Если вы заботитесь о производительности, объединяйте меши

Сообщение Sef 16 дек 2009, 14:49

Вариант от Канна не работает... если я его правильно применил...
Аватара пользователя
Sef
Старожил
 
Сообщения: 595
Зарегистрирован: 29 окт 2009, 13:24
  • ICQ

Re: Если вы заботитесь о производительности, объединяйте меши

Сообщение Kann 16 дек 2009, 14:58

Он работает, но не так как скрипт из демки с островом, создайте пустой GameObject на него вешается скрипт, приатачте к GameObject несколько кубиков, и получите 1 DrawCalls. этот скрипт что я привел, как исправление багов в документации, но его нужно допиливать под себя.
Kann
Старожил
 
Сообщения: 553
Зарегистрирован: 05 ноя 2009, 14:06

Re: Если вы заботитесь о производительности, объединяйте меши

Сообщение Neodrop 16 дек 2009, 15:19

Родной скрипт из 2.1 работает точно так же. Так что это какие то яйца в профиль. :-?
Добавить neodrop в Skype
Изображение
"Спасибо!" нашему порталу, вы сможете сказать ЗДЕСЬ.
Если проблема не решается честно, нужно её обмануть! || Per stupiditas at Astra!
Страх порождает слабость. Бесстрашных поражают пули.
Протратившись на блядях байтах, на битах не экономят.
Аватара пользователя
Neodrop
Админ
 
Сообщения: 8480
Зарегистрирован: 08 окт 2008, 15:42
Откуда: Питер
Skype: neodrop
  • Сайт

Re: Если вы заботитесь о производительности, объединяйте меши

Сообщение Kann 16 дек 2009, 15:30

ну я же не пишу что это новое решение ? я имел в виду что это то что народ выложил на офф форуме в замен на вопрос,(какого хрена не работает скрипт из документации ?) этот скрипт вполне себе может выполнять те функции которые требовались в первом посте и демонстрируются на скриншоте, все недостающее надо допиливать....
Kann
Старожил
 
Сообщения: 553
Зарегистрирован: 05 ноя 2009, 14:06

След.

Вернуться в Скрипты

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 6