Search Unity

Bug RenderTexture for CustomPass contains incorrect values.

Discussion in 'High Definition Render Pipeline' started by Shisha_x, Oct 19, 2022.

  1. Shisha_x

    Shisha_x

    Joined:
    May 12, 2019
    Posts:
    9
    Hello,

    I have an issue with passing to the custom pass shader a RenderTexture Float32 with negative values.
    Example:
    1) I have 2 cameras
    - 1st. camera just renders 5 cubes with simple materials:
    upload_2022-10-19_22-40-0.png

    - second one render only one cube to the Created RenderTexture with ARGBFloat type with this shader:
    Code (CSharp):
    1. Shader "Unlit/CubeShader"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Texture", 2D) = "white" {}
    6.     }
    7.     SubShader
    8.     {
    9.         Tags { "RenderType"="Opaque" }
    10.         LOD 100
    11.  
    12.         Pass
    13.         {
    14.             CGPROGRAM
    15.             #pragma vertex vert
    16.             #pragma fragment frag
    17.             // make fog work
    18.             #pragma multi_compile_fog
    19.  
    20.             #include "UnityCG.cginc"
    21.  
    22.             struct appdata
    23.             {
    24.                 float4 vertex : POSITION;
    25.                 float2 uv : TEXCOORD0;
    26.             };
    27.  
    28.             struct v2f
    29.             {
    30.                 float2 uv : TEXCOORD0;
    31.                 UNITY_FOG_COORDS(1)
    32.                 float4 vertex : SV_POSITION;
    33.             };
    34.  
    35.             sampler2D _MainTex;
    36.             float4 _MainTex_ST;
    37.  
    38.             v2f vert (appdata v)
    39.             {
    40.                 v2f o;
    41.                 o.vertex = UnityObjectToClipPos(v.vertex);
    42.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    43.                 UNITY_TRANSFER_FOG(o,o.vertex);
    44.                 return o;
    45.             }
    46.  
    47.             fixed4 frag (v2f i) : SV_Target
    48.             {
    49.                 return float4(-0.5, -0.5, 0, 1);
    50.             }
    51.             ENDCG
    52.         }
    53.     }
    54. }
    55.  


    upload_2022-10-19_22-41-48.png

    2) The 1st Camera has the CustomPass:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Rendering.HighDefinition;
    3. using UnityEngine.Rendering;
    4. using UnityEngine.Experimental.Rendering;
    5. using System.Runtime.InteropServices;
    6. using System;
    7. using Unity.Collections;
    8.  
    9. class PassForMaincamera : CustomPass
    10. {
    11.     public LayerMask layer;
    12.     public Shader shader;
    13.     Material mat;
    14.     RTHandle rtHandle;
    15.     Texture2D texture;
    16.     [SerializeField]
    17.     RenderTexture renderTexture; // RenderTexture from the second camera
    18.  
    19.     // It can be used to configure render targets and their clear state. Also to create temporary render target textures.
    20.     // When empty this render pass will render to the active camera render target.
    21.     // You should never call CommandBuffer.SetRenderTarget. Instead call <c>ConfigureTarget</c> and <c>ConfigureClear</c>.
    22.     // The render pipeline will ensure target setup and clearing happens in an performance manner.
    23.     protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd)
    24.     {
    25.         mat = CoreUtils.CreateEngineMaterial(shader);
    26.         rtHandle = RTHandles.Alloc(
    27.             Vector2.one, TextureXR.slices, dimension: TextureDimension.Tex2D,
    28.             colorFormat: GraphicsFormat.R32G32B32A32_SFloat,
    29.             useDynamicScale: true, name: "Anything");
    30.  
    31.         //This is just test texture for shader, when I pass it - OK!
    32.         var w = 5;
    33.         var h = 5;
    34.         var s = w * h;
    35.         texture = new Texture2D(w, h, TextureFormat.RGBAFloat, false);
    36.         var texData = new float[s * 4];
    37.  
    38.         for(var i = 0; i < texData.Length; i += 4)
    39.         {
    40.             texData[i + 0] = -0.5f;
    41.             texData[i + 1] = -0.5f;
    42.             texData[i + 2] = 0.0f;
    43.             texData[i + 3] = 1f;
    44.         }
    45.         var byteArray = new byte[s * sizeof(float) * 4];
    46.         Buffer.BlockCopy(texData, 0, byteArray, 0, byteArray.Length);
    47.  
    48.         texture.LoadRawTextureData(byteArray);
    49.         texture.Apply();
    50.  
    51.     }
    52.  
    53.     protected override void Execute(CustomPassContext ctx)
    54.     {
    55.         CoreUtils.SetRenderTarget(ctx.cmd, rtHandle, ClearFlag.Color);
    56.         CustomPassUtils.DrawRenderers(ctx, layer);
    57.  
    58.         ctx.propertyBlock.SetTexture("_texture_float", renderTexture);
    59.         ctx.propertyBlock.SetTexture("_mainTex", rtHandle);
    60.  
    61.         // Render the outline buffer fullscreen
    62.         CoreUtils.SetRenderTarget(ctx.cmd, ctx.cameraColorBuffer, ClearFlag.None);
    63.         CoreUtils.DrawFullScreen(ctx.cmd, mat, ctx.propertyBlock, shaderPassId: 0);
    64.     }
    65.  
    66.     protected override void Cleanup()
    67.     {
    68.         CoreUtils.Destroy(mat);
    69.         rtHandle.Release();
    70.     }
    71. }
    And the Shader code is:
    Code (CSharp):
    1. Shader "FullScreen/FullScreenCustomPass"
    2. {
    3.     HLSLINCLUDE
    4.  
    5.     #pragma vertex Vert
    6.  
    7.     #pragma target 4.5
    8.     #pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch
    9.  
    10.     #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/CustomPass/CustomPassCommon.hlsl"
    11.  
    12.     // The PositionInputs struct allow you to retrieve a lot of useful information for your fullScreenShader:
    13.     // struct PositionInputs
    14.     // {
    15.     //     float3 positionWS;  // World space position (could be camera-relative)
    16.     //     float2 positionNDC; // Normalized screen coordinates within the viewport    : [0, 1) (with the half-pixel offset)
    17.     //     uint2  positionSS;  // Screen space pixel coordinates                       : [0, NumPixels)
    18.     //     uint2  tileCoord;   // Screen tile coordinates                              : [0, NumTiles)
    19.     //     float  deviceDepth; // Depth from the depth buffer                          : [0, 1] (typically reversed)
    20.     //     float  linearDepth; // View space Z coordinate                              : [Near, Far]
    21.     // };
    22.  
    23.     // To sample custom buffers, you have access to these functions:
    24.     // But be careful, on most platforms you can't sample to the bound color buffer. It means that you
    25.     // can't use the SampleCustomColor when the pass color buffer is set to custom (and same for camera the buffer).
    26.     // float4 SampleCustomColor(float2 uv);
    27.     // float4 LoadCustomColor(uint2 pixelCoords);
    28.     // float LoadCustomDepth(uint2 pixelCoords);
    29.     // float SampleCustomDepth(float2 uv);
    30.  
    31.     // There are also a lot of utility function you can use inside Common.hlsl and Color.hlsl,
    32.     // you can check them out in the source code of the core SRP package.
    33.  
    34.  
    35.     sampler2D_float _texture_float;
    36.     sampler2D _mainTex;
    37.  
    38.     float4 FullScreenPass(Varyings varyings) : SV_Target
    39.     {
    40.         UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(varyings);
    41.         float depth = LoadCameraDepth(varyings.positionCS.xy);
    42.         PositionInputs posInput = GetPositionInput(varyings.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V);
    43.         float3 viewDirection = GetWorldSpaceNormalizeViewDir(posInput.positionWS);
    44.         // Load the camera color buffer at the mip 0 if we're not at the before rendering injection point
    45.         //if (_CustomPassInjectionPoint != CUSTOMPASSINJECTIONPOINT_BEFORE_RENDERING)
    46.             //color = float4(CustomPassLoadCameraColor(varyings.positionCS.xy, 0), 1);
    47.  
    48.         // Load the camera color buffer at the mip 0 if we're not at the before rendering injection point
    49.  
    50.  
    51.         // When sampling RTHandle texture, always use _RTHandleScale.xy to scale your UVs first.
    52.         float2 uv = posInput.positionNDC.xy * _RTHandleScale.xy;
    53.         float4 test_tex = tex2D(_texture_float, uv);
    54.         float4 color = tex2D(_mainTex, uv);
    55.  
    56.         float r = abs(test_tex.r);
    57.         float g = abs(test_tex.g);
    58.  
    59.         return float4(r, g, 0, 1);
    60.     }
    61.  
    62.     ENDHLSL
    63.  
    64.     SubShader
    65.     {
    66.         Tags{ "RenderPipeline" = "HDRenderPipeline" }
    67.         Pass
    68.         {
    69.             Name "Custom Pass 0"
    70.  
    71.             ZWrite Off
    72.             ZTest Always
    73.             Blend SrcAlpha OneMinusSrcAlpha
    74.             Cull Off
    75.  
    76.             HLSLPROGRAM
    77.                 #pragma fragment FullScreenPass
    78.             ENDHLSL
    79.         }
    80.     }
    81.     Fallback Off
    82. }
    83.  
    Basically, I expect to see the yellow cube, but it shows nothing, if I past positive values for Cube shader - it works. It seems like RenderTextures casts to int type or something else. Also It works fine with the Built In RP. Seems Like a bug....

    Does anybody know where I did wrong?
    Unity Version: 2021.3.10f1
     
    Last edited: Oct 21, 2022
    Iternity likes this.
  2. Shisha_x

    Shisha_x

    Joined:
    May 12, 2019
    Posts:
    9
    Also, some screenshots of how it looks like:
    upload_2022-10-20_11-11-37.png

    And MainCamera CustomPass settings:
    upload_2022-10-20_11-12-36.png
     
    avask2013 likes this.
  3. Shisha_x

    Shisha_x

    Joined:
    May 12, 2019
    Posts:
    9
    Ok, Lets try another one example...

    upload_2022-10-25_16-54-33.png

    This is an example of what I want to see:
    1) Camera2 renders the sphere with this shader:
    Code (CSharp):
    1. Shader "Unlit/Ball"
    2. {
    3.     SubShader
    4.     {
    5.         Tags { "RenderType"="Opaque" }
    6.         LOD 100
    7.  
    8.         Pass
    9.         {
    10.             CGPROGRAM
    11.             #pragma vertex vert
    12.             #pragma fragment frag
    13.  
    14.             #include "UnityCG.cginc"
    15.  
    16.             struct appdata
    17.             {
    18.                 float4 vertex : POSITION;
    19.                 float2 uv : TEXCOORD0;
    20.             };
    21.  
    22.             struct v2f
    23.             {
    24.                 float2 uv : TEXCOORD0;
    25.                 float4 vertex : SV_POSITION;
    26.             };
    27.  
    28.             v2f vert (appdata v)
    29.             {
    30.                 v2f o;
    31.                 o.vertex = UnityObjectToClipPos(v.vertex);
    32.                 return o;
    33.             }
    34.  
    35.             fixed4 frag (v2f i) : SV_Target
    36.             {          
    37.                 return float4(-0.5, 0, 0, 1);
    38.             }
    39.             ENDCG
    40.         }
    41.     }
    42. }
    And it renders to the RenderTexture as output with ARGB32 float format:
    upload_2022-10-25_16-59-31.png


    2) And I have the RawImage to draw this RenderTexture(RT1) with this shader:
    upload_2022-10-25_17-1-26.png

    Code (CSharp):
    1. Shader "Unlit/ImageMat"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Texture", 2D) = "white" {}
    6.     }
    7.     SubShader
    8.     {
    9.         Tags { "RenderType"="Opaque" }
    10.         LOD 100
    11.  
    12.         Pass
    13.         {
    14.             CGPROGRAM
    15.             #pragma vertex vert
    16.             #pragma fragment frag
    17.  
    18.             #include "UnityCG.cginc"
    19.  
    20.             struct appdata
    21.             {
    22.                 float4 vertex : POSITION;
    23.                 float2 uv : TEXCOORD0;
    24.             };
    25.  
    26.             struct v2f
    27.             {
    28.                 float2 uv : TEXCOORD0;
    29.                 float4 vertex : SV_POSITION;
    30.             };
    31.  
    32.             sampler2D _MainTex;
    33.             float4 _MainTex_ST;
    34.  
    35.             v2f vert (appdata v)
    36.             {
    37.                 v2f o;
    38.                 o.vertex = UnityObjectToClipPos(v.vertex);
    39.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    40.                 return o;
    41.             }
    42.  
    43.             fixed4 frag (v2f i) : SV_Target
    44.             {
    45.                 fixed4 col = tex2D(_MainTex, i.uv);
    46.  
    47.                 float r = abs(col.r);
    48.  
    49.                 return float4(r, 0, 0, 1);
    50.             }
    51.             ENDCG
    52.         }
    53.     }
    54. }
    And as you could see it works as expected with Built-in RP. But When I try the same scene with HDRP, the RawImage shows only black color. It Seems like Camera renders only on ARGB32
    HDRP Version 12.1.7
     
    Last edited: Dec 15, 2022
  4. Shisha_x

    Shisha_x

    Joined:
    May 12, 2019
    Posts:
    9
    Still no answer...