x


problem with accessing color values of Color32 in C plugin

Hello,

My short question is this: What is the packing of Color32 unity classes? I have been led to believe through the access violation errors in my c plugins, which write to pointer to Color32, that the packing is NOT 8888 for RGBA or 32 bbp as it is for the Color class.

Long winded question, I have written a plugin to write color values to unity textures. My first iteration of the program used Color[] to store color values with unity. My C# unity side the program was taken from the texture plug sample located here : http://unity3d.com/support/resources/example-projects/texture-plugins. The relevant code snippet for creating and sending the texture pointer is:

using UnityEngine; using System; using System.Runtime.InteropServices;

public class TexturePlayback : MonoBehaviour {

public int width = 256;
public int height = 256;
private Texture2D m_Texture;

private Color[] m_Pixels;
private GCHandle m_PixelsHandle;

void Start () {
    // Create texture that will be updated in the plugin
    m_Texture = new Texture2D (width, height, TextureFormat.ARGB32, false);
    // Create the pixel array for the plugin to write into at startup    
    m_Pixels = m_Texture.GetPixels (0);
    // "pin" the array in memory, so we can pass direct pointer to it's data to the plugin,
    // without costly marshaling of array of structures.
    m_PixelsHandle = GCHandle.Alloc(m_Pixels, GCHandleType.Pinned);

    // Assign texture to the renderer
    if (renderer)
        renderer.material.mainTexture = m_Texture;
    // or gui texture
    else if (GetComponent(typeof(GUITexture)))
    {
        GUITexture gui = GetComponent(typeof(GUITexture)) as GUITexture;
        gui.texture = m_Texture;
    }
    else
    {
        Debug.Log("Game object has no renderer or gui texture to assign the generated texture to!");
    }
}

void OnDisable() {
    // Free the pinned array handle.
    m_PixelsHandle.Free();
}

// Link to the UnityTexture plugin and call the UpdateTexture function there.
[DllImport ("UnityTexture")]
private static extern void UpdateTexture (IntPtr colors, int width, int height, float time);

// Now we can simply call UpdateTexture which gets routed directly into the plugin
void Update () {
    UpdateTexture (m_PixelsHandle.AddrOfPinnedObject(), m_Texture.width, m_Texture.height, Time.time);
    m_Texture.SetPixels (m_Pixels, 0);
    m_Texture.Apply ();
}

}

The relevant C plugin code for the UpdateTexture function is:

... float* data = reinterpret_cast<float*>(destination); // destination is texture pointer "m_PixelsHandle.AddrOfPinnedObject()" from unity

for(int y=0; y < height; y++){
    for(int x=0; x < width; x++){
       float* pixel = data + (y * width * 4 + x * 4);
       pixel[0] = 1.0f; 
       pixel[1] = 0.0f;
       pixel[2] = 0.0f;
       pixel[3] = 1.0f;
    }
}

...

Everything is going swimmingly when I use Color class and the texture is correctly changed to red. However, SetPixel is rather slow for large textures and I heard SetPixel32 is faster. So I changed the C# code to Color32 and SetPixel32, from Color and SetPixel respectively. However, this now causes an access violation on my plugin, thus leading me to believe the color data for Color32 is packed differently than Color. Is this the case? And if so, how are the color values stored in the Color32 class? If this is not the case and the program is failing for another unforeseen reason, I would appreciate any kind words of enlightenment.

thank you

more ▼

asked Jun 27 '12 at 08:41 PM

rgbohner gravatar image

rgbohner
31 2 2 4

Just briefly glancing at your code (apologies if this isn't the case): Color32 uses 4 byte values for rgba, not 4 floats. If you're trying to implicitly convert float to byte that could be your problem.

Jun 27 '12 at 08:52 PM Julien.Lynge
(comments are locked)
10|3000 characters needed characters left

1 answer: sort voted first

Per NOAA_Julien's suggestion, the Color32 structure is indeed packed as bytes rather than floats. http://docs.unity3d.com/Documentation/ScriptReference/Color32.html So a little change to my above plug-in code to represent the texture array from unity as unsigned chars fixed the problem:

    ...
    unsigned char* data = reinterpret_cast<unsigned char*>(destination); 
    for(int y=0; y < height; y++){
       for(int x=0; x < width; x++){
          unsigned char* pixel = data + (y * width * 4 + x * 4);
          pixel[0] = (unsigned char) 255; //RED
          pixel[1] = (unsigned char) 0; 
          pixel[2] = (unsigned char) 0;
          pixel[3] = (unsigned char) 255;
       }
    }
    ...

Also, for those interested, the change from SetPixels to SetPixels32 is an increase of about 33% in frame rate on SD sized textures.

more ▼

answered Jun 28 '12 at 08:54 PM

rgbohner gravatar image

rgbohner
31 2 2 4

Don't forget to give Julien a thumbs-up for their help! (and mark the answer as accepted so the question doesn't show up as unanswered)

Jun 28 '12 at 09:24 PM Loius
(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

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

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x2193
x506
x392

asked: Jun 27 '12 at 08:41 PM

Seen: 952 times

Last Updated: Jun 29 '12 at 11:09 PM