- Home /
Use SetPixels, but dont set unvisible Pixels
I have a little Solution to put togehter multiple Sprites in one Sprite, but i have a problem, when i use SetPixels Method on the new Texture2D, SetPixel sets also unvisible Pixels with Alpha = 0.(i Use GetPixels to get pixels from Sprite) So the function delet whats behinde the Sprite but should be vissible because its only behinde a alpha = 0 pixel. The Only Solution i see is to use SetPixel and check for alpha = 0, but thats realy bad work, because i have some offset and setting every single pixel that would be bad.
Answer by Bunny83 · Jun 22, 2016 at 11:41 PM
A texture is always a rectangle and SetPixels can only set all pixels at once. You would need to combine the pixel data manually. I've once written this simple alpha blend method which does exactly that. The method i've posted over there only works on images with equal size as i simply iterate over both pixel arrays. If you want to use offsets or source / target rectangles it's a bit more complicated but not too bad.
I've just written a little helper class that allows you to write a portion of a Texture2D into another Color array based on a blend function. By default it uses a src alpha blend function.
public static class Texture2DExtension
{
public delegate Color BlendFunc(Color src, Color dest);
public static void WriteTo(this Texture2D aTexture, Color[] aTarget, int aTargetWidth, Rect aSourceRect, Vector2 aTargetPos, BlendFunc blend = null)
{
if (blend == null)
blend = AlphaBlend;
int w = aTexture.width;
int h = aTexture.height;
int tw = aTargetWidth;
int th = aTarget.Length / tw;
Color32[] colors = aTexture.GetPixels32();
int sx = (int)aSourceRect.x;
int sy = (int)aSourceRect.y;
int sw = (int)aSourceRect.width;
int sh = (int)aSourceRect.height;
int tx = (int)aTargetPos.x;
int ty = (int)aTargetPos.y;
// clip rectangles
if (sx < 0) { sw -= sx; sx = 0; }
if (sy < 0) { sh -= sy; sy = 0; }
if (sx + sw > w) { sw -= sx + sw - w; }
if (sy + sh > h) { sh -= sy + sh - h; }
if (tx < 0) { sx -= tx; sw += tx; }
if (ty < 0) { sy -= ty; sh += ty; }
if (tx + sw > tw) { sw -= tx + sw - tw; }
if (ty + sh > th) { sh -= ty + sh - th; }
for (int y = 0; y < sh; y++)
{
for (int x = 0; x < sw; x++)
{
int srcIdx = x + sx + (y + sy) * w;
int destIdx = x + tx + (y + ty) * tw;
Color src = colors[srcIdx];
Color dest = aTarget[destIdx];
aTarget[destIdx] = blend(src, dest);
}
}
}
public static void WriteTo(this Texture2D aTexture, Color[] aTarget, int aTargetWidth, Vector2 aTargetPos, BlendFunc blend = null)
{
Rect srcRect = new Rect(0, 0, aTexture.width, aTexture.height);
WriteTo(aTexture, aTarget, aTargetWidth, srcRect, aTargetPos, blend);
}
public static BlendFunc AlphaBlend = _AlphaBlend;
private static Color _AlphaBlend(Color src, Color dest)
{
return Color.Lerp(src, dest, src.a);
}
}
With that class inside your project you can simply do this:
Texture2D someTex;
Color[] targetPixels;
someTex.WriteTo(targetPixels, targetWidth, new Vector2(10,10));
targetWidth is the width of the target texture so we can calculate the index into the targetPixels array. The vector defines where inside the target area you want to write that texture. Note that there's an overload that takes an additional "source rect" which allows you to just write a portion of "someTex" into the target area. The function clips all rectangles according to the image sizes.
Finally you can pass a custom blend function as last parameter so you can freely decide how the destination color and the source color should be combined.
Your answer
Follow this Question
Related Questions
SetPixels PROBLEM (trying to put decals) 0 Answers
getPixel/setPixels or stencil eraser brush 2 Answers
How can I show my SetPixels() texture changes without having to zoom my orthographic camera? 1 Answer
Resetting a Material's Texture After GetPixels/SetPixels 1 Answer
Proper way to strew lots of dead in Napoleonic RTS? 3 Answers