Search Unity

How to copy the everyplay thumbnail

Discussion in 'Unity Everyplay' started by JeffersonTD, Oct 3, 2015.

  1. JeffersonTD

    JeffersonTD

    Joined:
    Feb 5, 2013
    Posts:
    268
    Ok, I now the topic sounds weird, but so is my problem. In short:

    1. I am able to take a screenshot with the Everyplay API, and use that for a texture in the game.
    2. I am able to take a screenshot by using readPixels and apply methods of Texture2D and use that with the Post(string serviceType, string message, Texture2D image, string url, bool checkServiceAvailable) method of the U3DXT.iOS.Native.Social package.
    3. But I am not able to take the screenshot taken through the Everyplay API anduse that with the U3DXT library

    This works for 1:
    videoThumbnailMaterial.mainTexture = tex
    But when I try to eg.
    screenShot=Instantiate(tex)asTexture2D​
    or
    screenShot = Instantiate(thumbnailMaterial.mainTexture) as Texture2D;​
    or simply
    screenShot = tex;​
    it just won't work.

    Number 2:
    screenShot = new Texture2D (Screen.width / 2, Screen.height, TextureFormat.RGB24, true);
    screenShot.ReadPixels (new Rect (0, 0, Screen.width / 2, Screen.height), 0, 0, true);​
    screenShot.Apply ();
    does work, but it freezes the game for maybe like half a second (on iPhone 5) which is unacceptable.

    Why is that I can't just assign or copy the tex received from onThumbnailReady to be used by the U3DXT method like described above?
     
  2. JeffersonTD

    JeffersonTD

    Joined:
    Feb 5, 2013
    Posts:
    268
    Any help with this please? I've now tried using the GetNativeTexturePtr() for this too, but that results in just a black screenshot, whereas other methods result in an entirely gray screenshot. Is this some kind of a texture format problem, or what? How do I get the same end result from the "tex" received from the ThumbnailReady as I get from constructing a new Texture2D with RGB24 format and ReadPixels?
     
  3. JeffersonTD

    JeffersonTD

    Joined:
    Feb 5, 2013
    Posts:
    268
    I tested what kind of pixel values I get from the Everyplay screenshot texture with GetPixel. Well, it so happens that every component of each pixel is just always the same 0.804, which is some kind of a default. But why is it that the values are like that even though what I see in that texture is a real screenshot? Is the the texture data in a more native format or something? Or is it that the texture for some reason doesn't have its read/write tag on? Is there no way I could get the real pixels of that texture? This is really frustrating: I have the texture, I just can't use it for both of the purposes I'd like to.
     
  4. pmjo

    pmjo

    Unity Technologies

    Joined:
    Sep 17, 2013
    Posts:
    245
    The Everyplay thumbnail is kind of a special texture and it's real data only resides on the GPU and that is why you get just blank when you try to clone it. However I found a way to get around this issue by rendering the thumbnail texture to a RenderTexture with a simple blit shader and use that texture instead. If you need the cloned texture to be Texture2d you can convert the RenderTexture to Texture2D.

    Here is a method which creates a RenderTexture from the Everyplay thumbnail texture and also a simple blit shader which you should set to the material used for blitting. If you want you can use other shaders too for example to add effects to the cloned texture.

    Code (CSharp):
    1. public RenderTexture EveryplayThumbnailToRenderTexture(Texture2D texture, Material material) {
    2.    RenderTexture renderTexture = null;
    3.  
    4.    if(texture != null) {
    5.       renderTexture = newRenderTexture(texture.width, texture.height, 0, RenderTextureFormat.ARGB32);
    6.  
    7.       Graphics.Blit (texture, renderTexture, material);
    8.    }
    9.  
    10.    return renderTexture;
    11. }
    12.  
    Shader:

    Code (CSharp):
    1. Shader "Everyplay/Blit" {
    2.     Properties { _MainTex ("", any) = "" {} }
    3.     SubShader {
    4.         Pass {
    5.             Cull Off Lighting Off ZWrite Off Fog { Mode Off }
    6.  
    7.             CGPROGRAM
    8.             #pragma vertex vert
    9.             #pragma fragment frag
    10.  
    11.             #include "UnityCG.cginc"
    12.  
    13.             sampler2D _MainTex;
    14.        
    15.             struct v2f {
    16.                 float4 vertex : SV_POSITION;
    17.                 float2 texcoord : TEXCOORD0;
    18.             };
    19.  
    20.             v2f vert (appdata_base v)
    21.             {
    22.                 v2f o;
    23.                 o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
    24.                 o.texcoord = v.texcoord.xy;
    25.                 return o;
    26.             }
    27.  
    28.             fixed4 frag (v2f i) : SV_Target
    29.             {
    30.                 return tex2D(_MainTex, i.texcoord);
    31.             }
    32.             ENDCG
    33.  
    34.         }
    35.     }
    36.     Fallback Off
    37. }
    38.  
    ps. tested the code only with Unity 4.6.8 + iPhone 6 (iOS 8.4)
     
    Last edited: Nov 26, 2015
    DanishSinha likes this.
  5. gtzpower

    gtzpower

    Joined:
    Jan 23, 2011
    Posts:
    318
    Thank you so much for posting this. I have a completely different use case, but this is the only thing I have found so far that allows me to copy the native textures that "Easy Movie Texture" on the asset store uses.

    Tested and working in Unity 5.2.1 on Android 5.0.1 (Nexus 7) as well as iOS 9.0.1 (gen 1 iPad Mini)

    I did modify the code you provided a bit to better suit my needs. I didn't need the shader at all to get this working:
    Code (csharp):
    1.  
    2. public Texture2D CopyNativeTexture(Texture2D texture) {
    3.     RenderTexture renderTexture = null;
    4.     Texture2D destinationTexture = new Texture2D(texture.width, texture.height);
    5.  
    6.     if(texture != null) {
    7.         renderTexture = new RenderTexture(texture.width, texture.height, 0, RenderTextureFormat.ARGB32);
    8.  
    9.         RenderTexture oldActive = RenderTexture.active;
    10.         RenderTexture.active = renderTexture;
    11.  
    12.         Graphics.Blit (texture, renderTexture);
    13.  
    14.         destinationTexture.ReadPixels(newRect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
    15.         destinationTexture.Apply();
    16.  
    17.         RenderTexture.active = oldActive;
    18.     }
    19.  
    20.     return destinationTexture;
    21. }
    22.  
     
    pmjo likes this.
  6. pmjo

    pmjo

    Unity Technologies

    Joined:
    Sep 17, 2013
    Posts:
    245
    Yes, you don't need the shader if you don't want to modify any pixels. Here is a simplified version of the method. If you need the result to be Texture2D instead of RenderTexture you can use gtzpowers implementation.

    Code (CSharp):
    1.     public RenderTexture EveryplayThumbnailToRenderTexture(Texture2D texture) {
    2.         RenderTexture renderTexture = null;
    3.  
    4.         if(texture != null) {
    5.             renderTexture = new RenderTexture(texture.width, texture.height, 0, RenderTextureFormat.ARGB32);
    6.  
    7.             Graphics.Blit (texture, renderTexture);
    8.         }
    9.  
    10.         return renderTexture;
    11.     }
     
    Last edited: Nov 26, 2015
  7. umair_hassan

    umair_hassan

    Joined:
    Aug 14, 2014
    Posts:
    6
    when i take a thumbnail(screenshot), where does that image saved? In asset or phone memory? secondly, how to retrieve that image for assigning that texture to NGUI Textures or what so ever?
     
  8. pmjo

    pmjo

    Unity Technologies

    Joined:
    Sep 17, 2013
    Posts:
    245
    The Everyplay thumbnail API does not support files anymore. The captured thumbnail will be stored in memory (gpu). Here is an updated example how to use the thumbnail API.
     
  9. DanishSinha

    DanishSinha

    Joined:
    Nov 9, 2016
    Posts:
    18

    @pmjo I haven't used the shader file. Do I need to add in my scene hierarchy and do I create a standard C# file?
    A little explanation regarding the same would be great. :)
     
  10. pmjo

    pmjo

    Unity Technologies

    Joined:
    Sep 17, 2013
    Posts:
    245
    Hi
    What are you trying to achieve? If you are trying to copy the Everyplay texture to Texture2D I would simply use the function that @gtzpower pasted above. You will not need the shader incase you don't want to manipulate the pixels in any way when copying.