Search Unity

Selectively darken bright parts of Rendertexture?

Discussion in 'Shaders' started by christougher, Feb 1, 2020.

  1. christougher

    christougher

    Joined:
    Mar 6, 2015
    Posts:
    558
    Hi, I'm super noob when it comes to shaders... hoping for some help on what is hopefully a simple problem to fix... I'm using ARFoundation and getting the phone's camera image to blit to a rendertexture to make reflection probes. Some of the shaders that rely on the reflection probe get messed up/washed out if the colors are too bright or too white.

    Here is the shader code that creates the skybox from the Rendertexture:

    Code (CSharp):
    1. Shader "AR/ARSkybox"
    2. {
    3.     Properties
    4.     {
    5.         _LightingTex("Render Texture", 2D) = "black" {}
    6.     }
    7.  
    8.     CGINCLUDE
    9.  
    10.     #include "UnityCG.cginc"
    11.  
    12.     struct appdata
    13.     {
    14.         float4 position : POSITION;
    15.         float3 normal : NORMAL;
    16.         float3 texcoord : TEXCOORD0;
    17.     };
    18.  
    19.     struct v2f
    20.     {
    21.         float4 position : SV_POSITION;
    22.         float2 texcoord : TEXCOORD0;
    23.     };
    24.  
    25.     // This relies on a RenderTexture of this name being created in ARCoreCameraRenderTexture.cs.
    26.     sampler2D _LightingTex;
    27.     float4x4 _WorldToCameraMatrix;
    28.  
    29.     float2 SphereMapUVCoords( float3 viewDir, float3 normal )
    30.     {
    31.         // Sphere mapping. Find reflection and tranform into UV coords.
    32.         // Heavily inspired by https://www.clicktorelease.com/blog/creating-spherical-environment-mapping-shader/
    33.         float3 reflection = reflect(-viewDir, normal);
    34.         float m = 2. * sqrt(
    35.             pow(reflection.x, 2.) +
    36.             pow(reflection.y, 2.) +
    37.             pow(reflection.z + 1., 2.)
    38.         );
    39.         return reflection.xy / m + .5;
    40.     }
    41.  
    42.     v2f vert(appdata v)
    43.     {
    44.         // Create a sphere map with a texture whose center is at the viewDir/sphere intersection.
    45.         // The texture is wrapped around the sphere so that the corners meet directly behind the camera.
    46.         // To do this we could operate in static viewDir (0,0,1) space. We always want to look at the center on the texture.
    47.         // When we move the phone, there is no need to change the view direction.
    48.         // When rendering a skybox, the view direction is altered for each face. Grab the world space view direction to each vert
    49.         //  then reverse the camera's view direction, bringing it back to view space.
    50.         float3 viewDir = -normalize(WorldSpaceViewDir(v.position));
    51.         viewDir = mul(_WorldToCameraMatrix, float4(viewDir,0));
    52.  
    53.         v2f o;
    54.         o.position = UnityObjectToClipPos(v.position);
    55.         o.texcoord = SphereMapUVCoords(viewDir, v.normal);
    56.  
    57.         return o;
    58.     }
    59.  
    60.     fixed4 frag(v2f i) : COLOR
    61.     {
    62.         return tex2D(_LightingTex, i.texcoord);
    63.     }
    64.  
    65.     ENDCG
    66.  
    67.     SubShader
    68.     {
    69.         Tags{ "RenderType" = "Background" "Queue" = "Background" }
    70.             Pass
    71.         {
    72.             ZWrite Off
    73.             Cull Off
    74.             Fog{ Mode Off }
    75.             CGPROGRAM
    76. #pragma fragmentoption ARB_precision_hint_fastest
    77. #pragma vertex vert
    78. #pragma fragment frag
    79.             ENDCG
    80.         }
    81.     }
    82. }
    I'm wondering if there is a way to selectively darken the brighter areas of the rendertexture input, hopefully without killing performance on mobile... Perhaps limiting RGB values to less then 200??? I'm hoping there's an easy/cheap way to do this in the "fixed4 frag(v2f i) : COLOR" section...
     
  2. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,550
    In the frag, instead of instantly returning the result of tex2D(), store the result:
    fixed4 col = tex2D(_LightingTex, i.texcoord);


    Now you can do whatever simple math on the R,G,B components of
    col
    , and then
    return col;
    .

    You wouldn't really want to limit the individual values to 200 though, because that will cause color shift. It would be better to do some scaling based on the combined r+g+b value.
     
    christougher likes this.
  3. christougher

    christougher

    Joined:
    Mar 6, 2015
    Posts:
    558
    Thanks so much for the pointers! I think I got it figured out! :D