Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • 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 /
This post has been wikified, any user with enough reputation can edit it.
avatar image
1
Question by Major · May 02, 2015 at 05:12 AM · texture2dimagedynamicsetpixelssetpixel

Best Method for Setting Mass Numbers of Pixels (SetPixel, SetPixels)

I have been trying to fill the entire background of an image with just a single color, but the only way I can get it to work is through 2 for loops setting the x y coordinators and then setting the color. Naturally this is horrendously inefficient but I don't know how else to do it. Any guidance on this topic would be very helpful. Thanks!

Comment
Add comment · Show 1
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 roddles · May 11, 2015 at 11:15 PM 0
Share

Now that you have a solution for this, let me put in a caveat. There aren't many "good" reasons to use a single-color texture in a material ins$$anonymous$$d of using a material with the same albedo/diffuse color.

That said, I can think of a few reasons why you might choose to go the texture-route (like profiling draw performance before texture assets are available), but if you don't have a good reason you're using textures, I'd recommend achieving single-colored objects with textureless materials ins$$anonymous$$d. For one, it is easier to change an objects color in Unity's Editor, and it will incur even less processing overhead.

2 Replies

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

Answer by roddles · May 04, 2015 at 09:32 AM

Using Texture2D.SetPixels32 is definitely the way to go. The question of how to quickly create an array or list with a single value is still valid. Assuming you are using C# and not JavaScript, Enumerable.Repeat is efficient at making an array a specific value. You could do something like this:

 using UnityEngine;
 using System.Linq;
 
 public class MyClass {
     public void CreateTexture(Texture2D texture, int width, int height, Color32 color) {
         Color32[] newColors = Enumerable.Repeat(color, width * height).ToArray ();
         texture.SetPixels32 (newColors);
     }
 }

EDIT:

Here's the method using a simple array, since – as bunny83 pointed out – the Enumerable ToArray() technique has additional overhead and excess garbage creation.

 public void CreateTexture(Texture2D texture, int width, int height, Color32 color) {
      Color32[] newColors = new Color32[width * height];
      foreach (Color32 colorElement in newColors {
          colorElement = color;
      }
      texture.SetPixels32 (newColors);
  }


Comment
Add comment · Show 5 · 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 Major · May 11, 2015 at 04:04 AM 0
Share

wow. Before I could only do 32 X 32 texures, now like 512 X 512 with a stable frame rate. And all of that 6 times over. Thanks!

avatar image Major · May 12, 2015 at 03:01 AM 0
Share

I am actually trying to create a procedural skybox based on scene objects, and all of that. The solution must not be based on camera render distance. The whole idea is around the idea that when you move through the universe, the skybox changes at the same time. But I was having trouble getting setpixels to work. Under any other circumstance I would use a material with a solid color, but it just wouldn't work the way I want it to. It would still involve this kind of process.

avatar image Bunny83 · May 12, 2015 at 03:40 AM 1
Share

"Enumerable.Repeat is efficient" is simply not true ^^ It's actually the opposite. It's just a nice short one-liner but is very inefficient:

  • Enumerable.Repeat returns an IEnumerable and therefore creates an unnecessary object. (That's not too bad).

  • Since IEnumerable doesn't have a size the ToArray method has to iterate the IEnumerable and "collect" all items. This is done the same way a generic List works. It first creates an array with 4 elements and fills item after item. Once the array is to small it creates a new array and doubles the size. So the new array has 8 items. Once it's full again it does the same again 16->32->64 .... Each time a new array is created all elements from the old array are copied into the new one. So for an array with 512*512 elements it has to create a new array 16 times. This generates huge amount of garbage.

  • ToArray uses a Buffer object internally. Once the array is done it again creates a new array with the actual needed size and once more copies all elements over.

  • Each time you want such an initialized array this method creates a new array which actually isn't necessary. If you want to change the array frequently you shouldn't create a new array each time but reuse the old one.

two nested for loops that initialize an array is way more efficient in the sense of speed and being memory friendly

@$$anonymous$$ajor:
"Naturally this is horrendously inefficient" how did you come to this conclusion? If you have n elements of an array you want to set to a specific value there's no way around setting each element to that value which you usually do in a loop. If all should have the same value you don't need two nested loops but it actually makes almost no difference.

Don't get me wrong: Using SetPixel is slow as hell. You should always use SetPixels or SetPixels32 and work with an array. But to initialize the array you really should use a loop and not Enumerable.Repeat

avatar image roddles · May 12, 2015 at 03:57 AM 1
Share

@Bunny83 Good to know. $$anonymous$$y knowledge of C# internals is woefully incomplete. Also, since it's a single color and row/columns don't matter, a single loop with width * height elements is fine.

 public void CreateTexture(Texture2D texture, int width, int height, Color32 color) {
     Color32[] newColors = new Color32[width * height];
     foreach (Color32 colorElement in newColors {
         colorElement = color;
     }
     texture.SetPixels32 (newColors);
 }
avatar image Major · May 12, 2015 at 10:14 PM 0
Share

@Bunny83 I was referring to using setpixel. Actually now that I have been tweaking things it comes to more of setting the values in an array in Awake, and then setting them later in update with setpixels.

avatar image
1
Wiki

Answer by Sessional · May 02, 2015 at 03:18 PM

I find SetPixels is actually pretty quick. When I was browsing the Docs they suggested using Color32 where possible to avoid something (I don't remember quite what, probably something with the float to byte conversion?)

Here's a snippet of what I do:

 if (inputModule != null)
         {
             module = new Clamp(minimum, maximum, inputModule[0]);
             colors = new Color32[example.width * example.height];
             for (int texX = 0; texX < example.width; texX++)
             {
                 for (int texY = 0; texY < example.height; texY++)
                 {
                     double value = (module.GetValue(texX, texY, 10) + -inputNodes[0].outputMin) / (inputNodes[0].outputMax - inputNodes[0].outputMin);
                     if (value < 0.0) value = 0.0;
                     if (value > 1.0) value = 1.0;
 
                     byte colorValue = (byte)(value * 255);
 
                     colors[texY * example.width + texX] = new Color32(colorValue, colorValue, colorValue, 255);
                 }
             }
 
             example.SetPixels32(colors);
             example.Apply();
         }

This is for a 200x200 example texture that I refresh on button click, which actually refreshes quick enough you don't realize it didn't refresh. (This is also an OnGUI method so I have a little bit of forgiveness on speed I guess?)

A quick google also says it's not really possible to set the default value that the array will initialize to without a loop.

If you find the loop is not quick enough you can also create default textures with the background colors already set that you use to generate on top of for whatever you need.

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

22 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

Related Questions

For different texture sizes, which is faster? SetPixel or SetPixels? 2 Answers

Fastest rendering of 2D world with lots of changes to screen every frame? 3 Answers

Setpixels creates gradient texture instead of raw colored pixels 1 Answer

Drawing a solid circle onto texture 2 Answers

Finding a pixel in an images texture by raycast 0 Answers


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