Search Unity

Exporting png from custom render texture in HDRP results in darker image

Discussion in 'High Definition Render Pipeline' started by dlich, Oct 10, 2020.

  1. dlich

    dlich

    Joined:
    Apr 21, 2019
    Posts:
    11
    Hello, fellow gamedevs!
    I am trying to render icons in hdrp and save them to png. I am creating a custom render texture and clicking export in the context menu. It seems to save the file, however the color seems off - it's way darker than the original image. Refer to the screenshots below.
    After some googling and research I've found out that it's related to hdrp rendering in linear color space and the color format of the exported image. I could find suggestions to turn on check srgb mode on the render texture, however it doesn't seem like I have that option (screenshot below). There's an srgb option int color format dropdown, however I can't seem to select it - it goes back to UNORM options.(screen below)

    Render texture in the editor and how it's supposed to look:
    unknown.png


    Exported png looks darker:
    unknown (1).png

    No srgb checkbox in the inspector:
    upload_2020-10-10_18-43-3.png

    The srgb option in color format dropdown that I can't select:
    upload_2020-10-10_18-44-0.png
     
  2. Egad_McDad

    Egad_McDad

    Joined:
    Feb 5, 2020
    Posts:
    39
    Just tried this myself, first with a custom render texture and then with a render texture. I'm getting the same issue. For reference I'm using 2020.1.3f1 on windows.

    Have you tried initializing a new CRT at runtime to see if it allows it then?

    When I first saw the darker image the first thing that came to my mind was that you may have been blitting to the render texture prior to all post-processing completing. Using the frame debugger I've noticed the render target appearing dark until after the FinalPost. I believe you are correct in assuming that the color space is the culprit here, but just in case that turns out to be a dead end I thought I'd mention this possibility.
     
  3. robinDMUnity

    robinDMUnity

    Unity Technologies

    Joined:
    Oct 13, 2020
    Posts:
    8
    Hi there, it seems that the issue is not unique to HDRP. This happens when the color space of the project is set to linear (HDRP is always in linear). We are currently investigating a possible fix.
     
  4. John_VI

    John_VI

    Joined:
    Dec 11, 2013
    Posts:
    3
    I managed to get around this by saving it as a 32bit exr then applying the sRGB filter in photoshop, hope this is fixed soon though.
     
  5. Orion

    Orion

    Joined:
    Mar 31, 2008
    Posts:
    261
    This is still an issue. I can't get our project to export normal images for the life of me. Doesn't matter if it's regular render textures or custom ones.
     
  6. nGAGE

    nGAGE

    Joined:
    Sep 30, 2014
    Posts:
    6
    I can confirm, this is still a problem! I'm working with 2021.3.0f1 (LTS) atm.
    This has litterally wasted an entire day diagnosing until I realized it doesnt happen on the Built-in render-pipeline, only in URP and HDRP.
    Have not been able to find any solultion and editing externally is not an option. I'm working on an editor tool, to prevent the need for exactly that.

    *Indeed also happens in Built-in render-pipeline when ColorSpace is set to Linear. As well as, works as expected when using URP and ColorSpace is set to Gamma.

    If there is a fix by now that works for all render-pipelines, could anyone please share. I would really appreciate it.
     
    Last edited: Apr 13, 2022
  7. Orion

    Orion

    Joined:
    Mar 31, 2008
    Posts:
    261
    I have found a solution that worked well for me. It's kinda slow, but in my case, that wasn't an issue:
    • Copy the render texture to a texture2d
    • Use GetPixels on this texture and store the pixels in an array
    • Loop over each item of the array (they are colors)
    • Use the gamma or linear property of the item (I forgot which is the right one) and assign it back to the array
    • Use SetPixels to store the array in the texture again
    • Export EncodeToPNG (or what you want) to export the texture to a file
    This will give you the correct image. I spent more than two days trying to figure this out until I accidentally stumbled over the gamma/linear properties of the Color class, which solve the problem. Shame that the encode function doesn't have a switch for this or does it correctly automatically. But this works.
     
    PieterAlbers and Egad_McDad like this.
  8. nGAGE

    nGAGE

    Joined:
    Sep 30, 2014
    Posts:
    6
    Hmm... that would really go against what I'm trying to achieve with my tool. I'm computing textures with compute-shader, for speed. If I'd then have to loop over them on the CPU side that would defeat the purpose.

    For clarification, the output I get back is already being passed to a Texture2D and adjusted for linear ColorSpace. All looks fine, until I try to save that Texture2D. It's litterally just the
    Code (CSharp):
    1. File.WriteAllBytes(path, _preview.EncodeToPNG());
    bit that seems to mess things up.



    As you can see, the computed output is fine.
     
  9. Orion

    Orion

    Joined:
    Mar 31, 2008
    Posts:
    261
    Sorry. That's the best I've got.
     
  10. nGAGE

    nGAGE

    Joined:
    Sep 30, 2014
    Posts:
    6
    I seem to have found a word-around...
    It appears that by default, even when using linear color-space, textures are imported with gamma color-space. (if it were linear, they'd have to be imported with sRGB unchecked, apparently.)

    When I prepare my texture, I set it up to be in gamma (I think final parameter defaults to false, but just for illustration)



    I've added a simple bool in my compute shader, so I know if I'm working in linear color-space or not.


    And in the shader, I run every result through one final step that adjusts for gamma


    Final result seems to be correct


    Source of inspiration: https://medium.com/@abdulla.aldandarawy/unity-always-be-linear-1a30db4765db

    PS: It's not 100% perfect, but pretty close.
     
    Last edited: Apr 13, 2022
  11. Orion

    Orion

    Joined:
    Mar 31, 2008
    Posts:
    261
    Hm yeah I can see a little bit of difference, but not much. Isn't there a shader function for the conversion to get it exact?
     
  12. nGAGE

    nGAGE

    Joined:
    Sep 30, 2014
    Posts:
    6
    Great call!

    Changed it to:
    Code (CSharp):
    1. float4 gamma_correction(float4 source)
    2. {
    3.     if (is_linear)
    4.        return float4(LinearToGammaSpace(source), LinearToGammaSpaceExact(source.a));
    5.  
    6.     return source;
    7. }
    8.  
    Now the output is identical looking :)
     
    Last edited: Apr 15, 2022
    Egad_McDad likes this.
  13. Orion

    Orion

    Joined:
    Mar 31, 2008
    Posts:
    261
    Excellent!