Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

Standard Shader using HDRP maps

Discussion in 'Graphics Experimental Previews' started by goonter, Jul 19, 2018.

  1. goonter

    goonter

    Joined:
    Aug 31, 2015
    Posts:
    89
    Hello all. I've been doing a lot of testing going back and forth between Standard render pipeline and HDRP so I wrote two versions of the Standard Shader that use HDRP map format for easy swapping back and forth. They don't support all HDRP features but at least you get a basic visual for objects instead of them being invisible. "Standard HD" is for standard Normals, it supports cutout and double sided but not transparency. "Standard HD Obj Normal" is for materials that use object space normals. The texture properties are named like HDRP Lit so you won't have to reassign your textures when you swap back and forth. Enjoy!

    Standard HD

    Code (CSharp):
    1. Shader "Standard HD" {
    2.     Properties{
    3.  
    4.         _BaseColor("BaseColor", Color) = (1,1,1,1)
    5.         _BaseColorMap("BaseColorMap", 2D) = "white" {}
    6.         _MaskMap("MaskMap", 2D) = "white" {}
    7.         _NormalMap("NormalMap", 2D) = "bump" {}     // Tangent space normal map
    8.         _NormalScale("_NormalScale", Range(0.0, 2.0)) = 1
    9.         _Cutoff("Alpha cutoff", Range(0,1)) = 0.5
    10.     }
    11.         SubShader{
    12.         Tags{ "Queue" = "AlphaTest" "RenderType" = "TransparentCutout" }
    13.         //Tags{"RenderType" = "Opaque"}
    14.         LOD 400
    15.  
    16.         CGPROGRAM
    17.         // Physically based Standard lighting model, and enable shadows on all light types
    18. #pragma target 3.0
    19. #pragma surface surf Standard alphatest:_Cutoff addshadow  
    20.  
    21.         float _NormalScale;
    22.     sampler2D _BaseColorMap;
    23.     sampler2D _MaskMap;
    24.     sampler2D _NormalMap;
    25.  
    26.     struct Input {
    27.         float2 uv_BaseColorMap;
    28.     };
    29.  
    30.     fixed4 _BaseColor;
    31.  
    32.     void surf(Input IN, inout SurfaceOutputStandard o) {
    33.  
    34.         fixed4 c = tex2D(_BaseColorMap, IN.uv_BaseColorMap) * _BaseColor;
    35.         fixed4 mask = tex2D(_MaskMap,IN.uv_BaseColorMap);
    36.  
    37.         o.Albedo = c.rgb;
    38.         o.Metallic = mask.r;
    39.         o.Smoothness = mask.a;
    40.         o.Occlusion = mask.g;
    41.         o.Normal = normalize(UnpackScaleNormal(tex2D(_NormalMap, IN.uv_BaseColorMap), _NormalScale));
    42.         o.Alpha = c.a;
    43.     }
    44.     ENDCG
    45.  
    46.  
    47.         Cull front
    48.         CGPROGRAM
    49.         // Physically based Standard lighting model, and enable shadows on all light types
    50. #pragma target 3.0
    51. #pragma surface surf Standard vertex:vert alphatest:_Cutoff addshadow  
    52.  
    53.         void vert(inout appdata_full v) {
    54.             v.normal = -v.normal;
    55.         }
    56.  
    57.         float _NormalScale;
    58.     sampler2D _BaseColorMap;
    59.     sampler2D _MaskMap;
    60.     sampler2D _NormalMap;
    61.  
    62.     struct Input {
    63.         float2 uv_BaseColorMap;
    64.     };
    65.  
    66.     fixed4 _BaseColor;
    67.  
    68.     void surf(Input IN, inout SurfaceOutputStandard o) {
    69.  
    70.         fixed4 c = tex2D(_BaseColorMap, IN.uv_BaseColorMap) * _BaseColor;
    71.         fixed4 mask = tex2D(_MaskMap, IN.uv_BaseColorMap);
    72.  
    73.         o.Albedo = c.rgb;
    74.         o.Metallic = mask.r;
    75.         o.Smoothness = mask.a;
    76.         o.Occlusion = mask.g;
    77.         o.Normal = normalize(UnpackScaleNormal(tex2D(_NormalMap, IN.uv_BaseColorMap), _NormalScale));
    78.         o.Alpha = c.a;
    79.     }
    80.     ENDCG
    81.     }
    82.  
    83.         FallBack Off
    84. }

    Standard HD Obj Normal

    Code (CSharp):
    1. Shader "Standard HD Obj Normal" {
    2.     Properties{
    3.  
    4.         _BaseColor("BaseColor", Color) = (1,1,1,1)
    5.         _BaseColorMap("BaseColorMap", 2D) = "white" {}
    6.         _MaskMap("MaskMap", 2D) = "white" {}
    7.         _NormalMapOS("Object Space Normal (RGB)", 2D) = "bump" {}
    8.         _NormalScale("_NormalScale", Range(0.0, 2.0)) = 1
    9.         _Cutoff("Alpha cutoff", Range(0,1)) = 0.5
    10.     }
    11.         SubShader{
    12.         Tags{ "Queue" = "AlphaTest" "RenderType" = "TransparentCutout" }
    13.         //Tags{"RenderType" = "Opaque"}
    14.         LOD 400
    15.  
    16.         CGPROGRAM
    17.         // Physically based Standard lighting model, and enable shadows on all light types
    18. #pragma target 3.0
    19. #pragma surface surf ObjNormal addshadow  
    20.  
    21.         float _NormalScale;
    22.     sampler2D _BaseColorMap;
    23.     sampler2D _MaskMap;
    24.     sampler2D _NormalMapOS;
    25.  
    26.  
    27.     struct SurfaceOutputObjNormal {
    28.         fixed3 Albedo;
    29.         fixed3 Emission;
    30.         fixed3 Normal;
    31.         fixed Alpha;
    32.         fixed Metallic;
    33.         fixed Smoothness;
    34.         fixed Occlusion;
    35.         fixed3 ObjNormal;
    36.     };
    37.  
    38.  
    39.     struct Input {
    40.         float2 uv_BaseColorMap;
    41.     };
    42.  
    43.     fixed4 _BaseColor;
    44.     float _Cutoff;
    45.  
    46.     void surf(Input IN, inout SurfaceOutputObjNormal o) {
    47.  
    48.         fixed4 c = tex2D(_BaseColorMap, IN.uv_BaseColorMap) * _BaseColor;
    49.         fixed4 mask = tex2D(_MaskMap,IN.uv_BaseColorMap);
    50.  
    51.         o.Albedo = c.rgb;
    52.         o.Metallic = mask.r;
    53.         o.Smoothness = mask.a;
    54.         o.Occlusion = mask.g;
    55.         o.ObjNormal = mul((float3x3)unity_ObjectToWorld, tex2D(_NormalMapOS, IN.uv_BaseColorMap).rgb);
    56.         o.Alpha = c.a;
    57.     }
    58.  
    59.     inline fixed4 LightingObjNormal(SurfaceOutputObjNormal s, fixed3 lightDir, fixed3 viewDir, fixed atten)
    60.     {
    61.         clip(s.Alpha - _Cutoff);
    62.  
    63.         viewDir = normalize(viewDir);
    64.         lightDir = normalize(lightDir);
    65.         s.ObjNormal = normalize(s.ObjNormal);
    66.  
    67.         float NdotL = saturate(dot(s.ObjNormal, lightDir));
    68.  
    69.         fixed4 c;
    70.         c.rgb = s.Albedo * NdotL * _LightColor0.rgb * atten * 2;
    71.         c.a = 1.0;
    72.         return c;
    73.     }
    74.     ENDCG
    75.  
    76.  
    77.      
    78.     }
    79.  
    80.         FallBack Off
    81. }
     
    Last edited: Jul 19, 2018
  2. CherstvyDmitriy

    CherstvyDmitriy

    Joined:
    Jul 19, 2017
    Posts:
    25
    thanks Bro
     
  3. keeponshading

    keeponshading

    Joined:
    Sep 6, 2018
    Posts:
    937
    Hi,

    Thaks for the Standard HD.
    Very Helpful.

    Do you have also an variant with Detail Map?


    BuiltInRP.JPG
     
  4. Kortjakje

    Kortjakje

    Joined:
    Nov 21, 2020
    Posts:
    1
    Really great!
     
  5. FM-Productions

    FM-Productions

    Joined:
    May 1, 2017
    Posts:
    72
    Hi,
    I'm not sure if I should make a new forum thread on it or just post here, but I also have a possible use case of wanting to backport default hdrp materials to built-in, and I really appreciate this post! Thanks a lot for the shaders. I tried to take a look into the hdrp lit shader source code, but there are so many includes and it's so convoluted.

    I was trying to expand the standard shader to include more properties, focusing on the detail map for now, but there are so many questions.
    This page lays out what the color channels of the maps are used for:
    There are insightful youtube videos on the topic too, but I couldn't find "how" the detail channels are used specifically.


    The blue channel of the mask map is the masking value for the detail map.
    Red in detail is the greyscale of the albedo. What do I do with that information?
    Do I need to get the difference between the original albedo greyscale and that and try to adjust the original color to fit that greyscale? And how so?

    The normal map, you have the green from the green detail channel and red from alpha detail channel, so ... ? how do I get the blue value for the map? My current approach is to assume that the map has normalized normal values, so I do:
    blue = sqrt(1 - red * red * green * green), according to Pythagoras theorem

    are the resulting normals simply lerped between mask and detail map, depending on masking value?

    (also, are the attributes like _DetailAlbedoScale and _DetailSmoothnessScale for multiplying with the resulting value itself, or for scaling the texture uv before sampling)
    and why is the detail map grey when not assigned, it doesn't make any sense,



    I haven't really tested it in a real port yet, but this is the attempt so far. Since the shader above reuses some code in the passes, I decided to make a cginc file too:

    main shader code:
    Code (CSharp):
    1. Shader "HDRPToBuiltin/Standard HD" {
    2.     Properties{
    3.  
    4.         _BaseColor("BaseColor", Color) = (1,1,1,1)
    5.         _BaseColorMap("BaseColorMap", 2D) = "white" {}
    6.         _Metallic("Metallic", Range(0.0, 1.0)) = 0
    7.         _Smoothness("Smoothness", Range(0.0, 1.0)) = 0.5
    8.         _MaskMap("MaskMap", 2D) = "white" {}
    9.         _SmoothnessRemapMin("SmoothnessRemapMin", Float) = 0.0
    10.         _SmoothnessRemapMax("SmoothnessRemapMax", Float) = 1.0
    11.         _AORemapMin("AORemapMin", Float) = 0.0
    12.         _AORemapMax("AORemapMax", Float) = 1.0
    13.         _NormalMap("NormalMap", 2D) = "bump" {}     // Tangent space normal map
    14.         _NormalScale("_NormalScale", Range(0.0, 2.0)) = 1
    15.          [HDR] _EmissiveColor("EmissiveColor", Color) = (0, 0, 0)
    16.         _EmissiveIntensity("Emissive Intensity", Float) = 1
    17.  
    18.         [Toggle(_DETAILMAP)]
    19.         _EnableDetailMap("Enable Detail Map", Float) = 0.0
    20.         _DetailMap("DetailMap", 2D) = "gray" {}
    21.         _DetailAlbedoScale("_DetailAlbedoScale", Range(0.0, 2.0)) = 1
    22.         _DetailNormalScale("_DetailNormalScale", Range(0.0, 2.0)) = 1
    23.         _DetailSmoothnessScale("_DetailSmoothnessScale", Range(0.0, 2.0)) = 1
    24.  
    25.         [Toggle(_PARALLAXMAP)]
    26.         _EnableHeightMap("Enable Height Map?", Float) = 0.0
    27.         _HeightMap("HeightMap", 2D) = "black" {}
    28.         _HeightAmplitude("Height Amplitude/Power", Range(0,.250)) = 0.02
    29.  
    30.         _Cutoff("Alpha cutoff", Range(0,1)) = 0.5
    31.     }
    32.         SubShader{
    33.         Tags{ "Queue" = "AlphaTest" "RenderType" = "TransparentCutout" }
    34.         //Tags{"RenderType" = "Opaque"}
    35.         LOD 400
    36.  
    37.         CGPROGRAM
    38. #pragma shader_feature _DETAILMAP
    39. #pragma shader_feature _PARALLAXMAP
    40.         // Physically based Standard lighting model, and enable shadows on all light types
    41. #pragma target 3.0
    42. #pragma surface surf Standard alphatest:_Cutoff addshadow
    43. #include "HDRPLitCommon.cginc"
    44.         ENDCG
    45.  
    46.         Cull front
    47.         CGPROGRAM
    48. #pragma shader_feature _DETAILMAP
    49. #pragma shader_feature _PARALLAXMAP
    50.         // Physically based Standard lighting model, and enable shadows on all light types
    51. #pragma target 3.0
    52. #pragma surface surf Standard vertex:vertInvertNormals alphatest:_Cutoff addshadow
    53. #include "HDRPLitCommon.cginc"
    54.         ENDCG
    55.     }
    56.  
    57.     FallBack Off
    58. }
    And here the "HDRPLitCommon.cginc":

    Code (CSharp):
    1. #ifndef HDRP_TO_BUILTIN_LIT_CGINC
    2. #define HDRP_TO_BUILTIN_LIT_CGINC
    3.  
    4. float _NormalScale;
    5. half _Metallic;
    6. half _Smoothness;
    7. half _SmoothnessRemapMin;
    8. half _SmoothnessRemapMax;
    9. half _AORemapMin;
    10. half _AORemapMax;
    11. float _EmissiveIntensity;
    12. sampler2D _BaseColorMap;
    13. sampler2D _MaskMap;
    14. sampler2D _NormalMap;
    15. #if _DETAILMAP
    16. sampler2D _DetailMap;
    17. half _DetailAlbedoScale;
    18. half _DetailNormalScale;
    19. half _DetailSmoothnessScale;
    20. #endif
    21. #if _PARALLAXMAP
    22. sampler2D _HeightMap;
    23. float _HeightAmplitude;
    24. #endif
    25. struct Input {
    26.     float2 uv_BaseColorMap;
    27. #if _PARALLAXMAP
    28.     float2 uv_HeightMap;
    29.     float3 viewDir;
    30. #endif
    31. };
    32. fixed4 _BaseColor;
    33. float4 _EmissiveColor;
    34.  
    35. void vertInvertNormals(inout appdata_full v) {
    36.     v.normal = -v.normal;
    37. }
    38.  
    39. void surf(Input IN, inout SurfaceOutputStandard o) {
    40. #if !defined(_PARALLAXMAP)
    41.     float2 baseUV = IN.uv_BaseColorMap;
    42. #else
    43.     float2 texoffset = ParallaxOffset(tex2D(_HeightMap, IN.uv_HeightMap).r, _HeightAmplitude, IN.viewDir);
    44.     float2 baseUV = IN.uv_BaseColorMap + texoffset;
    45. #endif
    46.     fixed4 c = tex2D(_BaseColorMap, baseUV) * _BaseColor;
    47.     half4 mask = tex2D(_MaskMap,baseUV);
    48.     o.Albedo = c.rgb;
    49.     o.Metallic = mask.r * _Metallic;
    50.     o.Smoothness = mask.a * lerp(_SmoothnessRemapMin, _SmoothnessRemapMax, _Smoothness);
    51.     o.Occlusion = lerp(_AORemapMin, _AORemapMax, mask.g);
    52.     o.Normal = normalize(UnpackScaleNormal(tex2D(_NormalMap, baseUV), _NormalScale));
    53.     o.Emission = _EmissiveColor.rgb * _EmissiveIntensity;
    54.    
    55.     o.Alpha = c.a;
    56.  
    57. // No idea if the detail map is right in any way
    58. // The _DetailXScale values are likely also applied in a wrong way
    59. #if defined(_DETAILMAP)
    60.     // Detail map channel purposes:
    61.     // • Red: Stores the grey scale as albedo (desaturated albedo)
    62.     // • Green: Stores the green channel of the detail normal map. (normal.y)
    63.     // • Blue: Stores the detail smoothness.
    64.     // • Alpha: Stores the red channel of the detail normal map. (normal.x)
    65.     // Blue channel in mask map stores masking value for detail map:
    66.     float detailMask = mask.b;
    67.     half4 detailCol = tex2D(_DetailMap, baseUV);
    68.     half detailSmoothness = detailCol.b * lerp(_SmoothnessRemapMin, _SmoothnessRemapMax, _Smoothness) * _DetailSmoothnessScale;
    69.     // normalized vector length is 1, a² + b² + c² = 1² => a² + b² + c² = 1, meaning c = sqrt(1 - (a² + b²))
    70.     half normalBlue = sqrt(1.0 - (detailCol.a * detailCol.a + detailCol.g * detailCol.g));
    71.     half3 detailNormal = lerp(half3(0, 0, 1), half3(detailCol.a, detailCol.g, normalBlue), _DetailNormalScale);  // what to use as 3rd value? should we instead try to have a normalized vec?
    72.     o.Normal = lerp(o.Normal, detailNormal, detailMask);
    73.     o.Smoothness = lerp(o.Smoothness, detailSmoothness, detailMask);
    74.     // To simply multiply the existing color with the detail color can't be right either
    75.     o.Albedo = lerp(o.Albedo, saturate(o.Albedo * (detailCol.r * _DetailAlbedoScale), detailMask);
    76.  
    77. #endif
    78. }
    79.  
    80. #endif // HDRP_TO_BUILTIN_LIT_CGINC

    There are some other issues with it too, but mainly I want to know about the detail map usage.
     
  6. FM-Productions

    FM-Productions

    Joined:
    May 1, 2017
    Posts:
    72