Search Unity

How to use the new surfacestandard shaders

Discussion in 'Shaders' started by Alcolepone, Mar 11, 2017.

  1. Alcolepone

    Alcolepone

    Joined:
    Jan 28, 2013
    Posts:
    30
    i have this shader
    Code (CSharp):
    1. // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
    2.  
    3. Shader "JellyOldsurface"
    4. {
    5.     Properties {
    6.         _MainTex ("Base (RGB)", 2D) = "white" {}
    7.         _BumpMap ("Normal (Normal)", 2D) = "bump" {}
    8.         _Color ("Main Color", Color) = (1,1,1,1)
    9.         _SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 1)
    10.         _Shininess ("Shininess", Range (0.03, 1)) = 0.078125
    11.  
    12.         //_Thickness = Thickness texture (invert normals, bake AO).
    13.         //_Power = "Sharpness" of translucent glow.
    14.         //_Distortion = Subsurface distortion, shifts surface normal, effectively a refractive index.
    15.         //_Scale = Multiplier for translucent glow - should be per-light, really.
    16.         //_SubColor = Subsurface colour.
    17.         _Thickness ("Thickness (R)", 2D) = "bump" {}
    18.         _Power ("Subsurface Power", Float) = 1.0
    19.         _Distortion ("Subsurface Distortion", Float) = 0.0
    20.         _Scale ("Subsurface Scale", Float) = 0.5
    21.         _SubColor ("Subsurface Color", Color) = (1.0, 1.0, 1.0, 1.0)
    22.     }
    23.     SubShader {
    24.         Tags { "RenderType"="Opaque" }
    25.         LOD 200
    26.  
    27.         CGPROGRAM
    28.         #pragma surface surf Translucent
    29.         #pragma exclude_renderers flash
    30.  
    31.         sampler2D _MainTex, _BumpMap, _Thickness;
    32.         float _Scale, _Power, _Distortion;
    33.         fixed4 _Color, _SubColor;
    34.         half _Shininess;
    35.  
    36.         struct Input {
    37.             float2 uv_MainTex;
    38.         };
    39.  
    40.         void surf (Input IN, inout SurfaceOutput o) {
    41.             fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
    42.             o.Albedo = tex.rgb * _Color.rgb;
    43.             o.Alpha = tex2D(_Thickness, IN.uv_MainTex).r;
    44.             o.Gloss = tex.a;
    45.             o.Specular = _Shininess;
    46.             o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_MainTex));
    47.         }
    48.  
    49.         inline fixed4 LightingTranslucent (SurfaceOutput s, fixed3 lightDir, fixed3 viewDir, fixed atten)
    50.         {      
    51.             // You can remove these two lines,
    52.             // to save some instructions. They're just
    53.             // here for visual fidelity.
    54.             viewDir = normalize ( viewDir );
    55.             lightDir = normalize ( lightDir );
    56.  
    57.             // Translucency.
    58.             half3 transLightDir = lightDir + s.Normal * _Distortion;
    59.             float transDot = pow ( max (0, dot ( viewDir, -transLightDir ) ), _Power ) * _Scale;
    60.             fixed3 transLight = (atten * 2) * ( transDot ) * s.Alpha * _SubColor.rgb;
    61.             fixed3 transAlbedo = s.Albedo * _LightColor0.rgb * transLight ;
    62.  
    63.             half3 transLightDir2 = lightDir ;
    64.             float transDot2 = pow ( max (0, dot ( viewDir, transLightDir2 ) ), _Power ) * _Scale;
    65.             fixed3 transLight2 = (atten * 2) * ( transDot2 ) * s.Alpha * _SubColor.rgb;
    66.             fixed3 transAlbedo2 = s.Albedo * _LightColor0.rgb * transLight2 ;
    67.  
    68.             // Regular BlinnPhong.
    69.             half3 h = normalize (lightDir + viewDir);
    70.             fixed diff = max (0, dot (s.Normal, lightDir));
    71.             float nh = max (0, dot (s.Normal, h));
    72.             float spec = pow (nh, s.Specular*128.0) * s.Gloss;
    73.             fixed3 diffAlbedo = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * _SpecColor.rgb * spec) * (atten * 2);
    74.  
    75.             // Add the two together.
    76.             fixed4 c;
    77.             c.rgb = diffAlbedo + transAlbedo + transAlbedo2;
    78.  
    79.             c.a = _LightColor0.a * _SpecColor.a * spec * atten;
    80.             return c;
    81.         }
    82.  
    83.         ENDCG
    84.     }
    85.     FallBack "Bumped Diffuse"
    86. }
    that is based off old SSS materals found on the net.

    i'm trying to get the same result but using the new surfacestandard surface shaders, but do not understand how to get it to work..

    heres the current shader i'm trying to use

    Code (CSharp):
    1. // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
    2.  
    3. Shader "JellyNewsurface"
    4. {
    5.     Properties {
    6.         _MainTex ("Base (RGB)", 2D) = "white" {}
    7.         _BumpMap ("Normal (Normal)", 2D) = "bump" {}
    8.         _Color ("Main Color", Color) = (1,1,1,1)
    9.         _SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 1)
    10.                 _Glossiness ("Smoothness", Range(0,1)) = 0.5
    11.         _Metallic ("Metallic", Range(0,1)) = 0.0
    12.  
    13.         //_Thickness = Thickness texture (invert normals, bake AO).
    14.         //_Power = "Sharpness" of translucent glow.
    15.         //_Distortion = Subsurface distortion, shifts surface normal, effectively a refractive index.
    16.         //_Scale = Multiplier for translucent glow - should be per-light, really.
    17.         //_SubColor = Subsurface colour.
    18.         _Thickness ("Thickness (R)", 2D) = "bump" {}
    19.         _Power ("Subsurface Power", Float) = 1.0
    20.         _Distortion ("Subsurface Distortion", Float) = 0.0
    21.         _Scale ("Subsurface Scale", Float) = 0.5
    22.         _SubColor ("Subsurface Color", Color) = (1.0, 1.0, 1.0, 1.0)
    23.     }
    24.     SubShader {
    25.         Tags { "RenderType"="Opaque" }
    26.         LOD 200
    27.     CGPROGRAM
    28.         // Physically based Standard lighting model, and enable shadows on all light types
    29.         #pragma surface surf Standard
    30.         // Use shader model 3.0 target, to get nicer looking lighting
    31.         #pragma target 3.0
    32.  
    33.         sampler2D _MainTex, _BumpMap, _Thickness;
    34.         float _Scale, _Power, _Distortion;
    35.         fixed4 _Color, _SubColor;
    36.             half _Glossiness;
    37.         half _Metallic;
    38.  
    39.         struct Input {
    40.             float2 uv_MainTex;
    41.         };
    42.  
    43.         void surf (Input IN, inout SurfaceOutputStandard o) {
    44.    
    45.             o.Alpha = tex2D(_Thickness, IN.uv_MainTex).r;
    46.        
    47.             o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_MainTex));
    48.  
    49.  
    50.                 // Albedo comes from a texture tinted by color
    51.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    52.             o.Albedo = c.rgb;
    53.             // Metallic and smoothness come from slider variables
    54.             o.Metallic = _Metallic;
    55.             o.Smoothness = _Glossiness;
    56.  
    57.         }
    58.  
    59.         inline fixed4 LightingTranslucent (SurfaceOutputStandard s, fixed3 lightDir, fixed3 viewDir, fixed atten)
    60.         {      
    61.             // You can remove these two lines,
    62.             // to save some instructions. They're just
    63.             // here for visual fidelity.
    64.             viewDir = normalize ( viewDir );
    65.             lightDir = normalize ( lightDir );
    66.  
    67.             // Translucency.
    68.             half3 transLightDir = lightDir + s.Normal * _Distortion;
    69.             float transDot = pow ( max (0, dot ( viewDir, -transLightDir ) ), _Power ) * _Scale;
    70.             fixed3 transLight = (atten * 2) * ( transDot ) * s.Alpha * _SubColor.rgb;
    71.             fixed3 transAlbedo = s.Albedo * _LightColor0.rgb * transLight ;
    72.  
    73.             half3 transLightDir2 = lightDir ;
    74.             float transDot2 = pow ( max (0, dot ( viewDir, transLightDir2 ) ), _Power ) * _Scale;
    75.             fixed3 transLight2 = (atten * 2) * ( transDot2 ) * s.Alpha * _SubColor.rgb;
    76.             fixed3 transAlbedo2 = s.Albedo * _LightColor0.rgb * transLight2 ;
    77.  
    78.             // Regular BlinnPhong.
    79.             half3 h = normalize (lightDir + viewDir);
    80.             fixed diff = max (0, dot (s.Normal, lightDir));
    81.             float nh = max (0, dot (s.Normal, h));
    82.             float spec = pow (nh, s.Metallic*128.0) * s.Smoothness;
    83.             fixed3 diffAlbedo = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * _SpecColor.rgb * spec) * (atten * 2);
    84.  
    85.             // Add the two together.
    86.             fixed4 c;
    87.             c.rgb = diffAlbedo + transAlbedo + transAlbedo2;
    88.  
    89.             c.a = _LightColor0.a * _SpecColor.a * spec * atten;
    90.             return c;
    91.         }
    92.  
    93.         ENDCG
    94.     }
    95.     FallBack "Bumped Diffuse"
    96. }
    what am i missing, and it there any good tutorials on how to use the surface shaders? I've only ever touched vert/frag shaders in the past..
     
  2. brownboot67

    brownboot67

    Joined:
    Jan 5, 2013
    Posts:
    375
    You aren't using your custom lighting function. You need to change this line:

    #pragma surface surf Standard

    to

    #pragma surface surf Translucent
     
  3. Alcolepone

    Alcolepone

    Joined:
    Jan 28, 2013
    Posts:
    30
    cheers for the reply.

    when i do that i get the follow error
    Shader error in 'JellyNewsurface': Unexpected identifier "SurfaceOutputStandard". Expected one of: sampler sampler1D sampler2D sampler3D samplerCUBE sampler_state SamplerState SamplerComparisonState bool int uint half float double or a user-defined type at line 43

    what i dont understand, is how is the inline function "inline fixed4 LightingTranslucent" called?
    i dont understand what the line function in this instance affects?
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,348
    To use both the standard shader lighting model and the translucent shading will require a bit more work than you're thinking it will. Basically you'll need to track down the LightingStandard function Unity uses for the surface shader (I believe it's in Lighting.cginc?) and manually combine that custom lighting function and the standard one. The basic version of what you need to do is replace the "blinn-phong" section of the custom lighting function with what's in the Standars lighting function.

    You'll also need to change the custom lighting function to take the SurfaceOutputStandard that the surf function outputs and the LightingStandard function accepts.

    This page might help you. Parts 2&3 deal with surface shaders, including custom lighting models and using the standard shading model in a surface shader. Nothing specific about modifying the standard function like you're doing, but might help you understand what's going on better.
    http://www.alanzucconi.com/2015/06/10/a-gentle-introduction-to-shaders-in-unity3d/
     
  5. Alcolepone

    Alcolepone

    Joined:
    Jan 28, 2013
    Posts:
    30
    ah that makes sense now. I've got a clearer idea of whats going on now.

    not working yet, but atleast i can see the correct direction :D
     
  6. Alcolepone

    Alcolepone

    Joined:
    Jan 28, 2013
    Posts:
    30
    ok making some progress with my understanding, i'm now using this
    Code (CSharp):
    1.         inline half4 LightingTranslucent  (SurfaceOutputStandard s, half3 viewDir, UnityGI gi)
    2.             {
    3.  
    4.      
    5.                 s.Normal = normalize(s.Normal);
    6.  
    7.                 half oneMinusReflectivity;
    8.                 half3 specColor;
    9.                 s.Albedo = DiffuseAndSpecularFromMetallic (s.Albedo, s.Metallic, /*out*/ specColor, /*out*/ oneMinusReflectivity);
    10.  
    11.                 // shader relies on pre-multiply alpha-blend (_SrcBlend = One, _DstBlend = OneMinusSrcAlpha)
    12.                 // this is necessary to handle transparency in physically correct way - only diffuse component gets affected by alpha
    13.                 half outputAlpha;
    14.                 s.Albedo = PreMultiplyAlpha (s.Albedo, s.Alpha, oneMinusReflectivity, /*out*/ outputAlpha);
    15.  
    16.                 half4 c = UNITY_BRDF_PBS (s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, viewDir, gi.light, gi.indirect);
    17.                 c.rgb += UNITY_BRDF_GI (s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, viewDir, s.Occlusion, gi);
    18.  
    19.                 //c.rgb += transAlbedo + transAlbedo2;
    20.                 c.a = outputAlpha;
    21.                 return c;
    22.             }
    as the basis of the custom lighting i'm trying. But i'm after the lightDir, but the "SurfaceOutputStandard" doesnt provide it. Is there another way i can get the light direction? or do i need to do somthing else
     
  7. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,348
    In the older "SurfaceOutput, lightDir, viewDir, atten" method it's not part of the SurfaceOutput either. It's just that now the lightDir is passed inside a struct called UnityGI.

    Specifically: gi.light.dir

    You can look at the generated surface shader code to see that, though surface shader code can be a bit hard to follow. Curiously the atten value is not passed along, but instead the light color (gi.light.color) is pre-multiplied by the attenuation. That makes things a little more complicated for doing stuff that wants to modify atten with surface shaders using the standard lighting model. However I think it would be possible to use the older style lightDir, viewDir, atten setup and construct your own UnityGI struct to pass to the LightingStandard() function.