Search Unity

Getting the alpha value of opaque geometry in a render texture.

Discussion in 'Shaders' started by Mutimir, Aug 30, 2019.

  1. Mutimir

    Mutimir

    Joined:
    Dec 6, 2018
    Posts:
    36
    I am interested in storing some values from opaque objects into the alpha channel of a render texture. I got the idea from listening to a Unite talk where they used the trick to crate a bloom post effect without using hdr. Here is the link

    .

    I tried using CommandBuffers to get the texture right after Opaque geometry is rendered:

    Code (CSharp):
    1.  
    2. myCam = this.gameObject.GetComponent<Camera>();
    3.  
    4.         if (XRSettings.enabled)
    5.             originalTextureDescriptor = XRSettings.eyeTextureDesc;
    6.         else
    7.             originalTextureDescriptor = new RenderTextureDescriptor(Screen.width, Screen.height); // Not XR
    8.  
    9.         originalTextureDescriptor.colorFormat = RenderTextureFormat.ARGB32;
    10.  
    11.         CommandBuffer buf = new CommandBuffer();
    12.         buf.name = "grab alpha";
    13.  
    14.         int screenCopyID = Shader.PropertyToID("_AlphaMask");
    15.         buf.GetTemporaryRT(screenCopyID, originalTextureDescriptor);
    16.         buf.Blit(BuiltinRenderTextureType.CurrentActive, screenCopyID);
    17.         buf.SetGlobalTexture("_HDRmask", screenCopyID);
    18.  
    19.         myCam.AddCommandBuffer(CameraEvent.AfterForwardOpaque, buf);

    And use this test surface shader for opaque objects:


    Code (CSharp):
    1.  SubShader
    2.     {
    3.         Tags { "RenderType"="Opaque" }
    4.         LOD 200
    5.  
    6.         Blend SrcAlpha OneMinusSrcAlpha, One One
    7.         ColorMask RGBA
    8.         ZWrite On
    9.  
    10.         CGPROGRAM
    11.         #pragma surface surf Lambert keepalpha
    12.         #pragma target 3.0
    13.  
    14.  
    15.         sampler2D _MainTex;
    16.  
    17.         struct Input
    18.         {
    19.             float2 uv_MainTex;
    20.         };
    21.  
    22.         half _Glossiness;
    23.         half _Metallic;
    24.         fixed4 _Color;
    25.  
    26.         UNITY_INSTANCING_BUFFER_START(Props)
    27.             // put more per-instance properties here
    28.         UNITY_INSTANCING_BUFFER_END(Props)
    29.  
    30.         void surf (Input IN, inout SurfaceOutputStandard o)
    31.         {
    32.             // Albedo comes from a texture tinted by color
    33.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    34.             o.Albedo = c.rgb;
    35.             o.Alpha = c.a;
    36.         }
    Even though i use ColorMask RGBA and keepalpha tag all the opaque geometry has alpha 1 in the render texture. My cameras clear flag is set to solid color (0,0,0,0). Any advice would be appreciated.
     
  2. Mutimir

    Mutimir

    Joined:
    Dec 6, 2018
    Posts:
    36
    In the surface shader the declaration should be: void surf (Input IN, inout SurfaceOutput o).
    So i figured that the result from the surface shader is passed through the lighting code declared in a cginc that for some types changes the alpha back to 1. Writing your own lighting code solves the problem, and there is no specific need to use command buffers for this.