Search Unity

Help Reconstructing a Normal Map from a Swizzled map using a compute shader

Discussion in 'Shaders' started by Jaimi, Jan 11, 2021.

  1. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,208
    I'm trying to reconstruct a normal map texture from a swizzled normal map. These normal maps are generated at runtime (it's UMA). I've attempted to make a compute shader, copying the "UnpackNormalAGorRG" macro.

    Code (CSharp):
    1. void NormalConverter(uint3 id : SV_DispatchThreadID)
    2. {
    3. #pragma kernel NormalConverter
    4. Texture2D<float4> Input;
    5. RWTexture2D<float3> Result;
    6. [numthreads(1, 1, 1)]
    7. void NormalConverter(uint3 id : SV_DispatchThreadID)
    8. {
    9.     float2 src = float2(id.x, id.y);
    10.     float4 packednormal = Input[src];
    11.     float3 normal;
    12.     // This do the trick
    13.     packednormal.x *= packednormal.w;
    14.     normal.xy = packednormal.xy * 2 - 1;
    15.     normal.z = sqrt(1 - saturate(dot(normal.xy, normal.xy)));
    16.     Result[id.xy] = (normal * 0.5) + 0.5;
    17. }
    18. }
    The only problem is... it doesn't work. It returns back a normal map that is one shade of blue for everything. I know the texture is being written to (I generated a gradient in it just to verify). I've also verified the texture going in is correct (I've saved it to disk -- it even works as a normal map, if you don't set it to "normal map" in the import settings).

    I'm a newbie at compute shaders, so obviously I've done something completely wrong.

    Here's how I'm calling it (normalMap is a standard Texture2D that contains the swizzled normal map).

    Code (CSharp):
    1.     RenderTexture normalMapRenderTex = new RenderTexture(normalMap.width, normalMap.height, 24);
    2.             normalMapRenderTex.enableRandomWrite = true;
    3.             normalMapRenderTex.Create();
    4.             normalMapConverter.SetTexture(kernel, "Input", normalMap);
    5.             normalMapConverter.SetTexture(kernel, "Result", normalMapRenderTex);
    6.             normalMapConverter.Dispatch(kernel, normalMap.width, normalMap.height, 1);
     
    Last edited: Jan 11, 2021
  2. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,208
    in short, this works if you pass it a RenderTexture for input instead of a Texture2D. No idea why that is required.