Does anyone know how to load dynamic updates into Texture2D’s quickly? I’m trying to push data from WriteableBitmap to a Texture2D, but I’m only getting 1 frame a second, I tried converting to a byte array by using:
var psrc = GCHandle.Alloc(bitmap.Pixels, System.Runtime.InteropServices.GCHandleType.Pinned);
byte[ ] dst = new byte[bitmap.Pixels.Length * 4];
Marshal.Copy(psrc.AddrOfPinnedObject(),dst,0,dst.Length);
psrc.Free();
Then loading with:
texture.LoadRawTextureData(dst);
But I get:
ExceptionObject: {System.Runtime.InteropServices.SEHException: External component has thrown an exception.
at UnityEngineProxy.InternalCalls.Texture2D_CUSTOM_LoadRawTextureData(Object self, Object data)
at UnityEngine.Texture2D.LoadRawTextureData(Byte[ ] data)
I’m not sure I’m following why you would want to create an unmanaged pointer, push that onto a managed byte array when you’ve already got a managed byte array (bitmap) to begin with.
is the bitmap encoded in a way that unity supports it? why not just use LoadImage instead… seems much more straight forward.
Because I want to do it 60 times per second,Texture2D.LoadRawTextureData accepts raw data being push directly into the texture, ideally I want to use Texture2D.CreateExternalTexture over a WriteableBitmap. Both LoadImage and LoadRawTextureData use byte arrays, but bitmap.Pixels is an array of int, so I was trying to get the underlaying raw byte data on the int array (as the format is the same as is 4 bytes per pixel and each int represents a pixel)
But currently Texture2D.CreateExternalTexture and Texture2D.LoadRawTextureData provide no sample information.
As he describes, looks like unless you really need to do some heavy lifting, sticking to the managed class will provide same performance. Just thinking though, if you do need some image fx, you might need to put those routines into a c++ component to get the processing benefits, but you could keep the pixel “buffer” pushing in c#
I had been wanting to do something similar that takes a secondary camera texture from Unity and pump it into a XAML element… just haven’t had time to work on it yet though so I’m curious to see how you manage. My fear is that Unity’s performance with multiple cameras this way will be poor.
I’d got the image processing side sorted in a c# plugin, runs at only a few milliseconds I can easily push to a SharpDX at 60 ftp with 10ms to spare, so it’s just the semantics of getting it into Unitys Texture2D thats the issue…I’m actually considering shelling out to SharpDX just for that section of the game…grrr
Thanks for the links though, may have some bits in of use. I do think when we start seeing samples of Texture2D.CreateExternalTexture it will help as this just takes a pointer and so I assume points to the same in memory space.
Yes, LoadRawTextureData() should be instant, as it’s just doing a low level MemCopy. I tested with your method previously, it took around 900ms on a handset (the image size is 1280x768.
Here is an example using LoadRawTextureData(). The format of the raw data depends on the TextureFormat you create the Texture2D with. In this case it’s RGB24 and I’m generating a texture with alternating red and blue rows.
public class RawTex : MonoBehaviour {
void Start() {
int w = 50;
int h = 50;
Texture2D texture = new Texture2D(w, h, TextureFormat.RGB24, false);
byte[] data = new byte[w * h * 3];
int pixel = 0;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
if (y % 2 == 0) {
data[pixel] = 255;
data[pixel+1] = 0;
data[pixel+2] = 0;
} else {
data[pixel] = 0;
data[pixel+1] = 0;
data[pixel+2] = 255;
}
pixel += 3;
}
}
texture.LoadRawTextureData(data);
texture.Apply();
renderer.material.mainTexture = texture;
}
}