Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

RFloat 32 bit single-channel EXR import

Discussion in 'General Graphics' started by GuitarBro, Mar 29, 2019.

  1. GuitarBro

    GuitarBro

    Joined:
    Oct 9, 2014
    Posts:
    179
    Been scratching my head over this for the past few days, but it seems to be that there's no way to import a single-channel 32bit EXR texture despite the fact that I can export one I generated in Unity just fine. When importing as "Single Channel" I only see the following format options (for PC/Mac/Linux):
    • Alpha 8
    • R 8
    • R Compressed BC4
    • R Compressed EAC 4bit
    Considering I'm exporting an RFloat texture, one would think I would be able to import it back as such given that EXR supports 32bits per channel and single-channel images. All the pieces of the pipeline seem to be there, expect for the importer.

    My goal is to be able to pass the generated heightmap from a terrain as a texture to be sampled as a displacement map in another shader. I'm currently using an RGBA Half texture, however 16 bits of precision just isn't enough at the scale I'm working with (not to mention the other empty channels are quite wasteful). So I turned to RFloat.

    Of course, I could perform this texture generation at runtime every game session and simply keep it stored as a Texture2D in memory, however I'd like to allow it to be manually edited after it has been generated in which case I need a way to import it back post-modification.

    Am I missing something that would enable that import option? Or is it just impossible without support from Unity and I need to look for a workaround?
     
  2. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    GuitarBro and bgolus like this.
  3. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    Like that first link does, you'll want to give your texture file some kind of suffix like _RFloat that you can look for in your preprocessor.

    One oddity of doing this is the texture asset when viewed in the inspector won't show a format in the platform override's dropdown list, it'll just be a blank box, but it will show as being an RFloat in the preview window.

    Another oddity is Unity's handling of .exr files is completely hosed if you're using gamma color space for your project. The imported asset will get transformed into sRGB space, and clamped!
     
  4. GuitarBro

    GuitarBro

    Joined:
    Oct 9, 2014
    Posts:
    179
    Oh wow, how have I not heard of AssetPostprocessor until today? That sounds super helpful, I'll take a look. Thanks!

    (Also I'm using linear color space already so the sRGB thing shouldn't affect me, but that is quite strange.)
     
  5. GuitarBro

    GuitarBro

    Joined:
    Oct 9, 2014
    Posts:
    179
    Interesting. Looks like RFloat was added to TextureImporterFormat in 2018.3 (my project is currently 2018.2). That's kind of annoying, but I've been meaning to upgrade for a while now anyways and I guess this is as good of an excuse as any to do so.
     
    bgolus likes this.
  6. GuitarBro

    GuitarBro

    Joined:
    Oct 9, 2014
    Posts:
    179
    That did the trick! Upgraded to 2018.3 and RFloat was there in the TextureImporterFormat enum, just as the docs said. Made an AssetPostprocessor and it imported the EXR sucessfully!

    In the event that someone else stumbles upon this same problem, here's the script I wrote:
    Code (CSharp):
    1. using UnityEditor;
    2.  
    3. class RFloatImport : AssetPostprocessor {
    4.     string[] platforms = { "Standalone" };
    5.  
    6.     void OnPreprocessTexture() {
    7.         if (assetPath.Contains("_RF")) {
    8.             TextureImporter textureImporter = (TextureImporter)assetImporter;
    9.             textureImporter.mipmapEnabled = false;
    10.             textureImporter.sRGBTexture = false;
    11.             textureImporter.textureType = TextureImporterType.SingleChannel;
    12.             textureImporter.textureShape = TextureImporterShape.Texture2D;
    13.             textureImporter.npotScale = TextureImporterNPOTScale.None;
    14.  
    15.             TextureImporterPlatformSettings tips = new TextureImporterPlatformSettings();
    16.             tips.format = TextureImporterFormat.RFloat;
    17.             tips.textureCompression = TextureImporterCompression.Uncompressed;
    18.             for (int i = 0; i < platforms.Length; i++) {
    19.                 textureImporter.SetPlatformTextureSettings(tips);
    20.             }
    21.         }
    22.     }
    23. }
     
    eamonwoortman likes this.
  7. eamonwoortman

    eamonwoortman

    Joined:
    Jan 11, 2017
    Posts:
    3
    Thanks GuitarBro!
    Used the same technique to force my EXR texture to `RGBAFloat`.
     
    GuitarBro likes this.