Search Unity

Unity UI Is there a way to render a UI canvas into a buffer or RenderTexture?

Discussion in 'UGUI & TextMesh Pro' started by awmcclain, Apr 25, 2018.

  1. awmcclain

    awmcclain

    Joined:
    Dec 24, 2013
    Posts:
    12
    I'm attempting an offset ghosting effect for some of the UI in our game.

    Since the "effect" is larger than the bounding box of the UI elements I want to ghost, and because I have mixed elements that use different shaders (image background + TMPro text), my naive solution is to render out a subcanvas or group of UI elements into a buffer that's slightly larger than the bounding box and then run a post-process effect on it, blitting it back to the screen.

    I'm just not sure if there's a good way to accomplish that.
     
  2. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,096
    you can easily render the ui into a render texture by changing the Render Mode of the canvas to "Screen Space - Camera".
    Since you need to render more than the canvas itself this might not work for you perfectly. But you can also set it to "World Space". Now you can place the UI wherever you want and render with a camera as much as you need.
     
  3. AlejMC

    AlejMC

    Joined:
    Oct 15, 2013
    Posts:
    149
    This will open a can of worms if the render texture size doesn't match the camera's resolution (i.e. for rendering at a bit lower or a bit higher resolution).
    - The UI sizing will be scaled different (unless a custom made component that inherits from CanvasScaler and handles the HandleScaleWithScreenSize() method.
    - Buttons, raycasts and others don't seem to work (I'm still trying to find a solution for this).
     
  4. DearUnityPleaseAddSerializableDictionaries

    DearUnityPleaseAddSerializableDictionaries

    Joined:
    Sep 12, 2014
    Posts:
    135
    Did you find a solution to this?
     
  5. AlejMC

    AlejMC

    Joined:
    Oct 15, 2013
    Posts:
    149
    Not at the time and I can't remember what I did with it. Probably just kept it full screen res (a render target that gets created dynamically depending on back buffer sizes on start).

    The only dynamic render target resolution handling that I did and kept afterwards is for screen rays from the pointer like so:
    Code (CSharp):
    1. // Has a render texture, so handle via viewport coords.
    2.  
    3. Camera c;
    4.  
    5. var viewportCoord = new Vector3()
    6. {
    7.     x = position.x / Screen.width,
    8.     y = position.y / Screen.height,
    9.     z = c.nearClipPlane
    10. };
    11. var r = c.ViewportPointToRay(viewportCoord);
    12. return r;
    13.  
    14. // Caveats
    15. // On editor the Screen class's width/height is the monitor's device resolution and not the game view. This works as a workaround:
    16. #if UNITY_EDITOR
    17.     string[] resWidthAndHeight = UnityEditor.UnityStats.screenRes.Split('x');
    18.  
    19.     width = System.Convert.ToInt32(resWidthAndHeight[0]);
    20.     height = System.Convert.ToInt32(resWidthAndHeight[1]);
    21.  
    22.     //Debug.Log("Size: " + UnityEditor.UnityStats.screenRes);
    23. #endif
    24.  
    For UI didn't find a similar solution to tweak the ray, pointer, etc positions.