Search Unity

RenderTexture bug on Android

Discussion in 'General Graphics' started by 2367, Jan 23, 2020.

  1. 2367

    2367

    Joined:
    Nov 23, 2014
    Posts:
    8
    Hi, I try to get a Sceenshoot from camera, render to texture and encode to .PNG. It's working fine in Unity Editor, but it creates wrong texture on Android. I use Unity 2018.4, OpenGL 3.0.
    I found out that the problem is with the depth parameter for RenderTexture. If it's = 0, the texture is corrent on Android too, but I need to see the depth on the screen. Thanks
     

    Attached Files:

  2. Shaunyowns

    Shaunyowns

    Joined:
    Nov 4, 2019
    Posts:
    328
    Hey @2367 I'll send this post over to see if we can get a response!
     
  3. 2367

    2367

    Joined:
    Nov 23, 2014
    Posts:
    8
    I really need a solution to this problem. As I understand it, there is no other way to get a screenshot from the camera, except for rendering in the texture? In this case, the rendering inoperability makes it impossible for the project to work on the android. If there is another way to get a screenshot from the camera in a sprite, without rendering in a texture, let me know.
     
  4. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    3,028
    @2367 do you see any errors in the device logs?
     
  5. 2367

    2367

    Joined:
    Nov 23, 2014
    Posts:
    8
    No, I do not see any errors on the device, only a corrupted texture
     
  6. 2367

    2367

    Joined:
    Nov 23, 2014
    Posts:
    8
    I am really surprised that this problem has not yet been solved, since it is very easy to reproduce: I created a new project, with two cameras: the main one and for the screenshot, added the render code to the texture from the Unity documentation. And this problem is reproducible on any android device that I just tried. Try this, I'm sure you can get any debugging information that you need. If you need my project specifically, I can upload it to github
     
  7. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    3,028
    @2367 The screenshot looks like you're not clearing the render target. What are the camera clear flags?
     
  8. 2367

    2367

    Joined:
    Nov 23, 2014
    Posts:
    8
    ScreenCamera.clearFlags = CameraClearFlags.Nothing;
     
  9. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    3,028
    This is expected, then.
    Not clearing an area and not rendering into it is undefined behaviour, and what you see is completely valid.
    Set clear to some solid color, for example, and you'll be fine.
     
  10. 2367

    2367

    Joined:
    Nov 23, 2014
    Posts:
    8
    You was right, this solved the problem!
     
  11. Nurallaerel

    Nurallaerel

    Joined:
    May 6, 2015
    Posts:
    13
    I have a similiar problem and hope you could help me out. I've used this tutorial to create fog of war effect.
    In order to remove fog permanently, camera with 'Dont' clear' flag used for rendering a texture for projector.

    However this doesnt' work on my Android device as-is. Everything is fine in the Editor, but Android device seems to generate broken Render texture:
    upload_2021-7-13_1-58-7.png or if I increase dimensions: upload_2021-7-13_1-58-19.png

    On the left side you could see the correct behaviour (Don't clear flag turned off), on the right side the same setup but with the flag:
    upload_2021-7-13_1-59-45.png

    1) It works if I turn off anti-aliasing on a render texture. (but this is not a solution in this case)
    2) This very same texture works fine, when the camera flag is set to anything but 'Don't clear'

    Render Texture settings:
    upload_2021-7-13_1-56-34.png

    Using Unity 2021.1.12f1 and Android 11

    I tried changing color formats, dimensions and other settings, but I dont have very deep knowledge of how things work, and my hopes are on this forum. Thanks in advance
     
  12. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    3,028
    @Nurallaerel "don't clear" with a render texture on mobile GPUs means literally "don't do anything with the underlying memory". If there's garbage in this memory, it will be there when you start using it. You should only use this is you know you're going to overwrite all the content.
     
    Nurallaerel likes this.
  13. Nurallaerel

    Nurallaerel

    Joined:
    May 6, 2015
    Posts:
    13
    Thank you, that is pretty clear answer. I will have to use some kind of substitue like this.

    Still don't get why it works without anti-aliasing though
     
  14. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    3,028
    Because it can happen that it reuses the same memory in some conditions, so you get something that "looks correct". In the language they use in the documentation, this is described as "the content of a render texture is undefined". You may get the correct thing, or may not, nothing is guaranteed.
     
    Nurallaerel likes this.
  15. mm_hohu

    mm_hohu

    Joined:
    Jun 4, 2021
    Posts:
    41
    I am facing a similar problem with render textures.
    The following buffer zero-clear code does not work properly with Vulkan.

    Code (CSharp):
    1. void RenderTextureClear(ScriptableRenderContext ctx, CommandBuffer cmd, RenderTexture rt)
    2.         {
    3.             // Note: (Vulkan Only)
    4.             // Note: If the clear color is completely 0, the clearing process itself is omitted. The expected behavior is to zero-clear the buffer.
    5.             // Note: When using OpenGL, this code works fine.
    6.             // Note: Devices that automatically zero-clear uninitialized buffers do not reproduce this problem. (e.g. mediatek's dimencity 800, in my case)
    7.             // Note: I am observing this problem with adreno610.
    8.             var clearColor = Color.clear;
    9.             cmd.SetRenderTarget(rt, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.DontCare);
    10.             cmd.ClearRenderTarget(RTClearFlags.ColorDepth, clearColor, 1f, 0U);
    11.             ctx.ExecuteCommandBuffer(cmd);
    12.             cmd.Clear();
    13.         }
     
  16. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    3,028
    @mm_hohu Did you try using
    RenderBufferLoadAction.Clear
    instead?
     
  17. mm_hohu

    mm_hohu

    Joined:
    Jun 4, 2021
    Posts:
    41
    I got the following error.
    ArgumentException: RenderBufferLoadAction.Clear is not supported.

    According to documentation, "Currently only works together with the RenderPass API".
    I am not using NativeRenderPass.
     
  18. mm_hohu

    mm_hohu

    Joined:
    Jun 4, 2021
    Posts:
    41
    I found a few more details. As it turns out, it seems that a pass that writes no color at all (i.e. a zero-clear pass) discards the result if there is no pass immediately following that pass that writes a color "greater than zero" to the buffer.

    I tried to force clear the buffer using cmd.DrawProcedural() instead of ClearRenderTarget(), but the result was discarded.

    I had zero-cleared all the render textures I was going to use together at the beginning of the render pipeline, but I found that this did not work well on certain Android devices. However, I was unaware of this fact until now, since the above code works fine without Vulkan.

    For ClearRenderTarget( Color.clear ) to work, it must be executed just before the pass that actually writes a color greater than 0.

    I have checked my render pipeline code many times. However, it is possible that I am missing something.
     
  19. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    3,028
    I suggest asking in the Android subforum then.
     
    mm_hohu likes this.
  20. danipomix

    danipomix

    Joined:
    Oct 18, 2019
    Posts:
    11

    Hi,

    I have a problem that may relate to this topic.

    To create a texture with a certain material effect applied on it, I do something like this:




    public Texture2D source;
    public Material material;


    public static void Create(GameController gameController)
    {
    Texture2D t = source;
    gameController.ImprovedPhoto = t;
    gameController.ImprovedPhoto = ImproveOriginalPhoto(gameController, material, gameController.ImprovedPhoto, 1024);
    }


    //this is the method where I apply the material to the new texture, using a RenderTexture
    public static Texture2D ImproveOriginalPhoto(GameController gameController, Material material, Texture2D source, int size)
    {

    //gameController.renderTexture.format is ARGB32 and I see in the logcat
    //that CheckSupportRenderTextureInfo(RenderTextureFormat.ARGB32) == true
    RenderTexture buffer = new RenderTexture(size, size, 32, gameController.renderTexture.format);

    //render material to a RenderTexture using a Blit()
    Graphics.Blit(source, buffer, material, -1);

    //then create a Texture2D with the same dimensions and format as the render texture
    Texture2D new_Texture = new Texture2D(buffer.width, buffer.height, TextureFormat.ARGB32, true);
    new_Texture.filterMode = FilterMode.Bilinear;
    new_Texture.wrapMode = TextureWrapMode.Clamp;

    //and use ReadPixels() to copy the render texture to the CPU memory.
    new_Texture.ReadPixels(
    new Rect(0, 0, buffer.width, buffer.height), // Capture the whole texture
    0, 0, // Write starting at the top-left texel
    true);

    new_Texture.Apply();

    return new_Texture;

    }




    I tested this method on an "old" Redmi Note 9 (M2003J15SS) and there it works great (in the editor too), but when I test my application on a newer Xiaomi Mi 10T Pro (M2007J3SG) the generated ImprovedPhoto looks like the ImprovedPhoto.png, with transparent lines cutting through it.
    The Redmi Note has an aspect of 1080x2340, the Mi 10T has 1080x2400.
    I'm using Unity 2021.3.24f1.

    What could be causing this problem?
     

    Attached Files:

    Last edited: Sep 30, 2023
  21. danipomix

    danipomix

    Joined:
    Oct 18, 2019
    Posts:
    11
    I solved, It Was the blit(); So on the shader I added ZTest Always. I find my solution Here https://forum.unity.com/threads/gra...mR5yGhHra66q3zMDSyJJKXEt0eWvxQDVns95X7zPQVEng