Unity3d Split Texture2d at runtime - unity3d

I am creating a mobile painting application. I have two textures (Texture2D), which is a template of an image and a color map for it.
This color map contains a unique color for each region of the template where the player can draw.
I need to have several other textures, one texture per each unique color in the color map.
For now I am trying to use GetPixels for the color map, and using a dictionary, I check every pixel.
If there is no color as a key value in this dictionary, create a new texture with SetPixel using the coordinate
If there is a color as a key, get the texture by using the key and SetPixel with the coordinates to get this texture.
But when I run this even my computer begins to extremely lag, no word about mobiles.
Is there a more efficent way?
To help you visualize the issue I am adding the color map, the texture I need to split.

I don't see a magically fast way to do it, but here are a few tips that may help:
Try using GetPixels32 (and SetPixels32) instead of simply GetPixels - the return value is not Color but Color32 which uses bytes and not floating points, it should be faster. See http://docs.unity3d.com/ScriptReference/Texture2D.SetPixels32.html http://docs.unity3d.com/ScriptReference/Texture2D.GetPixels32.html
Do not call SetPixel for each pixel, this is really slow. Instead, for each color create a temporary Color32 array and work with it, and only at the end assign all the arrays to new textures using SetPixels32.
If you use foreach loop or Array.ForEach or some linq stuff to parse the colors array, don't do it - use simple for loop, it is the fastest way.
Hope this helps.

Now there is a faster way to do this, which is using Texture2D.GetRawTextureData() and Texture2D.LoadRawTextureData().

Related

How to create a Sprite Color Mask in Unity

I'm trying to use the Among Us Spritesheets to get crewmates in Unity. The spritesheet looks like this: https://www.reddit.com/r/AmongUs/comments/ir6nl0/main_player_sprite_sheet_for_those_who_wanted_it/
Each sprite is a blue/red color. Somehow the devs get every color of crewmate from these sprites, and I'm wondering how they did it.
How can I get every color of crewmate from this sprite sheet?
Thanks!
EDIT: Solution
I edited the title to be more accurate to my problem. Thanks to #G Kalendar for mentioning Shaders, I hadn't thought about that.
What I ended up doing was creating a Shader Graph, extracting each color channel, multiplying it by a color value, and recombining them into a texture.
I followed this helpful and straightforward tutorial: https://www.youtube.com/watch?v=4dAGUxvsD24
This is what my Shader Graph ended up looking like:
"Secondary" and "Primary" are color properties.
Hope this helps somebody!
If you want to have multiple info stored in a single image, it's common practice to use the channels: Red, Green, Blue. Horizon Zero Dawn for example uses that technique to make the environment effects as efficient as possible.
Here it looks like blue and red are used as a polaceholder to mark an area. So in unity's shader graph, when you use this image in a SampleTexture2D node you can use a Split node to get the different channels of the image to isolate the parts you want to color in.
Then just multiply the different channels by the color you want, add them together and use that as the base color.
Edit: Or use the "Replace Color Node" I just learned about.

Different ways to detect size of image on mesh versus size of mesh

I'm creating a puzzle game that generates random sized pieces with 2D meshes. The images contain transparent portions and sometimes a piece is completely transparent. I need to detect what percentage of a piece is transparent. One way I found to do this is to go pixel by pixel. I posted my solution to this HERE. However, this process adds a few seconds during loading which I'd like to avoid and I'm looking for other ideas
I've considered using the selection outline of a MeshCollider to somehow to get a surface area I can compare to the surface area of the mesh but everything I find is on the rendering of outline with specialized shaders. Does anyone have any ideas on to solve this?
.
1) I guess you could add a PolygonCollider2D to your sprite and use its Path for the outline and calculation of the surface area. Not sure however if this will be faster.
PolygonCollider2D.GetPath:
A path is a cyclic sequence of line segments between points that define the outline of the Collider
Checking PolygonCollider2D.GetTotalPointCount or path length may be good enough to determine if the sprite is 'empty'.
Sprite.vertices, Sprite.triangles may also be helpful.
2) You could also improve performance of your first approach:
instead of calling GetPixel as you do now use GetPixels or GetPixels32 and loop through the array in one for loop.
Using GetPixels can be faster than calling GetPixel repeatedly, especially for large textures. In addition, GetPixels can access individual mipmap levels. For most textures, even faster is to use GetPixels32 which returns low precision color data without costly integer-to-float conversions.
check only every 2nd or nth pixel as it should be good enough for approximation
limit number of type casts

How can i find for every pixel on the screen which object it belongs to?

Each frame unity generate an image. I want that it will also create an additional arrays of int's and every time it decide to write a new color on the generated image it will write the id of the object on the correspond place in the array of int's.
In OpenGL I know that it’s pretty common and I found a lot of tutorials for this kind of things, basically based on the depth map you decide which id should be written at each pixel of the helper array. but in unity i using a given Shader and i didn't find a proper way to do just that. i think there should be any build in functions for this kind of common problem.
my goal is to know for every pixel on the screen which object it belongs to.
Thanks.
In forward rendering if you don't use it for another purpose you could store the ID into the alpha channel of the back buffer (and it would only be valid for opaque objects), up to 256 IDs without HDR. In deferred you could edit the unused channel of the gbuffer potentially.
This is if you want to minimize overhead, otherwise you could have a more generic system that re-renders specific objects into a texture in screenspace, whith a very simple shader that just outputs ID, into whatever format you need, using command buffers.
You'll want to make a custom shader that renders the default textures and colors to the mainCamera and renders an ID color to a renderTexture trough another camera.
Here's an example of how it works Implementing Watering in my Farming Game!

Placing objects around image highlights- coco2d /opengl / coregraphics?

I would like to extract the white areas/bright areas of an image and place a custom objects in those areas. I need to know which framework to work with. if anyone has done something similar, I would appreciate an answer. I know how to get Pixel values, however the hard part is creating a Bloom/star effect in those highlighted areas.
You could make a mask where the luminance value was above a threshold, then blur or whatever the mask and composite above the image.

Getting pixels data from image on iPhone

I want to use bitmap images as a "map" for levels in iphone game. Basicly it's all about the location of obstacles in the rectangular world. The obstacles would be color-coded -- where the white pixel is, there's no obstacle. Black means there is one at this point.
Now I need to use this data to do 2 things: (a) display the level map, (b) for in-game calculations. So, in general, I need a way to read the data from the bitmap and create some data structure (matrix-like) with those information - to both overlay the bitmap onto the level graphics as well as to calculate collisions and such.
How should I do it? Is there any easy way to read the data from image? And what's the best format to keep the images for this?
Have you looked at how Texture2D translates an image file to an OpenGL Texture ?
Tip: take a look at this Method in Texture2D.m:
- (id) initWithCGImage:(CGImageRef)image orientation:(UIImageOrientation)orientation sizeToFit:(BOOL)sizeToFit pixelFormat:(Texture2DPixelFormat)pixelFormat filter:(GLenum) filter
In 3D apps, it's quite common to use this kind of representation for height maps, in a height map, you use a Texture with colors that range from black to white ( white represents the maximum altitude )
For example, from this:
To this:
That was just to tell you that your representation is not that crazy :).
About reading the bitmap, I would also recommend you to read this (just in case you want to go deeper)
Hope I helped a bit!