Search Unity

Best way to add a Normal Power Slider for Surface Shader?

Discussion in 'Shaders' started by Harrison_Hough, Feb 16, 2017.

  1. Harrison_Hough

    Harrison_Hough

    Joined:
    Dec 3, 2015
    Posts:
    43
    Hey Guys,

    I'm just wondering what the best/most accurate way is to create a Normal scale slider (similar to the Unity Standard shader one). Ideally one that can go from 0 - 3 or even more. I have tried a couple of different ways with mixed results. I have looked briefly at the way Unity does it in their shader but I didnt really understand how to replicate it.

    Any help would be great!

    Here are some examples on the methods I have tried.

    Code (CSharp):
    1. sampler2D _MainTex;
    2.         sampler2D _BumpMap;
    3.  
    4.         struct Input {
    5.             float2 uv_MainTex;
    6.         };
    7.  
    8.         half _Glossiness;
    9.         half _BumpScale;
    10.         half _Metallic;
    11.         fixed4 _Color;
    12.         half3 _NormalDefault;
    13.  
    14.         void surf (Input IN, inout SurfaceOutputStandard o) {
    15.             // Albedo comes from a texture tinted by color
    16.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    17.             o.Albedo = c.rgb;
    18.             // Metallic and smoothness come from slider variables
    19.             o.Metallic = _Metallic;
    20.             o.Smoothness = _Glossiness;
    21.  
    22.             //Method 1
    23.             o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_MainTex) *_BumpScale);
    24.  
    25.             //Method 2
    26.             //_NormalDefault = Half3(128, 128, 255) --found these values online
    27.             o.Normal = lerp(_NormalDefault, UnpackNormal(tex2D(_BumpMap, IN.uv_MainTex)), _BumpScale);
    28.  
    29.  
    30.             //fallback method
    31.             o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_MainTex));
    32.             //o.Normal = _NormalDefault;
    33.             o.Alpha = c.a;
    34.         }
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    UnityStandardUtils.cginc has the one that the Standard shaders use.
    Code (CSharp):
    1. half3 UnpackScaleNormal(half4 packednormal, half bumpScale)
    2. {
    3.     #if defined(UNITY_NO_DXT5nm)
    4.         return packednormal.xyz * 2 - 1;
    5.     #else
    6.         half3 normal;
    7.         normal.xy = (packednormal.wy * 2 - 1);
    8.         #if (SHADER_TARGET >= 30)
    9.             // SM2.0: instruction count limitation
    10.             // SM2.0: normal scaler is not supported
    11.             normal.xy *= bumpScale;
    12.         #endif
    13.         normal.z = sqrt(1.0 - saturate(dot(normal.xy, normal.xy)));
    14.         return normal;
    15.     #endif
    16. }
    The lerp method in your example can work as well, except your _NormalDefault value is for the values of an 8 bit normal map texture, not the actual tangent space normal direction which o.Normal expects and UnpackNormal() returns.

    You could try:
    o.Normal = lerp(half3(0.0, 0.0, 1.0), UnpackNormal(tex2D(_BumpMap, IN.uv_MainTex), _BumpScale);
     
    ifurkend and Harrison_Hough like this.
  3. Harrison_Hough

    Harrison_Hough

    Joined:
    Dec 3, 2015
    Posts:
    43
    Great Thanks that works , I must have missed that!