Advertisement
Guest User

CustomPBR

a guest
Apr 12th, 2017
206
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. Shader "ShaderChallenge/CustomPBR"
  2. {
  3.     Properties
  4.     {
  5.         _Albedo("Albedo", 2D) = "white" {}
  6.         _Roughness("Roughness", Range(0, 1)) = 1.0
  7.         _Metallic("Metallic", Range(0, 1)) = 0.0
  8.     }
  9.     SubShader
  10.     {
  11.         Pass
  12.         {
  13.             Tags { "LightMode" = "ForwardBase" }
  14.  
  15.             CGPROGRAM
  16.             #pragma vertex vert
  17.             #pragma fragment frag
  18.             #include "UnityStandardBRDF.cginc"
  19.  
  20.             #define pi 3.14159265359
  21.  
  22.             sampler2D _Albedo;
  23.             float _Roughness;
  24.             float _Metallic;
  25.  
  26.             struct v2f
  27.             {
  28.                 float4 pos : SV_POSITION;
  29.                 float3 worldPos : TEXCOORD0;
  30.                 float3 normal : TEXCOORD1;
  31.                 float2 uv : TEXCOORD2;
  32.             };
  33.  
  34.             v2f vert(appdata_base v)
  35.             {
  36.                 v2f o;
  37.                 o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
  38.                 // Convert vertex position to world space
  39.                 o.worldPos = mul(unity_ObjectToWorld, v.vertex);
  40.                 // Normal vector
  41.                 o.normal = UnityObjectToWorldNormal(v.normal);
  42.                 o.uv = v.texcoord;
  43.                 return o;
  44.             }
  45.  
  46.             // Oren-Nayar
  47.             float OrenNayar(float3 n, float3 v, float3 l)
  48.             {
  49.                 float nl = dot(n, l);
  50.                 float nv = dot(n, v);
  51.  
  52.                 float anglenl = acos(nl);
  53.                 float anglenv = acos(nv);
  54.  
  55.                 float alpha = max(anglenv, anglenl);
  56.                 float beta = min(anglenv, anglenl);
  57.                 float gamma = dot(v - n * nv, l - n * nl);
  58.  
  59.                 float a2 = pow(_Roughness, 2.0);
  60.  
  61.                 float A = 1.0 - 0.5 * (a2 / (a2 + 0.57));
  62.    
  63.                 float B = 0.45 * (a2 / (a2 + 0.09));
  64.    
  65.                 float C = sin(alpha) * tan(beta);
  66.    
  67.                 float result = max(0.0, nl) * (A + B * max(0.0, gamma) * C);
  68.    
  69.                 return result;
  70.             }
  71.  
  72.             float DistributionGGX(float3 n, float3 h)
  73.             {
  74.                 float a2 = pow(_Roughness, 2.0);
  75.                 float nh = dot(n, h);
  76.                 float nh2 = pow(nh, 2.0);
  77.  
  78.                 float num = a2;
  79.                 float den = (nh2 * (a2 - 1.0) + 1.0);
  80.                 den = pi * pow(den, 2.0);
  81.  
  82.                 return num / den;
  83.             }
  84.            
  85.             float GeometrySchlickGGX(float dot, float k)
  86.             {
  87.                 float num   = dot;
  88.                 float den = dot * (1.0 - k) + k;
  89.    
  90.                 return num / den;
  91.             }
  92.  
  93.             float GeometrySmith(float3 n, float3 v, float3 l)
  94.             {
  95.                 float k = pow(_Roughness + 1.0, 2.0) / 8.0;
  96.  
  97.                 float nv = DotClamped(n, v);
  98.                 float nl = DotClamped(n, l);
  99.                 float ggx1 = GeometrySchlickGGX(nv, k);
  100.                 float ggx2 = GeometrySchlickGGX(nl, k);
  101.  
  102.                 return ggx1 * ggx2;
  103.             }
  104.  
  105.             float3 FresnelSchlick(float3 n, float3 v, float3 albedo)
  106.             {
  107.                 float cosTheta = dot(n, v);
  108.                 float3 F0 = 0.04;
  109.                 F0 = lerp(F0, albedo, _Metallic);
  110.  
  111.                 return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
  112.             }
  113.  
  114.             float3 FresnelSchlickRoughness(float3 n, float3 v, float3 albedo)
  115.             {
  116.                 float cosTheta = dot(n, v);
  117.                 float3 F0 = 0.04;
  118.                 F0 = lerp(max(1.0 - _Roughness, F0), albedo, _Metallic);
  119.  
  120.                 return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
  121.             }
  122.  
  123.             float3 Microfacet(float3 n, float3 h, float3 v, float3 l, float3 albedo)
  124.             {
  125.                 float d = DistributionGGX(h, n);
  126.                 float g = GeometrySmith(n, v, l);
  127.                 float3 f = FresnelSchlick(n, v, albedo);
  128.    
  129.                 return (d * g * f) / 4.0 * DotClamped(n, l) * DotClamped(n, v) + 0.001;
  130.             }
  131.  
  132.             float4 frag(v2f i) : SV_TARGET
  133.             {
  134.                 float3 lightCol = _LightColor0.rgb;
  135.  
  136.                 // Normalize the normal
  137.                 float3 n = normalize(i.normal);
  138.                 // Light vector from mesh's surface
  139.                 float3 l = normalize(_WorldSpaceLightPos0.xyz);
  140.                 // Viewport(camera) vector from mesh's surface
  141.                 float3 v = normalize(_WorldSpaceCameraPos - i.worldPos.xyz);
  142.                 // Halfway vector
  143.                 float3 h = normalize(l + v);
  144.  
  145.                 float3 albedo = tex2D(_Albedo, i.uv).rgb;
  146.                 float3 ambient = unity_AmbientSky;
  147.  
  148.                 float3 kS = FresnelSchlickRoughness(n, v, albedo);
  149.                 float3 kD = 1.0 - kS;
  150.                 kD *= 1.0 - _Metallic;
  151.                
  152.                 float3 specular = Microfacet(n, h, v, l, albedo) * lightCol;
  153.  
  154.                 float3 worldRefl = reflect(-v, n);
  155.  
  156.                 float4 probe = UNITY_SAMPLE_TEXCUBE_LOD (unity_SpecCube0, worldRefl, _Roughness * 6.0);
  157.                 specular += DecodeHDR(probe, unity_SpecCube0_HDR);
  158.                 specular *= lightCol;
  159.  
  160.                 float3 diffuse = ambient + OrenNayar(n, v, l) * lightCol;
  161.                 diffuse *= 1.0 - _Metallic;
  162.  
  163.                 float3 color = albedo * diffuse + specular;
  164.  
  165.                 return float4(color, 1.0);
  166.             }
  167.             ENDCG
  168.         }
  169.     }
  170. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement