Search Unity

Standard Shader (modified to be double sided) is very shiny on the underside

Discussion in 'Shaders' started by infinitypbr, Mar 21, 2016.

  1. infinitypbr

    infinitypbr

    Joined:
    Nov 28, 2012
    Posts:
    3,149
    Hello!

    I have zero experience in shaders aside from using a forum post to modify the Standard Shader to make it double sided.

    However, the "back side" that now shows is very shiny, much more than the front side. Is there a way to modify this or otherwise fix this visual effect?

    Thanks!!

    Screen Shot 2016-03-21 at 1.20.35 PM.png Screen Shot 2016-03-21 at 1.20.40 PM.png Screen Shot 2016-03-21 at 1.20.55 PM.png
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    The problem is the normals for the back side are still pointing the same way, which is away from you. Most PBR calculations (Unity's Standard shader included) don't really handle this case because in the real world it's not possible for a surface to not be pointing toward the viewer and still be seen.

    The fix is testing if the normals are facing towards the camera or not and flip the Z if they're facing away. There's some examples on the forum if you search for them. The correct way to do this is using the VFACE semantic, but most people just use a dot product of the normal and the view direction.
     
    NeatWolf and infinitypbr like this.
  3. infinitypbr

    infinitypbr

    Joined:
    Nov 28, 2012
    Posts:
    3,149
    Thanks! Per a unity doc, I found the following code. I have about 99% no idea what's going on, but best I can tell, the last line is basically saying "if it's front, show this, if it's back ,show that"


    Code (CSharp):
    1. float4 vert (float4 vertex : POSITION) : SV_POSITION
    2.             {
    3.                 return mul(UNITY_MATRIX_MVP, vertex);
    4.             }
    5.  
    6.             fixed4 _ColorFront;
    7.             fixed4 _ColorBack;
    8.  
    9.             fixed4 frag (fixed facing : VFACE) : SV_Target
    10.             {
    11.                 // VFACE input positive for frontbaces,
    12.                 // negative for backfaces. Output one
    13.                 // of the two colors depending on that.
    14.                 return facing > 0 ? _ColorFront : _ColorBack;
    15.             }
    However, _ColorFront & _ColorBack are black -- I replace that with _Color, which is part of the shader, and sure enough that color shows up. I think I need it to display _MainTex, though, which throws an error when I try to use it.

    " cannot implicitly convert from 'const sampler2D' to 'half4' at line 99 (on glcore)"

    Any ideas how to get the main texture to be used instead?
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    Sounds like you're doing:
    Code (CSharp):
    1. return facing > 0 ? _MainTex : _ColorBack;
    You can't do that since you need to actually sample the texture to get a color, ie:

    Code (CSharp):
    1. fixed4 col = tex2D(_MainTex, i.uv.xy); // need to pass uvs through from vert function
    2. return facing > 0 ? col : _ColorBack;
     
    McMayhem likes this.
  5. infinitypbr

    infinitypbr

    Joined:
    Nov 28, 2012
    Posts:
    3,149
    Huh. Ok -- thanks! I'm sure that's helpful, but I'm looking at the nvidia and unity docs for "tex2D", and while the concept roughly makes sense, I'm not at all sure how to go about getting any other aspect of what's required to fill that function. Unfortunately I can't see any similar code in the Unity standard shader script either to jump off from.
     
  6. o0_ICE_0o

    o0_ICE_0o

    Joined:
    Apr 3, 2014
    Posts:
    21
    Im not sure if this would help you, but, i had a problem with double sided normals and i added the code
    Code (CSharp):
    1. SubShader {
    2.          Tags { "RenderType" = "Opaque" }
    3.          Cull off
    4. // Cull off supports double sided normals
    5.  
    Adding Cull off made the toon lit shader support double sided normals without a hitch, maybe it will work with your shader too?
    Im noob, so not sure if this would work. :)
     
  7. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    He's already done this. The problem is that this doesn't do double sided normals, this does double sided surfaces with single sided normals.

    Imagine you have an opaque ball with light coming from above. The top of the ball will naturally be lit. Now let's turn on front face culling so we're only seeing back faces. The result will look about the same as the "top" faces are lit even though we're now seeing the inside of the ball and it's the bottom faces that should now be lit because the back faces' normals are still pointing the same way as the front faces.
     
    o0_ICE_0o likes this.
  8. infinitypbr

    infinitypbr

    Joined:
    Nov 28, 2012
    Posts:
    3,149
    Yep. Unfortunately I can't figure out how to get the back sides to render properly. I have no idea where to even start looking -- I went through the standard shader and it's includes, but nothing made sense to me.

    Anyone care to give me an assist?

    Thanks!!

    Screen Shot 2016-03-26 at 6.15.19 PM.png
     
  9. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    You should be able to use VFACE with a surface shader, just add

    fixed facing : VFACE;

    to the input struct. Then at the end of your surf function do

    o.Normal.z *= saturate(IN.facing) * 2.0 - 1.0;

    Or

    o.Normal.s *= facing > 0.5 ? 1.0 : -1.0;

    facing should be either 1 for front facing and either 0 or -1 for back facing (I forgot which, but the above code should work either way).
     
  10. infinitypbr

    infinitypbr

    Joined:
    Nov 28, 2012
    Posts:
    3,149

    What's the "surf function"?

    I'm guessing it's the last bit from the unity doc examples?

    This throws an error, as I didn't declare "o" variable. All of the shader stuff is really really new to me -- as in I've never looked at it before :)

    Below is part of my code -- I'm attaching the current shader I have -- the "working" one, that's 2-sided but looks funky, and the one I'm working on. Where (And how?) do I declare the o variable? And is that last function where I should put the code? (the "surf" function?)

    Code (CSharp):
    1. float4 vert (float4 vertex : POSITION) : SV_POSITION
    2.             {
    3.                 return mul(UNITY_MATRIX_MVP, vertex);
    4.             }
    5.  
    6.             struct Input {
    7.                 fixed facing : VFACE;
    8.             };
    9.  
    10.             fixed4 _ColorFront;
    11.             fixed4 _ColorBack;
    12.  
    13.             fixed4 frag (fixed facing : VFACE) : SV_Target
    14.             {
    15.                 o.Normal.z *= saturate(IN.facing) * 2.0 - 1.0;
    16.  
    17.                 // VFACE input positive for frontbaces,
    18.                 // negative for backfaces. Output one
    19.                 // of the two colors depending on that.
    20.                // fixed4 col = tex2D(_MainTex, uv_MainTex); // need to pass uvs through from vert function
    21.                 //return facing > 0 ? col : _ColorBack;
    22.             }
     

    Attached Files:

  11. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
  12. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    Here's a basic example shader. The naming for the normal flip mode isn't great, but one acts like the surface is a peice of plastic or metal that's been stamped / molded so when you see the backside it's the inverted surface normals, and the other makes both sides look the same.

    Code (CSharp):
    1. Shader "Custom/Two Sided SurfaceShader" {
    2.     Properties {
    3.         _Color ("Color", Color) = (1,1,1,1)
    4.         [NoScaleOffset] _MainTex ("Albedo (RGB)", 2D) = "white" {}
    5.         _Glossiness ("Smoothness", Range(0,1)) = 0.5
    6.         [Gamma] _Metallic ("Metallic", Range(0,1)) = 0.0
    7.         [NoScaleOffset] _BumpMap("Normal Map", 2D) = "bump" {}
    8.         [Enum(Flip,0,Invert,1)] _BumpFlipMode("Normal Flip Mode", Float) = 0
    9.     }
    10.     SubShader {
    11.         Tags { "RenderType"="Opaque" }
    12.         Cull Off
    13.         LOD 200
    14.        
    15.         CGPROGRAM
    16.         // Physically based Standard lighting model, and enable shadows on all light types
    17.         #pragma surface surf Standard fullforwardshadows
    18.  
    19.         // Use shader model 3.0 target, to get nicer looking lighting
    20.         #pragma target 3.0
    21.  
    22.         sampler2D _MainTex;
    23.         sampler2D _BumpMap;
    24.  
    25.         struct Input {
    26.             float2 uv_MainTex;
    27.             fixed facing : VFACE;
    28.         };
    29.  
    30.         half _Glossiness;
    31.         half _Metallic;
    32.         fixed4 _Color;
    33.         bool _BumpFlipMode;
    34.  
    35.         void surf (Input IN, inout SurfaceOutputStandard o) {
    36.             // Albedo comes from a texture tinted by color
    37.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    38.             o.Albedo = c.rgb;
    39.             // Metallic and smoothness come from slider variables
    40.             o.Metallic = _Metallic;
    41.             o.Smoothness = _Glossiness;
    42.             o.Alpha = c.a;
    43.             o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_MainTex));
    44.  
    45.             // Test if looking at the backface.
    46.             if (IN.facing < 0.5)
    47.             {
    48.                 if (_BumpFlipMode)
    49.                     o.Normal *= -1.0;
    50.                 else
    51.                     o.Normal.z *= -1.0;
    52.             }
    53.         }
    54.         ENDCG
    55.     }
    56.     FallBack "Diffuse"
    57. }
    58.  
     
    spakment and NeatWolf like this.
  13. infinitypbr

    infinitypbr

    Joined:
    Nov 28, 2012
    Posts:
    3,149
    Thanks -- I succeeded in adding a Specular input option, but that's about it :/

    I think I'm going to have to hire out on this one, it's above my head for sure. I'll PM you if you're interested.
     
  14. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    You're looking for a version of the above based on the standard specular shader?
     
  15. infinitypbr

    infinitypbr

    Joined:
    Nov 28, 2012
    Posts:
    3,149
    We have our specular in the alpha of the map, so it's currently in the MetalRough standard shader.

    Below is what it looks like now -- using two materials, the top one being "Fade" (shown) and the bottom being a Cutout one with the same maps. That's the best look I've been able to get so far. Using the double-sided version from before makes the hair look a bit more thick and normal (esp. from certain angles), but of course is shiny.

    The male head is from the modelers application, and is how he intended it to look, using the standard shader in 3ds Max.

    Hair_3dsMax.jpg Screen Shot 2016-03-29 at 4.25.01 PM.png Hair_3dsMax.jpg

    Screen Shot 2016-03-29 at 4.25.01 PM.png
     
  16. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    Code (CSharp):
    1. Shader "Custom/Standard Two Sided Soft Blend" {
    2.     Properties {
    3.         _Color ("Color", Color) = (1,1,1,1)
    4.         [NoScaleOffset] _MainTex ("Albedo (RGB)", 2D) = "white" {}
    5.         [Toggle] _UseMetallicMap ("Use Metallic Map", Float) = 0.0
    6.         [NoScaleOffset] _MetallicGlossMap("Metallic", 2D) = "black" {}
    7.         [Gamma] _Metallic ("Metallic", Range(0,1)) = 0.0
    8.         _Glossiness ("Smoothness", Range(0,1)) = 0.5
    9.         _BumpScale("Scale", Float) = 1.0
    10.         [NoScaleOffset] _BumpMap("Normal Map", 2D) = "bump" {}
    11.         _Cutoff("Alpha Cutoff", Range(0.01,1)) = 0.5
    12.     }
    13.     SubShader {
    14.         Tags { "Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout" }
    15.         Blend SrcAlpha OneMinusSrcAlpha
    16.         LOD 200
    17.         ZWrite Off
    18.         Cull Off
    19.  
    20.         Pass {
    21.             ColorMask 0
    22.             ZWrite On
    23.  
    24.             CGPROGRAM
    25.             #pragma vertex vert
    26.             #pragma fragment frag
    27.          
    28.             #include "UnityCG.cginc"
    29.  
    30.             struct v2f {
    31.                 float4 vertex : SV_POSITION;
    32.                 float2 texcoord : TEXCOORD0;
    33.             };
    34.  
    35.             sampler2D _MainTex;
    36.             fixed _Cutoff;
    37.  
    38.             v2f vert (appdata_img v)
    39.             {
    40.                 v2f o;
    41.                 o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
    42.                 o.texcoord = v.texcoord;
    43.                 return o;
    44.             }
    45.  
    46.             fixed4 frag (v2f i) : SV_Target
    47.             {
    48.                 fixed4 col = tex2D(_MainTex, i.texcoord);
    49.                 clip(col.a - _Cutoff);
    50.                 return 0;
    51.             }
    52.             ENDCG
    53.         }
    54.  
    55.         Pass
    56.         {
    57.             Tags {"LightMode"="ShadowCaster"}
    58.             ZWrite On
    59.             Cull Off
    60.  
    61.             CGPROGRAM
    62.             #pragma vertex vert
    63.             #pragma fragment frag
    64.             #pragma multi_compile_shadowcaster
    65.             #include "UnityCG.cginc"
    66.  
    67.             struct v2f {
    68.                 V2F_SHADOW_CASTER;
    69.                 float2 texcoord : TEXCOORD1;
    70.             };
    71.  
    72.             v2f vert(appdata_base v)
    73.             {
    74.                 v2f o;
    75.                 TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
    76.                 o.texcoord = v.texcoord;
    77.                 return o;
    78.             }
    79.          
    80.             sampler2D _MainTex;
    81.             fixed _Cutoff;
    82.  
    83.             float4 frag(v2f i) : SV_Target
    84.             {
    85.                 fixed4 col = tex2D(_MainTex, i.texcoord);
    86.                 clip(col.a - _Cutoff);
    87.                 SHADOW_CASTER_FRAGMENT(i)
    88.             }
    89.             ENDCG
    90.         }
    91.      
    92.         CGPROGRAM
    93.         #pragma surface surf Standard fullforwardshadows alpha:fade nolightmap
    94.         #pragma shader_feature _USEMETALLICMAP_ON
    95.         #pragma target 3.0
    96.  
    97.         sampler2D _MainTex;
    98.         sampler2D _MetallicGlossMap;
    99.         sampler2D _BumpMap;
    100.  
    101.         struct Input {
    102.             float2 uv_MainTex;
    103.             fixed facing : VFACE;
    104.         };
    105.  
    106.         half _Glossiness;
    107.         half _Metallic;
    108.         fixed4 _Color;
    109.         half _BumpScale;
    110.         fixed _Cutoff;
    111.  
    112.         void surf (Input IN, inout SurfaceOutputStandard o) {
    113.             // Albedo comes from a texture tinted by color
    114.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    115.             o.Albedo = c.rgb;
    116.  
    117.             #ifdef _USEMETALLICMAP_ON
    118.             fixed4 mg = tex2D(_MetallicGlossMap, IN.uv_MainTex);
    119.             o.Metallic = mg.r;
    120.             o.Smoothness = mg.a;
    121.             #else
    122.             o.Metallic = _Metallic;
    123.             o.Smoothness = _Glossiness;
    124.             #endif
    125.  
    126.             // Rescales the alpha on the blended pass
    127.             o.Alpha = saturate(c.a / _Cutoff);
    128.  
    129.             o.Normal = UnpackScaleNormal(tex2D(_BumpMap, IN.uv_MainTex), _BumpScale);
    130.  
    131.             if (IN.facing < 0.5)
    132.                 o.Normal *= -1.0;
    133.         }
    134.         ENDCG
    135.     }
    136.     FallBack "Diffuse"
    137. }
    138.  
    edit: fixed shader with my suggestion from below
     
    Last edited: Jan 27, 2017
  17. infinitypbr

    infinitypbr

    Joined:
    Nov 28, 2012
    Posts:
    3,149
    You have rocked my world! Thank you!
     
  18. infinitypbr

    infinitypbr

    Joined:
    Nov 28, 2012
    Posts:
    3,149
    I'm running into a small problem, and i'm not sure where in the shader this is coming from. In some lighting, the transparent parts of the hair give a light visible film to the image. Like in the shot attached. Any idea where this is coming from?

    Thanks!!

    Screen-Shot-2016-04-06-at-1.32.jpg
     
  19. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    Guessing my shader doesn't play well with additional lights beyond the main directional light. Try replacing keepalpha with alpha:fade
     
    infinitypbr likes this.
  20. infinitypbr

    infinitypbr

    Joined:
    Nov 28, 2012
    Posts:
    3,149
    BOOM

    That did it. Thanks! :D:D:D
     
  21. ponpal

    ponpal

    Joined:
    Nov 14, 2017
    Posts:
    6
    The above shader doesn't seem to receive any shadows from other objects, how can I add this feature to it?
     
  22. Flavelius

    Flavelius

    Joined:
    Jul 8, 2012
    Posts:
    945
    You can try adding 'addshadow' to the pragma, maybe that works.
     
  23. ponpal

    ponpal

    Joined:
    Nov 14, 2017
    Posts:
    6
    That pragma gives me the following:

    Shader warning in 'Custom/Standard Two Sided Soft Blend': Unrecognized #pragma directive: addshadow at line 111


    I've tried adding the "Receive shadows" part of this page as a new pass to the shader with no luck (nothing changes). Any ideas to what the issue might be?
     
    JamesArndt likes this.
  24. Flavelius

    Flavelius

    Joined:
    Jul 8, 2012
    Posts:
    945
    Last edited: May 14, 2018
    JamesArndt likes this.
  25. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    Because I'm guessing you wrote this:
    #pragma addshadow

    When it should have been added to end of the exist #pragma surface line... except it is unnecessary and unwanted as the shader already defines a ShadowCaster pass, which is what the addshadow keyword creates. Also it needs to be a custom shadow caster pass since the generated one would not work properly for this.

    Unfortunately I think Unity's surface shaders haven changed in the two years since I posted the above as it did originally receive shadows properly. The alpha:fade keyword changes enough stuff now that it fully prevents shadow receiving where as before it did not and would only change some elements on how the shader would render. Unfortunately with out alpha:fade it rather defeats the main purpose of the shader which was to provide a shadow receiving hard edged alpha blended shader. Removing alpha:fade prevents the alpha blending from working, and using keepalpha causes the issue shown in the image above. With how surface shaders are now, there's no way to do the effect as originally intended to work without using vertex fragment shaders. :(

    If you just want a two sided lit standard shader and don't need the alpha, the above is overkill.
     
    JamesArndt likes this.
  26. ponpal

    ponpal

    Joined:
    Nov 14, 2017
    Posts:
    6
    Thanks a lot, removing alpha:fade did indeed make receiving shadows work! :)

    alpha:fade is probably not needed for what I am doing, but I guess it would be good to have that functionality in the future.

    In any case I think Unity should have two-sided shaders by default, or just provide a "two-sided checkbox" for materials like Unreal does...
     
  27. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    I agree, and so does Unity. The upcoming HD Pipeline has this as a built in feature.
     
    camta005 and JamesArndt like this.
  28. ponpal

    ponpal

    Joined:
    Nov 14, 2017
    Posts:
    6
    Cool, thanks for the info!
     
  29. Frigid

    Frigid

    Joined:
    Jan 31, 2014
    Posts:
    3
    Very, very nicely done! But i have a question. I'm trying to make the shader recieve shadows and use
    Code (CSharp):
    1. #pragma multi_compile_fwdadd_fullshadows
    Shadows appear, but the entire object becomes much darker. Is there a way to get rid of such a global blackout?
    Logo on top: Custom/Standard Two Sided Soft Blend shader (with multi_compile_fwdadd_fullshadows)
    Logo on bottom: Custom/Standard Two Sided Soft Blend shader (original from bgolus)




    Fun fact: different results on different versions of unity
     
    Last edited: Jun 17, 2018
    JamesArndt likes this.
  30. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    If you take the generate code from the original shader and only modify the FowardAdd pass to use that multi_compile it may work better.
     
  31. Cellenseres

    Cellenseres

    Joined:
    Mar 30, 2015
    Posts:
    68
    Just for interest, is there a version of this shader with Specular-Map instead of metallic?
     
  32. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    Sure, take any surface shader using SurfaceOutputStandard and replace it with SurfaceOutputStandardSpecular. Then change:
    o.Metallic = mg.r;
    to:
    o.Specular = mg.rgb;

    The "metallic" texture property (which you could change the name of) will now function as a specular color texture.
     
    Kin0min likes this.
  33. Cellenseres

    Cellenseres

    Joined:
    Mar 30, 2015
    Posts:
    68
    Thank you, I tried as you said, but yea.
    It doesn't look like Specular should :S
    upload_2018-12-13_10-48-27.png

    Here's the edited Script:

    Code (CSharp):
    1. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    2.  
    3. Shader "Custom/Standard Two Sided Soft Blend" {
    4.     Properties{
    5.         _Color("Color", Color) = (1,1,1,1)
    6.         [NoScaleOffset] _MainTex("Albedo (RGB)", 2D) = "white" {}
    7.     [Toggle] _UseSpecularMap("Use Specular Map", Float) = 0.0
    8.         [NoScaleOffset] _SpecularGlossMap("Specular", 2D) = "black" {}
    9.     [Gamma] _Specular("Specular", Range(0,1)) = 0.0
    10.         _Glossiness("Smoothness", Range(0,1)) = 0.5
    11.         _BumpScale("Scale", Float) = 1.0
    12.         [NoScaleOffset] _BumpMap("Normal Map", 2D) = "bump" {}
    13.     _Cutoff("Alpha Cutoff", Range(0.01,1)) = 0.5
    14.     }
    15.         SubShader{
    16.         Tags{ "Queue" = "AlphaTest" "IgnoreProjector" = "True" "RenderType" = "TransparentCutout" }
    17.         Blend SrcAlpha OneMinusSrcAlpha
    18.         LOD 200
    19.         ZWrite Off
    20.         Cull Off
    21.  
    22.         Pass{
    23.         ColorMask 0
    24.         ZWrite On
    25.  
    26.         CGPROGRAM
    27. #pragma vertex vert
    28. #pragma fragment frag
    29.  
    30. #include "UnityCG.cginc"
    31.  
    32.         struct v2f {
    33.         float4 vertex : SV_POSITION;
    34.         float2 texcoord : TEXCOORD0;
    35.     };
    36.  
    37.     sampler2D _MainTex;
    38.     fixed _Cutoff;
    39.  
    40.     v2f vert(appdata_img v)
    41.     {
    42.         v2f o;
    43.         o.vertex = UnityObjectToClipPos(v.vertex);
    44.         o.texcoord = v.texcoord;
    45.         return o;
    46.     }
    47.  
    48.     fixed4 frag(v2f i) : SV_Target
    49.     {
    50.         fixed4 col = tex2D(_MainTex, i.texcoord);
    51.     clip(col.a - _Cutoff);
    52.     return 0;
    53.     }
    54.         ENDCG
    55.     }
    56.  
    57.         Pass
    58.     {
    59.         Tags{ "LightMode" = "ShadowCaster" }
    60.         ZWrite On
    61.         Cull Off
    62.  
    63.         CGPROGRAM
    64. #pragma vertex vert
    65. #pragma fragment frag
    66. #pragma multi_compile_shadowcaster
    67. #include "UnityCG.cginc"
    68.  
    69.         struct v2f {
    70.         V2F_SHADOW_CASTER;
    71.         float2 texcoord : TEXCOORD1;
    72.     };
    73.  
    74.     v2f vert(appdata_base v)
    75.     {
    76.         v2f o;
    77.         TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
    78.             o.texcoord = v.texcoord;
    79.         return o;
    80.     }
    81.  
    82.     sampler2D _MainTex;
    83.     fixed _Cutoff;
    84.  
    85.     float4 frag(v2f i) : SV_Target
    86.     {
    87.         fixed4 col = tex2D(_MainTex, i.texcoord);
    88.     clip(col.a - _Cutoff);
    89.     SHADOW_CASTER_FRAGMENT(i)
    90.     }
    91.         ENDCG
    92.     }
    93.  
    94.         CGPROGRAM
    95. #pragma surface surf StandardSpecular fullforwardshadows alpha:fade nolightmap
    96. #pragma shader_feature _USESPECULARMAP_ON
    97. #pragma target 3.0
    98.  
    99.         sampler2D _MainTex;
    100.     sampler2D _SpecularGlossMap;
    101.     sampler2D _BumpMap;
    102.  
    103.     struct Input {
    104.         float2 uv_MainTex;
    105.         fixed facing : VFACE;
    106.     };
    107.  
    108.     half _Glossiness;
    109.     half _Specular;
    110.     fixed4 _Color;
    111.     half _BumpScale;
    112.     fixed _Cutoff;
    113.  
    114.     void surf(Input IN, inout SurfaceOutputStandardSpecular o) {
    115.         // Albedo comes from a texture tinted by color
    116.         fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
    117.         o.Albedo = c.rgb;
    118.  
    119. #ifdef _USESPECULARMAP_ON
    120.         fixed4 mg = tex2D(_SpecularGlossMap, IN.uv_MainTex);
    121.         o.Specular = mg.rgb;
    122.         o.Smoothness = mg.a;
    123. #else
    124.         o.Specular = _Specular;
    125.         o.Smoothness = _Glossiness;
    126. #endif
    127.  
    128.         // Rescales the alpha on the blended pass
    129.         o.Alpha = saturate(c.a / _Cutoff);
    130.  
    131.         o.Normal = UnpackScaleNormal(tex2D(_BumpMap, IN.uv_MainTex), _BumpScale);
    132.  
    133.         if (IN.facing < 0.5)
    134.             o.Normal *= -1.0;
    135.     }
    136.     ENDCG
    137.     }
    138.         FallBack "Diffuse"
    139. }
    140.  

    Would be cool if you could fix that for me <3
     
  34. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    Looks correct to me, what's the problem you're seeing?
     
  35. JakeFromBend

    JakeFromBend

    Joined:
    Jun 22, 2014
    Posts:
    6
    @infinitypbr
    I have a suggestion, depending on your use case...

    Instead of this:
    Code (csharp):
    1.         if (IN.facing < 0.5)
    2.             o.Normal *= -1.0;
    You might want to try only flipping the z-component, like so:
    Code (csharp):
    1.         if (IN.facing < 0.5)
    2.             o.Normal.z *= -1.0;
    backface_normals.jpg
     
    robot-ink, Kin0min, NeatWolf and 2 others like this.
  36. Cellenseres

    Cellenseres

    Joined:
    Mar 30, 2015
    Posts:
    68
    This is the edited Shader how I currently have it:
    upload_2018-12-17_17-8-49.png

    the material is yea... dunno how to explain it (sorry, english isn't my native language).
    It's like its mirroring. I can't change that with the sliders.
    By using the standard specular shader, it looks correclty when removing the Smoothness:
    upload_2018-12-17_17-10-51.png

    But this Standard Shader isn't Double-Sided.
    I also like to the smooth alpha blending this shader has.

    Mind checking that again for me why the smoothness slider doesn't work?
     
  37. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    Because the sliders don't do anything in this shader when the check box for Use Specular Map is checked. The standard shaders have 2 sets of sliders which are hidden with a custom editor so only one shows at a time. If you want you can multiply the smoothness value from the texture by the _Glossiness property to get the same kind of control.
     
  38. Cellenseres

    Cellenseres

    Joined:
    Mar 30, 2015
    Posts:
    68
    well, I want to set the Smoothness to nearly zero so that it looks like the Material in the other screenshot.
    unchecking the "Use Specular Map" disables the Specular Map completely :S

    Could you tell me how to get the slider for that to work correctly?
    Unfortunately I've never worked on Shaders before :S
     
  39. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    This is the snippet of code that's important here.
    Code (CSharp):
    1. #ifdef _USESPECULARMAP_ON
    2.         fixed4 mg = tex2D(_SpecularGlossMap, IN.uv_MainTex);
    3.         o.Specular = mg.rgb;
    4.         o.Smoothness = mg.a;
    5. #else
    6.         o.Specular = _Specular;
    7.         o.Smoothness = _Glossiness;
    8. #endif
    The #ifdef is based on if that check box is checked or not. So if it is, then it reads the texture and assigns the specular and smoothness values from the texture. If it's not it just uses the float values from the two sliders, _Specular and _Glossiness "Smoothness" (though _Specular should be a Color, and not a single float value as it is in your version of the shader).

    If you want the _Glossiness value to still affect the smoothness when using a texture, multiply the mg.a at the same time as assigning o.Smoothness.

    o.Smoothness = mg.a * _Glossiness;

    I personally never use those sliders in the standard shader when using a texture and always modify my art content directly if I want to change their smoothness, so I left out the functionality. But it makes sense to still have if you only want a constant value of smoothness and don't want to use an DXT5 for your specular color just to put in a black alpha.
     
    See101 and NeatWolf like this.
  40. Cellenseres

    Cellenseres

    Joined:
    Mar 30, 2015
    Posts:
    68
    Well, I've tried that without luck :S

    Yea, probably that's the problem :S
    I used your Script as base and just did that:
    Unfortunately Shaders is something I still don't understand to code :S

    And that's why I'm asking you for help.

    Mind fixing the Shader for me so that it works like the original Standard Specular Shader (+ your features?)
    I want to use a Specular Map on your Shader but this way I did it seems to be wrong.
     
  41. invadererik

    invadererik

    Joined:
    Oct 31, 2010
    Posts:
    148
    You could get one of the hair shaders on the asset store. Using the same technique basically.
     
    NeatWolf likes this.
  42. soleron

    soleron

    Joined:
    Apr 21, 2013
    Posts:
    580
    Is this LWRP compatible?
     
  43. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
  44. TabuuForteAkugun

    TabuuForteAkugun

    Joined:
    Sep 28, 2015
    Posts:
    58
    THANK YOU! You helped me fix my multi-layered transparent hair issues!

    Will credit you in my game!~
     
    jake_hempson and NeatWolf like this.
  45. frystihrysti

    frystihrysti

    Joined:
    Apr 11, 2019
    Posts:
    1
    you can create a button if you insert this command, [Enum(No,2,Yes,0)] _TwoSided("Two Sided", Float) = 2.000000
    and replace cull off with Cull[_TwoSided] , Sorry if you already knew
     

    Attached Files:

    • 1234.jpg
      1234.jpg
      File size:
      51.5 KB
      Views:
      971
  46. jake_hempson

    jake_hempson

    Joined:
    May 28, 2019
    Posts:
    1
    Thanks very much folks - this thread and end resultant shader has been a huge help.
     
  47. neutrino353

    neutrino353

    Joined:
    Sep 10, 2015
    Posts:
    15
    I have similar problem when choosing a proper shader for the hair of my character.
    When I tried to use the bgolus's shader , every is fine when viewed in the editor's camera.
    However, when view from the game camera, thing go wrong as shown in the attached screen cap.
    It seem that the alpha cutoff don't work properly.
    Does anyone has the problem and has any clue to solve this problem ?
    Thanks

    image_01.jpg
     
  48. neutrino353

    neutrino353

    Joined:
    Sep 10, 2015
    Posts:
    15
    Just found out how to solve the problem. Setting shader's render queue to transparent solve the problem.
    Don't understand why, but OK.
     
    camta005 likes this.
  49. camta005

    camta005

    Joined:
    Dec 16, 2016
    Posts:
    320
    I've been playing with this and discovered that replacing alpha:fade with decal:blend seems to solve the shadow receiving problem.

    Edit: Also render queue needs to be set to AlphaTest (2450) or lower for it to receive shadows.
     
    Last edited: May 7, 2020
    TabuuForteAkugun likes this.
  50. TabuuForteAkugun

    TabuuForteAkugun

    Joined:
    Sep 28, 2015
    Posts:
    58
    Thank you. You fixed many issues I had with the shader on materials like capes and skin,.
     
    camta005 likes this.