Search Unity

Question Needing help with writing a LittleBigPlanet 3 PS4 styled "fuzz" Shader

Discussion in 'Shaders' started by Marshi, Sep 5, 2021.

  1. Marshi

    Marshi

    Joined:
    Jun 9, 2018
    Posts:
    2
    As the title says, I'm looking for guidance to recreate a Shader from LittleBigPlanet 3 on PS4 that's used on Sackboy's skin materials, it's a fur Shader that uses fins around the outline of Sackboy to make him fuzzy.
    I have some images as an example for what I mean:

    Below is the texture used for Sackboy's fuzz effect with the color channels separated.
    Red multiplies the length of the fins, Green is the alpha channel combined with the diffuse of the fins, Not sure what Blue does yet.

    I have pre-existing Shader code using a snippet of code from a friend's own game inserted into a Unity Standard Shader, and while it mostly works as intended, the lighting setup needed for their Shader is different from Unity's Standard lighting, resulting in the fins having much darker lighting than intended and not looking as it does in LBP. Sackboy is used for reference below:

    For now I just want to fix the lighting in the "Fins" section of the code so it isn't so dark and looks more like the reference images, I'd also like to create a method of Specular to match the aesthetic of LBP as well later down the line, though it's not as important to me as the fuzz effect at the moment. Help would be appreciated!
    Code (CSharp):
    1.             //Fins
    2.  
    3.             Pass
    4.             {
    5.             LOD 100
    6.             Cull Off
    7.             ZWrite Off
    8.             Ztest Less
    9.             Blend SrcAlpha OneMinusSrcAlpha
    10.             CGPROGRAM
    11.             #define UNITY_SHADER_NO_UPGRADE
    12.             #pragma vertex vert
    13.             #pragma geometry geom
    14.             #pragma fragment frag
    15.             #pragma multi_compile_fwd_base
    16.             #pragma target 4.0
    17.             #pragma require geometry
    18.  
    19.             #include "UnityCG.cginc"
    20.             #include "UnityLightingCommon.cginc"
    21.             #include "AutoLight.cginc"
    22.  
    23.             struct appdata
    24.             {
    25.                 float4 vertex : POSITION;
    26.                 float2 uv : TEXCOORD0;
    27.                 float2 uv2 : TEXCOORD1;
    28.                 float3 normal : NORMAL;
    29.             };
    30.  
    31.  
    32.             struct v2g
    33.             {
    34.                 float2 uv : TEXCOORD0;
    35.                 float2 uv_unscaled : TEXCOORD1;
    36.                 float2 uv2 : TEXCOORD2;
    37.                 float4 pos : SV_POSITION;
    38.                 float3 normal : NORMAL;
    39.                 float3 falloff : COLOR0;
    40.                 float4 diffuse : COLOR1;
    41.                 float4 ambient : COLOR2;
    42.                 SHADOW_COORDS(3)
    43.             };
    44.  
    45.             struct g2f
    46.             {
    47.                 float2 uv : TEXCOORD0;
    48.                 float2 originalUv : TEXCOORD1;
    49.                 float2 originalUv_unscaled : TEXCOORD2;
    50.                 float2 uv2 : TEXCOORD3;
    51.                 float4 vertex : SV_POSITION;
    52.                 float3 falloff : COLOR0;
    53.                 float4 diffuse : COLOR1;
    54.                 float4 ambient : COLOR2;
    55.                 SHADOW_COORDS(4)
    56.             };
    57.  
    58.             sampler2D _MainTex;
    59.             sampler2D _SideFurTex;
    60.             sampler2D _FurMaskTex;
    61.             float4 _MainTex_ST;
    62.             float _Size;
    63.             float _FurLayers;
    64.             float4 _Comb;
    65.             sampler2D _FluffTex;
    66.             sampler2D _Dirt;
    67.             sampler2D _Decals;
    68.             float4 _Falloff;
    69.             float _FalloffExponent;
    70.             //float _FalloffExponent2;
    71.             float _FalloffBrightness2;
    72.             float4 _Falloff2;
    73.  
    74.             float3 DoFalloff(float lightatten, float4 normal, float4 viewDir, float3 worldNormal)
    75.             {
    76.                 float biasedatten = lightatten * 0.5f;//pow(saturate(lightatten), _RimBias)*_RimBias;
    77.                 float4 FalloffTerm = pow(1 - dot(normal, normalize(viewDir)), 1);
    78.                 float4 Falloff1 = _Falloff * lerp(1 - worldNormal.y, 1, 0.5);
    79.                 float4 Falloff2 = _Falloff2 * lerp(worldNormal.y, 1, 0.75);
    80.                 float3 Falloff = lerp(Falloff1 * _FalloffExponent, Falloff2 * _FalloffBrightness2, biasedatten) * FalloffTerm / 3;
    81.                 return Falloff * saturate(pow(FalloffTerm, 0.35));
    82.             }
    83.  
    84.             float DoSoftDiffuse(float NdotL)
    85.             {
    86.                 NdotL = saturate(NdotL);
    87.                 return (pow(NdotL, 0.5) / 6) + (pow(NdotL, 1) / 5) + (pow(NdotL, 2) / 1.5);
    88.             }
    89.  
    90.             v2g vert(appdata v)
    91.             {
    92.                 v2g o;
    93.                 o.pos = mul(unity_ObjectToWorld, v.vertex);
    94.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    95.                 o.uv_unscaled = v.uv;
    96.                 o.uv2 = v.uv2;
    97.                 o.normal = mul(v.normal, unity_WorldToObject);
    98.                 float4 viewDir = float4(ObjSpaceViewDir(v.vertex),1);
    99.                 float3 normal = v.normal;
    100.                 float3 worldNormal = UnityObjectToWorldNormal(v.normal);
    101.                 float3 wNormal = worldNormal;
    102.                 worldNormal *= 1.25f;
    103.                 float3 screenNormal = mul(UNITY_MATRIX_V, UnityObjectToWorldNormal(v.normal));
    104.                 //float3 falloff = pow(1 - dot(normal, normalize(viewDir)), _FalloffExponent2) * _FalloffExponent * 0.75;
    105.                 //float falloffthingy = 1 - lerp((clamp(screenNormal.x, 0, 1) * clamp(screenNormal.x, 0, 1)), (clamp(screenNormal.y, 0, 1) * clamp(screenNormal.y, 0, 1)), 0.5f);
    106.                 o.diffuse = DoSoftDiffuse(dot(worldNormal, _WorldSpaceLightPos0.xyz));
    107.                 o.diffuse.w = 1;
    108.                 o.falloff = DoFalloff(o.diffuse, float4(normal,0), viewDir, worldNormal) * 2;//((falloff * falloffthingy * _Falloff) + ((falloff * falloff * (1 - clamp(falloffthingy, 0, 1)) / 8) * _FalloffBrightness2 * _LightColor0));
    109.                 float ambientUp = wNormal.y;
    110.                 float ambientDown = 1 - wNormal.y;
    111.                 float4 ambient;
    112.                 ambient.w = 1;
    113.                 ambient.xyz = unity_AmbientSky * ambientUp;
    114.                 ambient.xyz += unity_AmbientGround * ambientDown;
    115.                 o.ambient = ambient;
    116.                 TRANSFER_SHADOW(o);
    117.                 return o;
    118.             }
    119.  
    120.             [maxvertexcount(4)]
    121.             void geom(line v2g IN[2], inout TriangleStream<g2f> triStream)
    122.             {
    123.                 float4x4 vp = mul(UNITY_MATRIX_MVP, unity_WorldToObject);
    124.  
    125.                 float3 eyeVec = normalize(((IN[0].pos - _WorldSpaceCameraPos) + (IN[1].pos - _WorldSpaceCameraPos)) / 2);
    126.                 float4 lineNormal = float4(normalize((IN[0].normal + IN[1].normal) / 2), 0) * 0.15 * _Size;
    127.                 float eyeDot = dot(lineNormal, eyeVec);
    128.  
    129.                 float3 newNormal = normalize(cross(IN[1].pos - IN[0].pos, lineNormal));
    130.                 float maxOffset = 0.25f;
    131.  
    132.                 if (eyeDot < maxOffset && eyeDot > -maxOffset)
    133.                 {
    134.  
    135.                     g2f pIn;
    136.  
    137.                     pIn.vertex = mul(vp, IN[1].pos);
    138.                     pIn.uv = float2(0.0625 + ((IN[1].uv.x + IN[1].uv.y) / 2), 0);
    139.                     pIn.originalUv = IN[1].uv;
    140.                     pIn.originalUv_unscaled = IN[1].uv_unscaled;
    141.                     pIn.uv2 = IN[1].uv2;
    142.                     pIn.falloff = IN[1].falloff;
    143.                     #if defined (SHADOWS_SCREEN) || defined (SHADOWS_DEPTH) || defined (SPOT)
    144.                     pIn._ShadowCoord = IN[1]._ShadowCoord;
    145.                     #endif
    146.                     pIn.diffuse = IN[1].diffuse;
    147.                     pIn.ambient = IN[1].ambient;
    148.                     triStream.Append(pIn);
    149.  
    150.                     pIn.vertex = mul(vp, IN[1].pos + lineNormal);
    151.                     pIn.uv = float2(0.0625 + ((IN[1].uv.x + IN[1].uv.y) / 2), 1);
    152.                     pIn.originalUv = IN[1].uv;
    153.                     pIn.originalUv_unscaled = IN[1].uv_unscaled;
    154.                     pIn.uv2 = IN[1].uv2;
    155.                     pIn.falloff = IN[1].falloff;
    156.                     #if defined (SHADOWS_SCREEN) || defined (SHADOWS_DEPTH) || defined (SPOT)
    157.                     pIn._ShadowCoord = IN[1]._ShadowCoord;
    158.                     #endif
    159.                     pIn.diffuse = IN[1].diffuse;
    160.                     pIn.ambient = IN[1].ambient;
    161.                     triStream.Append(pIn);
    162.  
    163.                     pIn.vertex = mul(vp, IN[0].pos);
    164.                     pIn.uv = float2(((IN[1].uv.x + IN[1].uv.y) / 2), 0);
    165.                     pIn.originalUv = IN[0].uv;
    166.                     pIn.originalUv_unscaled = IN[0].uv_unscaled;
    167.                     pIn.uv2 = IN[0].uv2;
    168.                     pIn.falloff = IN[0].falloff;
    169.                     #if defined (SHADOWS_SCREEN) || defined (SHADOWS_DEPTH) || defined (SPOT)
    170.                     pIn._ShadowCoord = IN[0]._ShadowCoord;
    171.                     #endif
    172.                     pIn.diffuse = IN[0].diffuse;
    173.                     pIn.ambient = IN[0].ambient;
    174.                     triStream.Append(pIn);
    175.  
    176.                     pIn.vertex = mul(vp, IN[0].pos + lineNormal);
    177.                     pIn.uv = float2(((IN[1].uv.x + IN[1].uv.y) / 2), 1);
    178.                     pIn.originalUv = IN[0].uv;
    179.                     pIn.originalUv_unscaled = IN[0].uv_unscaled;
    180.                     pIn.uv2 = IN[0].uv2;
    181.                     pIn.falloff = IN[0].falloff;
    182.                     #if defined (SHADOWS_SCREEN) || defined (SHADOWS_DEPTH) || defined (SPOT)
    183.                     pIn._ShadowCoord = IN[0]._ShadowCoord;
    184.                     #endif
    185.                     pIn.diffuse = IN[0].diffuse;
    186.                     pIn.ambient = IN[0].ambient;
    187.                     triStream.Append(pIn);
    188.  
    189.                     triStream.RestartStrip();
    190.                 }
    191.  
    192.             }
    193.  
    194.             fixed4 frag(g2f i) : SV_Target
    195.             {
    196.  
    197.                 half    shadow = 1.0;
    198.  
    199.                 shadow = SHADOW_ATTENUATION(IN);
    200.  
    201.                 fixed4 originalCol = tex2D(_MainTex, i.originalUv) * tex2D(_Dirt, i.originalUv_unscaled);
    202.                 fixed col = tex2D(_FluffTex, i.uv).y;
    203.                 fixed mask = tex2D(_FluffTex, i.originalUv_unscaled).x;
    204.  
    205.                 //if (mask.r <= .5) discard;
    206.                 clip(mask.r - 0.75);
    207.  
    208.                 float clampcolorterm_uv2 = 1;
    209.                 clampcolorterm_uv2 -= clamp((-clamp(floor(i.uv2.x), -1, 0) + (clamp(ceil(i.uv2.x), 1, 2) - 1)), 0, 1);
    210.                 float4 decaldiff = 0;
    211.                 //#if defined(DECAL)
    212.                 decaldiff = tex2D(_Decals, i.uv2);
    213.                 //#endif
    214.                 col = lerp(col, 0, pow(decaldiff.w,2) / 2 * clampcolorterm_uv2);
    215.  
    216.                 originalCol.w *= col * mask;
    217.                 originalCol.xyz *= ((i.diffuse * shadow) + i.ambient);
    218.                 originalCol.xyz += i.falloff / 4;
    219.  
    220.                 return originalCol;// *col;
    221.             }
    222.  
    223.             ENDCG
    224.             }
     
  2. Marshi

    Marshi

    Joined:
    Jun 9, 2018
    Posts:
    2
    Anyone know what I need to do to fix the lighting in this? I'm sort of stuck at the moment until I can get the fluff to be lighter in color and properly working with all lighting conditions.
     
  3. VZPX

    VZPX

    Joined:
    Sep 5, 2021
    Posts:
    14
    do you think you could send the whole shader code?
     
  4. NathanielAH

    NathanielAH

    Joined:
    Jul 22, 2013
    Posts:
    100
    I realize this is an old thread; sorry to raise the dead, but wanted to see if you ever solved this?