Search Unity

Normal Viewer Shaders Confusion ???

Discussion in 'Shaders' started by DouglasPotesta, Nov 21, 2017.

  1. DouglasPotesta

    DouglasPotesta

    Joined:
    Nov 6, 2014
    Posts:
    109
    Hey Guys I've been hacking together a normal viewer replacement shader. I was able to use a lot of posts on the forum to put it together.
    It appears to work, but there are still a few things I'm confused about.

    Mainly I just want to confirm or rectify my understanding of the process of the shader below.

    Code (CSharp):
    1. struct v2f {
    2.                 float3 worldPos : TEXCOORD0;
    3.                 // these three vectors will hold a 3x3 rotation matrix
    4.                 // that transforms from tangent to world space
    5.                 half3 tspace0 : TEXCOORD1; // tangent.x, bitangent.x, normal.x
    6.                 half3 tspace1 : TEXCOORD2; // tangent.y, bitangent.y, normal.y
    7.                 half3 tspace2 : TEXCOORD3; // tangent.z, bitangent.z, normal.z
    8.                 float2 uv : TEXCOORD4;
    9.                 float4 pos : SV_POSITION;
    10.             };
    11.  
    12.             v2f vert (float4 vertex : POSITION, float3 normal : NORMAL, float4 tangent : TANGENT, float2 uv : TEXCOORD0)
    13.             {
    14.                 v2f o;
    15.                 o.pos = UnityObjectToClipPos(vertex);
    16.                 o.worldPos = mul(unity_ObjectToWorld, vertex).xyz;
    17.                 o.uv = TRANSFORM_TEX(uv, _MainTex);
    18.                 half3 wNormal = UnityObjectToWorldNormal(normal);
    19.                 half3 wTangent = UnityObjectToWorldDir(tangent.xyz);
    20.                 half tangentSign = tangent.w * unity_WorldTransformParams.w;
    21.                 half3 wBitangent = cross(wNormal, wTangent) * tangentSign;
    22.                 o.tspace0 = half3(wTangent.x, wBitangent.x, wNormal.x);
    23.                 o.tspace1 = half3(wTangent.y, wBitangent.y, wNormal.y);
    24.                 o.tspace2 = half3(wTangent.z, wBitangent.z, wNormal.z);
    25.                 return o;
    26.             }
    27.  
    28.             fixed4 frag (v2f i) : SV_Target
    29.             {
    30.                 half3 tnormal = UnpackNormal(tex2D(_BumpMap, i.uv));
    31.                 half3 worldNormal;
    32.                 worldNormal.x = dot(i.tspace0, tnormal);
    33.                 worldNormal.y = dot(i.tspace1, tnormal);
    34.                 worldNormal.z = dot(i.tspace2, tnormal);
    35.  
    36.                 fixed4 c = 0;
    37.                 c.rgb = normalize(mul((float3x3)UNITY_MATRIX_V, worldNormal))/2+0.5;
    38.                 return c;
    39.             }
    My understanding so far is that I am first transforming the combined mesh normal and normal map in the frag function into worldnormals. Then from there I am transforming them into view space using UNITY_MATRIX_V.

    So finally it outputs an objects normals in the viewports view space.

    Please correct me if anything I said is wrong.
     
    dval likes this.
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,348
    Looks correct to me, though you’re unnecessary computing and passing the world space position in the vertex shader to the fragment shader.

    Is something in particular not behaving as you would expect from the above code?
     
  3. DouglasPotesta

    DouglasPotesta

    Joined:
    Nov 6, 2014
    Posts:
    109
    Well it works when replacing the standard shader, but if I’m replacing the basic unlit shader there’s wierd behavior towards the poles of a sphere primitive. I’ll post a picture when I get to my computer.
     
  4. DouglasPotesta

    DouglasPotesta

    Joined:
    Nov 6, 2014
    Posts:
    109
    The left is the standard, and the right is the unity default unlit shader.
     

    Attached Files:

  5. DouglasPotesta

    DouglasPotesta

    Joined:
    Nov 6, 2014
    Posts:
    109
    Anybody know why this behavior may be happening?
     
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,348
    I wonder if it might be a bug, like the mesh's tangents aren't being passed along. What happens if you try rendering just the v.tangent without doing anything to convert it? I wonder if the unlit sphere ends up rendering black.
     
  7. DouglasPotesta

    DouglasPotesta

    Joined:
    Nov 6, 2014
    Posts:
    109
    The left is standard the right is unlit
    upload_2017-11-25_1-40-10.png

    They appear to come out the same.
     
  8. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,348
    Try the normal, then try the normal map. Make sure they’re all working as expected.
     
    DouglasPotesta likes this.
  9. DouglasPotesta

    DouglasPotesta

    Joined:
    Nov 6, 2014
    Posts:
    109
    Thanks for the help I figured out that it was being caused by not assigning a normal map to it. Now I simply added a shader feature _NormalMap, and then returned just the viewspace normal from the mesh if no normal map is defined.

    Left is standard, right is unlit.
    upload_2017-11-25_2-28-38.png
     
    bgolus likes this.