2016-05-07 6 views
1

Я пытаюсь оптимизировать следующий код как цикл, который много раз, чтобы получить каждый пиксель текстуры, занимает очень много времени!Попытка оптимизировать с setpixel/getpixel

У меня есть 3 текстуры, созданные в другом месте, которые необходимо объединить, а затем сохранить на диск.

Я пробовал использовать SetPixels и GetPixels, но это не особенно полезно, поскольку использование его несколько раз просто заменяет всю текстуру, а не только заменяет непрозрачные пиксели. Ниже моя функция до сих пор:

public void savePNG() 
{ 

    stationWidth = PlayerPrefs.GetInt("Station Width"); 
    stationHeight = PlayerPrefs.GetInt("Station Height"); 

    Debug.Log(stationWidth + ", " + stationHeight); 

    Texture2D spaceStation = new Texture2D(stationWidth*256, stationHeight*256, TextureFormat.ARGB32, false); 
    spaceStation = new Texture2D(stationWidth*256, stationHeight*256, TextureFormat.ARGB32, false); 

    Color Test; 

    floorTex = new Texture2D(stationWidth*256, stationHeight*256, TextureFormat.ARGB32, false); 
    wallTex = new Texture2D(stationWidth*256, stationHeight*256, TextureFormat.ARGB32, false); 
    roomTex = new Texture2D(stationWidth*256, stationHeight*256, TextureFormat.ARGB32, false); 

    floorTex.LoadImage(File.ReadAllBytes(Application.dataPath + "/../floorTexture.png"), false); 
    wallTex.LoadImage(File.ReadAllBytes(Application.dataPath + "/../wallTexture.png"), false); 
    roomTex.LoadImage(File.ReadAllBytes(Application.dataPath + "/../roomTexture.png"), false); 


    for(int row = 0; row < stationWidth*256; row ++) 
    { 
     for(int col = 0; col < stationHeight*256; col ++) 
     { 

      Test = floorTex.GetPixel(row,col); 

      if(Test.a != 0.0f) 
      { 
       spaceStation.SetPixel(row, col, floorTex.GetPixel(row,col)); 
      } 
      else 
      { 
       spaceStation.SetPixel(row, col, Color.white); 
      } 

      Test = wallTex.GetPixel(row,col); 

      if(Test.a != 0.0f) 
      { 
       spaceStation.SetPixel(row, col, wallTex.GetPixel(row,col)); 
      } 

      Test = roomTex.GetPixel(row,col); 

      if(Test.a != 0.0f) 
      { 
       spaceStation.SetPixel(row, col, roomTex.GetPixel(row,col)); 
      } 

     } 
    } 

    spaceStation.Apply(); 

    byte[] bytes = spaceStation.EncodeToPNG(); 
    File.WriteAllBytes(Application.dataPath + "/../SpaceStation.png", bytes); 

} 

Я не уверен, куда идти отсюда, любые идеи или предложения будут высоко оценены!

Дополнительная

GetPixels и SetPixels код, который я пробовал выглядел следующим образом:

spaceStation.SetPixels(floorTex.GetPixels(0, 0, stationWidth*256, stationHeight*256)); 
    spaceStation.SetPixels(wallTex.GetPixels(0 ,0, stationWidth*256, stationHeight*256)); 
    spaceStation.SetPixels(roomTex.GetPixels(0, 0, stationWidth*256, stationHeight*256)); 

Каждый SetPixels полностью переписал предыдущие, где я хотел бы прозрачные пиксели, чтобы не перезаписать любой пиксель на всех поэтому подробности будут отображаться через

+0

'GetPixels' и' SetPixels' способны на любой эффект. Покажите код, который использует их, и вызывает проблемы. –

+0

добавил код 'SetPixels', который не работал для меня –

+1

Ahh ну, вам все равно нужно запустить свой алгоритм. Если вы просто хотите рисовать с прозрачностью, для этого должна быть функция. Для других эффектов, петля над массивом, возвращаемым из 'GetPixels', каждый раз меняйте массив по одному пикселю, затем применяйте все сразу, используя' SetPixels'. –

ответ

-1

Я действительно не знаю производительность (get/set) Пиксельные методы объекта Texture2D. Но в мире .NET мы предпочитаем классы System.Drawing.Bitmap и System.Drawing.Imaging.BitmapData и свойство Scan0 BitmapData для быстрого доступа к значениям пикселей.

Там уже есть красивый answer, данный там в SO, который демонстрирует использование.

+0

, но, к сожалению, если я правильно помню, Unity не имеет System.Drawing вообще! –

0

Я использовал цветные массивы вместо установки каждого пикселя в отдельности, только один раз вызывал GetPixels и SetPixels один раз. Функция теперь примерно на 80% быстрее, что довольно прилично. Мне сказали, что я могу получить еще лучшие результаты, используя Graphics.Blit и шейдер, но я действительно ничего не знаю о шейдерах, поэтому я не буду принимать этот подход на данный момент. Вот как выглядит код:

public void savePNG() 
{ 
    stationWidth = PlayerPrefs.GetInt("Station Width"); 
    stationHeight = PlayerPrefs.GetInt("Station Height"); 

    Texture2D spaceStation = new Texture2D(stationWidth*256, stationHeight*256, TextureFormat.ARGB32, false); 
    spaceStation = new Texture2D(stationWidth*256, stationHeight*256, TextureFormat.ARGB32, false); 

    Color[] mainArray = new Color[(stationWidth*256)*(stationHeight*256)]; 
    Color[] wallArray = new Color[(stationWidth*256)*(stationHeight*256)]; 
    Color[] roomArray = new Color[(stationWidth*256)*(stationHeight*256)]; 

    floorTex = new Texture2D(stationWidth*256, stationHeight*256, TextureFormat.ARGB32, false); 
    wallTex = new Texture2D(stationWidth*256, stationHeight*256, TextureFormat.ARGB32, false); 
    roomTex = new Texture2D(stationWidth*256, stationHeight*256, TextureFormat.ARGB32, false); 

    floorTex.LoadImage(File.ReadAllBytes(Application.dataPath + "/../floorTexture.png"), false); 
    wallTex.LoadImage(File.ReadAllBytes(Application.dataPath + "/../wallTexture.png"), false); 
    roomTex.LoadImage(File.ReadAllBytes(Application.dataPath + "/../roomTexture.png"), false); 


    mainArray = floorTex.GetPixels(0,0,stationWidth*256, stationHeight*256); 
    wallArray = wallTex.GetPixels(0,0,stationWidth*256, stationHeight*256); 
    roomArray = roomTex.GetPixels(0,0,stationWidth*256, stationHeight*256); 

    for(int i = 0; i < mainArray.Length; i++) 
    { 
     if(wallArray[i].a != 0.0f) 
     { 
      mainArray[i] = wallArray[i]; 
     } 
     if(roomArray[i].a != 0.0f) 
     { 
      mainArray[i] = roomArray[i]; 
     } 
    } 

    spaceStation.SetPixels(mainArray); 

    spaceStation.Apply(); 

    byte[] bytes = spaceStation.EncodeToPNG(); 
    File.WriteAllBytes(Application.dataPath + "/../SpaceStation.png", bytes); 

}