Guest User

Custom PBR

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