• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Double-V · Jul 31, 2020 at 07:27 PM · performanceoptimizationtexture2d

Is operating using GetRawTextureData faster that doing SetPixel/Pixels?

I'm writing a Texture2D manipulation script and I wonder if switching the way of doing thins would make it faster - does using the NativeArray that you get from GetRawTextureData give a performance advantage vs just Getting and Setting pixels?

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by Kaart · Jul 31, 2020 at 10:50 PM

I was curious myself and wrote a small program to test this. While I'm not really familiar with RawTextureData it doesn't seem to be much slower or faster than Texture2D.GetPixels() and Texture2D.SetPixels(). However Texture2D.GetPixel(x,y) and Texture2D.SetPixel(x, y) is much slower when you need to manipulate multiple pixels.

I used a 1000x1000 .png image to test with the following import settings: alt text

I did a few runs and this would be a typical result: alt text

I've included the script I used if you want to do further testing, I'm really interested in your results. using System.Diagnostics; using UnityEngine;

 public class Example : MonoBehaviour
 {
     [SerializeField]
     private Texture2D _image;
 
     private Stopwatch _stopwatch = new Stopwatch();
 
     // Start is called before the first frame update
     void Start()
     {
         if (_image != null)
         {
             TestGetSetPixel();
             TestGetSetPixels();
             TestRawTextureData();
         }
     }
 
     private void TestGetSetPixel()
     {
         _stopwatch.Start();
 
         for (int y = 0; y < _image.height; y++)
         {
             for (int x = 0; x < _image.width; x++)
             {
                 Color color = _image.GetPixel(x, y);
 
                 // Do something fancy with the color value.        
                 color = new Color(0f, 0f, 0f);
                 _image.SetPixel(x, y, color);
             }
         }
 
         _stopwatch.Stop();
         UnityEngine.Debug.Log("TestGetSetPixel took: " + _stopwatch.ElapsedMilliseconds + " milliseconds to complete.");
         _stopwatch.Reset();
     }
 
     private void TestGetSetPixels()
     {
         _stopwatch.Start();
         Color[] colors = _image.GetPixels();
 
         for (int i = 0; i < colors.Length; i++)
         {
             // Do something fancy with the color value.            
             colors[i] = new Color(0f, 0f, 0f);
         }
         _image.SetPixels(colors);
 
         _stopwatch.Stop();
         UnityEngine.Debug.Log("TestGetSetPixels took: " + _stopwatch.ElapsedMilliseconds + " milliseconds to complete.");
         _stopwatch.Reset();
     }
 
     private void TestRawTextureData()
     {
         _stopwatch.Start();
         Unity.Collections.NativeArray<Color32> colors = _image.GetRawTextureData<Color32>();
 
         for (int i = 0; i < colors.Length; i++)
         {
             colors[i] = new Color32(0, 0, 0, 255);
         }
         _image.Apply();
 
         _stopwatch.Stop();
         UnityEngine.Debug.Log("TestRawTextureData took: " + _stopwatch.ElapsedMilliseconds + " to complete.");
         _stopwatch.Reset();
     }
 }
 

square1000.png (35.8 kB)
result.png (15.2 kB)
Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Double-V · Aug 01, 2020 at 12:23 PM 0
Share

So in my implementation I'm blurring an image, so I do need to make changes per individual pixel and it turns out that yes, when there are hundreds/thousands of those then setting individual bytes in the NativeArray is faster than doing GetPixel, SetPixel. In my case I had a texture with TextureFormat.RGB24, which means there are 3 array elements per color, but I think it would still be faster even with RGB32.

The exact values probably have a lot to do with other stuff in the implementation, but the SetPixel GetPixel one took around 3050ms on a 1600x800 texture and around 2000ms with GetRawTextureData(), with the same resolution and other settings of the blur.

avatar image Kaart Double-V · Aug 01, 2020 at 03:32 PM 1
Share

Please note there is a difference between Texture2D.GetPixel()/SetPixel() and Texture2D.GetPixels()/SetPixels(). The later uses a Color array which is much faster than getting and setting each individual pixel colors using GetPixel()/SetPixel().

avatar image
0

Answer by joshrs926 · Feb 07 at 07:43 PM

Yes it can be a lot faster depending on a few things. First you need to know exactly what format Unity has stored the pixels. For example they might be stored as RGBA32 which means each pixel is 4 bytes, 1 byte per channel or it might be stored as RGB24 which is similar but without the alpha so it is 3 bytes per pixel. Also you'd be getting/setting bytes not floats so a float value of .5f would probably be rougly a byte value of 128. You'd have to do that conversion. Using GetRawTextureData I think will also avoid some copying of data back and forth. The big speedup up you can get is using the Job system with burst and multithreading to manipulate that data. You have to provide a job with a NativeArray (or some other Native Collection). If you aren't sure about the data format you could actually use GetPixels to get a Color[] and then create a NativeArray from it and give that to the job too. This would involve multiply copies but might be faster than manipulating the data outside a bursted job. Coverting code to Bursted Jobs can give orders of magnitude speed ups.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

161 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How Can I Reduce Build Time for Script-Heavy Projects? 2 Answers

How to optimize with a lot of objects 0 Answers

A very simple optimization question, particle 1 Answer

Double Buffer and/or Mesh.MarkDynamic in Unity 5 0 Answers

What's faster: Lerp or LerpUnclamped? (Performance) 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges