Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question How does exposure post processing work?

Discussion in 'High Definition Render Pipeline' started by TOES, Mar 30, 2023.

  1. TOES

    TOES

    Joined:
    Jun 23, 2017
    Posts:
    134
    I want to make my own Exposure shader, taking the raw floating point rendered output and applying exposure to it, mimicking the one found in Unitys built in Exposure post processing.

    But I have trouble getting the same results as the one built into Unity (I cannot use this though, as I will do the exposure in a program outside Unity, I just want the exposure values to give the exact same results as what Unity does).

    Considering a simple scene with sunlight at the default 100.000 LUX, the camera is inside a building looking out at the terrain that is brightly lit. Since the inside is dark and the outside is lit by the sun, the difference in intensity is great, and I found it hard to come up with an exposure algorithm that works as well as the one built into Unity.

    In my scene the Unity exposure post process does a good job, and you can see both the outside and the inside without over or underexposing.

    My code fails to do this though:

    Code (CSharp):
    1. float4 CustomPostProcess(Varyings input) : SV_Target
    2. {
    3.     UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
    4.  
    5.     float4 sourceColor = SAMPLE_TEXTURE2D_X(_MainTex, s_linear_clamp_sampler, input.texcoord);
    6.     float3 exposedColor = sourceColor.rgb * exp2(-_fixedExposure);
    7.     return float4(exposedColor, sourceColor.a);
    8. }
    There is not one good value for _fixedExposure that will allow both the very bright and the dark areas to not be underexposed/overexposed like the built in Unity Exposure post processing can.

    Does anyone know what method Unity uses to apply the exposure in post process? Is the source code for Unitys Exposure post process available anywhere?
     
  2. OBiwer

    OBiwer

    Joined:
    Aug 2, 2022
    Posts:
    61
    from the exposure shader:

    Code (CSharp):
    1.  
    2. #define ParamEV100                      _ExposureParams.y
    3. #define ParamExposureCompensation       _ExposureParams.x
    4.  
    5.  
    6.  
    7. //
    8. // Fixed exposure
    9. // Doesn't do anything fancy, simply copies the exposure & clamp values set in the volume system
    10. //
    11. [numthreads(1,1,1)]
    12. void KFixedExposure(uint2 dispatchThreadId : SV_DispatchThreadID)
    13. {
    14.     float ev100 = ParamEV100;
    15.     ev100 -= ParamExposureCompensation;
    16.     _OutputTexture[dispatchThreadId] = float2(ConvertEV100ToExposure(ev100, LensImperfectionExposureScale), ev100);
    17. }
    18.  

    couldn't find the shader definition for ConvertEV100ToExposure, but the version in color utils:

    Code (CSharp):
    1.        
    2.         static public float lensImperfectionExposureScale
    3.         {
    4.             get => (78.0f / (100.0f * s_LensAttenuation));
    5.         }
    6.  
    7.  
    8.         /// <summary>
    9.         /// Converts an exposure value (EV100) to a linear multiplier.
    10.         /// </summary>
    11.         /// <param name="EV100">The exposure value to convert, in EV100.</param>
    12.         /// <returns>A linear multiplier.</returns>
    13.         public static float ConvertEV100ToExposure(float EV100)
    14.         {
    15.             // Compute the maximum luminance possible with H_sbs sensitivity
    16.             // maxLum = 78 / ( S * q ) * N^2 / t
    17.             //        = 78 / ( S * q ) * 2^ EV_100
    18.             //        = 78 / (100 * s_LensAttenuation) * 2^ EV_100
    19.             //        = lensImperfectionExposureScale * 2^ EV
    20.             // Reference: http://en.wikipedia.org/wiki/Film_speed
    21.             float maxLuminance = lensImperfectionExposureScale * Mathf.Pow(2.0f, EV100);
    22.             return 1.0f / maxLuminance;
    23.         }
     
  3. jjejj87

    jjejj87

    Joined:
    Feb 2, 2013
    Posts:
    1,106
    Is setting exposure to "Fixed" not achieving what you intend? I usually work with Physical Camera + Fixed to do it. Obviously the physically correctness goes out the window and have to hand dial point lights and etc.
     
  4. impheris

    impheris

    Joined:
    Dec 30, 2009
    Posts:
    1,511
    excuse me, can i know why you want to mimic the Unity's built in Exposure? please
     
  5. OBiwer

    OBiwer

    Joined:
    Aug 2, 2022
    Posts:
    61
    Well ... he already did:

    he's processing the image outside of unity, but his exposure effect leaves it's image over/underexposed in some spots but he does not have the same issue with unitys builtin solution, so he wonders how they do it.

    I guess he could also live with a solution different to unitys, if it would esthetically pleasing.
     
  6. TOES

    TOES

    Joined:
    Jun 23, 2017
    Posts:
    134
    Because I am exporting the full raw HDR rendered image, and I need to make my own dynamic exposure externally in a separate program that is not (and cannot be) Unity based.

    I am trying to figure out how to mimic the exposure algorithm used in Unity, as it does a good job of showing both under and overexposed areas together. It works different to every HDR based exposure I have tried, for example the one in Photoshop, which use the method I indicate in my first post.

    It looks like some Tonemapping might be involved in the Unity version? But when applying Filmic or AES I get washed out results...
     
  7. SebLazyWizard

    SebLazyWizard

    Joined:
    Jun 15, 2018
    Posts:
    220