Search Unity

Resolved Lighting problem with normal maps from texture array

Discussion in 'General Graphics' started by KayH, May 29, 2020.

  1. KayH

    KayH

    Joined:
    Jan 6, 2017
    Posts:
    110
    I use an instanced shader to render many blocks with different textures in one draw call. The problem is that the lighting is wrong for many of these blocks:
    faulty_lighting02.png faulty_lighting01.png
    Some blocks that face away from the sun get brightly lit and vice versa. I'm guessing that all blocks get lit for a certain rotation (that of the first block rendered maybe) and the actual orientation of each block is ignored.

    How can this be fixed?

    I'm on version 2019.3.15f1 (latest at the time of writing). I'm using forward shading. Switching to deferred didn't fix the problem. Deferred is not really an option though since that caused strange bugs on Quest (rendering only one eye and everything became brightly lit).

    Here's my shader:

    Code (CSharp):
    1. Shader "Brick/MultiTextureSurfaceInstanced"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex("MainTex", 2DArray) = "" {}
    6.         _BumpMap("NormalMap", 2DArray) = "" {}
    7.         _TextureIndexOffset ("TextureIndexOffset", Vector) = (0, 0, 0, 0)
    8.          _Glossiness("Smoothness", Range(0,1)) = 0.5
    9.          _Metallic("Metallic", Range(0,1)) = 0.0
    10.     }
    11.  
    12.     SubShader
    13.     {
    14.         Tags { "RenderType"="Opaque" }
    15.  
    16.         CGPROGRAM
    17.  
    18.         #pragma surface surf Standard fullforwardshadows
    19.         #pragma target 3.5
    20.         #include "UnityCG.cginc"
    21.  
    22.         UNITY_DECLARE_TEX2DARRAY(_MainTex);
    23.         UNITY_DECLARE_TEX2DARRAY(_BumpMap);
    24.         half _Glossiness;
    25.         half _Metallic;
    26.  
    27.         struct Input
    28.         {
    29.             float2 uv_MainTex;
    30.             float2 uv_BumpMap;
    31.         };
    32.  
    33.         UNITY_INSTANCING_BUFFER_START(Props)
    34.             UNITY_DEFINE_INSTANCED_PROP(float4, _TextureIndexOffset)
    35.         UNITY_INSTANCING_BUFFER_END(Props)
    36.  
    37.         void surf (Input IN, inout SurfaceOutputStandard o)
    38.         {
    39.             fixed4 tio = UNITY_ACCESS_INSTANCED_PROP(Props, _TextureIndexOffset);
    40.             fixed4 c = UNITY_SAMPLE_TEX2DARRAY(_MainTex, float3(tio.w * (IN.uv_MainTex.xy + tio.xy), tio.z));
    41.             o.Albedo = c.rgb;
    42.             o.Normal = UnpackNormal(UNITY_SAMPLE_TEX2DARRAY(_BumpMap, float3(tio.w * (IN.uv_BumpMap + tio.xy), tio.z)));
    43.             o.Metallic = _Metallic;
    44.             o.Smoothness = _Glossiness;
    45.             o.Alpha = c.a;
    46.         }
    47.  
    48.         ENDCG
    49.     }
    50.     FallBack "Diffuse"
    51. }
     
  2. KayH

    KayH

    Joined:
    Jan 6, 2017
    Posts:
    110
    I just noticed (from my own screenshots provided here) that the problem seems different from what I described above. The brightly lit blocks are lit from both sides, whereas the non lit ones aren't from either. Still strange, but different kind of strange.

    Any ideas what could cause this behavior?

    Some additional info:

    Groups of blocks of the same color lit in the same way don't just share the same rotation but are also parented in the same containing transform (which has the rotation). But taking a single one of a group out of the container (maintaining the rotation) didn't change the lighting for that block.
     
  3. KayH

    KayH

    Joined:
    Jan 6, 2017
    Posts:
    110
    I updated to 2019.4.1f1. That didn't fix it.

    I enabled shadows. On bricks that are lit on the wrong side, shadows of coins also appear on the wrong side.

    Can someone help please?
     
  4. KayH

    KayH

    Joined:
    Jan 6, 2017
    Posts:
    110
    Some findings:

    1. Problem is not related to instancing. Disabling instancing has no effect.

    2. The problem is caused by normal mapping. If I comment out line 42, lighting and shadows are restored. But I lose my normal mapping.

    When enabled, disregarding the general lighting problem normal mapping works as intended (i.e. the lighting angles align with the texture pattern) but the texture array of the normal maps cannot be properly browsed in the editor, i.e. if I check the slices they're all some salmon pink without any texture. Are there any things to watch out for when using a texture array for normal maps? Anything I could be doing wrong in that regard?

    @Mods, could you please edit the title to say "Lighting problem with normal maps from texture array"? Thanks!
     
    Last edited: Jul 20, 2020
  5. UnityMaru

    UnityMaru

    Community Engagement Manager PSM

    Joined:
    Mar 16, 2016
    Posts:
    1,227
  6. KayH

    KayH

    Joined:
    Jan 6, 2017
    Posts:
    110
    Thanks!
     
  7. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,338
    Going by that last post, my guess is the bug is in the code you have to create the normal map texture array. There's nothing wrong with your shader code that I can see.

    There's nothing super special about creating texture arrays for normal maps apart from them needing to be created with the linear space option set, and otherwise matching the format of the imported normal map texture. In Unity that defaults to DXT5. Then use Graphics.CopyTexture to copy the individual normal map textures into the array.
     
  8. KayH

    KayH

    Joined:
    Jan 6, 2017
    Posts:
    110
    That fixed it, thanks! I guess the lighting angle shifts (borders, contours) were in the right places but the actual angles were distorted by it assuming gamma space.

    Set to resolved. I noticed I could have edited the title myself with thread tools.
     
    Last edited: Jul 23, 2020