Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We are updating our Terms of Service for all Unity subscription plans, effective October 13, 2022, to create a more streamlined, user-friendly set of terms. Please review them here: unity.com/legal/terms-of-service.
    Dismiss Notice
  3. Have a look at our Games Focus blog post series which will show what Unity is doing for all game developers – now, next year, and in the future.
    Dismiss Notice

Disney Principled BRDF shader

Discussion in 'Shaders' started by GreatWall, May 10, 2019.

  1. GreatWall

    GreatWall

    Joined:
    Aug 7, 2014
    Posts:
    57

    Attached Files:

  2. Przemyslaw_Zaworski

    Przemyslaw_Zaworski

    Joined:
    Jun 9, 2017
    Posts:
    279
    Direct implementation, but still requires improvements:

    Code (CSharp):
    1. Shader "Disney"
    2. {
    3.     Properties
    4.     {
    5.         metallic ("Metallic", Range (0.0,1.0)) = 0.0
    6.         subsurface ("Subsurface", Range (0.0,1.0)) = 0.0
    7.         _specular ("Specular", Range (0.0,1.0)) = 0.0
    8.         roughness ("Roughness", Range (0.0,1.0)) = 0.5
    9.         specularTint ("SpecularTint", Range (0.0,1.0)) = 0.0
    10.         anisotropic ("Anisotropic", Range (0.0,1.0)) = 0.0
    11.         sheen ("Sheen", Range (0.0,1.0)) = 0.0
    12.         sheenTint ("SheenTint", Range (0.0,1.0)) = 0.5
    13.         clearcoat ("Clearcoat", Range (0.0,1.0)) = 0.0
    14.         clearcoatGloss ("ClearcoatGloss", Range (0.0,1.0)) = 1.0
    15.     }
    16.     SubShader
    17.     {
    18.         Pass
    19.         {
    20.             CGPROGRAM
    21.             #pragma vertex VSMain
    22.             #pragma fragment PSMain
    23.  
    24.             static const float3 baseColor = float3(1,1,1);
    25.             float metallic, subsurface, _specular, roughness, specularTint, anisotropic, sheen,
    26.             sheenTint, clearcoat, clearcoatGloss;
    27.                        
    28.             static const float PI = 3.14159265358979323846;
    29.  
    30.             float sqr(float x) { return x*x; }
    31.  
    32.             float SchlickFresnel(float u)
    33.             {
    34.                 float m = clamp(1-u, 0, 1);
    35.                 float m2 = m*m;
    36.                 return m2*m2*m; // pow(m,5)
    37.             }
    38.  
    39.             float GTR1(float NdotH, float a)
    40.             {
    41.                 if (a >= 1) return 1/PI;
    42.                 float a2 = a*a;
    43.                 float t = 1 + (a2-1)*NdotH*NdotH;
    44.                 return (a2-1) / (PI*log(a2)*t);
    45.             }
    46.  
    47.             float GTR2(float NdotH, float a)
    48.             {
    49.                 float a2 = a*a;
    50.                 float t = 1 + (a2-1)*NdotH*NdotH;
    51.                 return a2 / (PI * t*t);
    52.             }
    53.  
    54.             float GTR2_aniso(float NdotH, float HdotX, float HdotY, float ax, float ay)
    55.             {
    56.                 return 1 / (PI * ax*ay * sqr( sqr(HdotX/ax) + sqr(HdotY/ay) + NdotH*NdotH ));
    57.             }
    58.  
    59.             float smithG_GGX(float NdotV, float alphaG)
    60.             {
    61.                 float a = alphaG*alphaG;
    62.                 float b = NdotV*NdotV;
    63.                 return 1 / (NdotV + sqrt(a + b - a*b));
    64.             }
    65.  
    66.             float smithG_GGX_aniso(float NdotV, float VdotX, float VdotY, float ax, float ay)
    67.             {
    68.                 return 1 / (NdotV + sqrt( sqr(VdotX*ax) + sqr(VdotY*ay) + sqr(NdotV) ));
    69.             }
    70.  
    71.             float3 mon2lin(float3 x)
    72.             {
    73.                 return float3(pow(x[0], 2.2), pow(x[1], 2.2), pow(x[2], 2.2));
    74.             }
    75.  
    76.             float3 BRDF( float3 L, float3 V, float3 N, float3 X, float3 Y )
    77.             {
    78.                 float NdotL = max(dot(N,L),0.0);
    79.                 float NdotV = max(dot(N,V),0.0);
    80.  
    81.                 float3 H = normalize(L+V);
    82.                 float NdotH = max(dot(N,H),0.0);
    83.                 float LdotH = max(dot(L,H),0.0);
    84.  
    85.                 float3 Cdlin = mon2lin(baseColor);
    86.                 float Cdlum = .3*Cdlin[0] + .6*Cdlin[1]  + .1*Cdlin[2]; // luminance approx.
    87.  
    88.                 float3 Ctint = Cdlum > 0 ? Cdlin/Cdlum : float3(1,1,1); // normalize lum. to isolate hue+sat
    89.                 float3 Cspec0 = lerp(_specular*.08*lerp(float3(1,1,1), Ctint, specularTint), Cdlin, metallic);
    90.                 float3 Csheen = lerp(float3(1,1,1), Ctint, sheenTint);
    91.  
    92.                 // Diffuse fresnel - go from 1 at normal incidence to .5 at grazing
    93.                 // and lerp in diffuse retro-reflection based on roughness
    94.                 float FL = SchlickFresnel(NdotL), FV = SchlickFresnel(NdotV);
    95.                 float Fd90 = 0.5 + 2 * LdotH*LdotH * roughness;
    96.                 float Fd = lerp(1.0, Fd90, FL) * lerp(1.0, Fd90, FV);
    97.  
    98.                 // Based on Hanrahan-Krueger brdf approximation of isotropic bssrdf
    99.                 // 1.25 scale is used to (roughly) preserve albedo
    100.                 // Fss90 used to "flatten" retroreflection based on roughness
    101.                 float Fss90 = LdotH*LdotH*roughness;
    102.                 float Fss = lerp(1.0, Fss90, FL) * lerp(1.0, Fss90, FV);
    103.                 float ss = 1.25 * (Fss * (1 / (NdotL + NdotV) - .5) + .5);
    104.  
    105.                 // specular
    106.                 float aspect = sqrt(1-anisotropic*.9);
    107.                 float ax = max(.001, sqr(roughness)/aspect);
    108.                 float ay = max(.001, sqr(roughness)*aspect);
    109.                 float Ds = GTR2_aniso(NdotH, dot(H, X), dot(H, Y), ax, ay);
    110.                 float FH = SchlickFresnel(LdotH);
    111.                 float3 Fs = lerp(Cspec0, float3(1,1,1), FH);
    112.                 float Gs  = smithG_GGX_aniso(NdotL, dot(L, X), dot(L, Y), ax, ay);
    113.                 Gs *= smithG_GGX_aniso(NdotV, dot(V, X), dot(V, Y), ax, ay);
    114.  
    115.                 // sheen
    116.                 float3 Fsheen = FH * sheen * Csheen;
    117.  
    118.                 // clearcoat (ior = 1.5 -> F0 = 0.04)
    119.                 float Dr = GTR1(NdotH, lerp(.1,.001,clearcoatGloss));
    120.                 float Fr = lerp(.04, 1.0, FH);
    121.                 float Gr = smithG_GGX(NdotL, .25) * smithG_GGX(NdotV, .25);
    122.  
    123.                 return ((1/PI) * lerp(Fd, ss, subsurface)*Cdlin + Fsheen) * (1-metallic) + Gs*Fs*Ds + .25*clearcoat*Gr*Fr*Dr;
    124.             }
    125.            
    126.             void VSMain (inout float4 vertex:POSITION, inout float2 uv:TEXCOORD0, inout float3 normal:NORMAL, inout float4 tangent:TANGENT, out float3 world:TEXCOORD1)
    127.             {
    128.                 world = mul(unity_ObjectToWorld, vertex).xyz;
    129.                 vertex = UnityObjectToClipPos(vertex);
    130.             }
    131.  
    132.             float4 PSMain (float4 vertex:POSITION, float2 uv:TEXCOORD0, float3 normal:NORMAL, float4 tangent:TANGENT, float3 world:TEXCOORD1) : SV_TARGET
    133.             {
    134.                 float3 LightDirection = normalize(lerp(_WorldSpaceLightPos0.xyz, _WorldSpaceLightPos0.xyz - world,_WorldSpaceLightPos0.w));
    135.                 float3 NormalDirection = normalize(mul((float3x3)unity_ObjectToWorld,normal));
    136.                 float3 ViewDirection = normalize( _WorldSpaceCameraPos.xyz - world);
    137.                 float3 WorldTangent = mul((float3x3)unity_ObjectToWorld,tangent.xyz);
    138.                 float3 WorldBinormal = cross(NormalDirection,WorldTangent)*tangent.w;
    139.                 return float4(BRDF( LightDirection, ViewDirection, NormalDirection, WorldTangent, WorldBinormal ), 1.0);
    140.             }
    141.             ENDCG
    142.         }
    143.     }
    144. }
    145.  
     
  3. GreatWall

    GreatWall

    Joined:
    Aug 7, 2014
    Posts:
    57
unityunity