medfall

A super great game engine
Log | Files | Refs

pbr.glsl (1896B)


      1 float normal_distribution_ggx( vec3 N, vec3 H, float roughness ) {
      2 	float a = roughness * roughness;
      3 	float a2 = a * a;
      4 	float NdotH = dot_sat( N, H );
      5 	float NdotH2 = NdotH * NdotH;
      6 
      7 	float denom = ( NdotH2 * ( a2 - 1.0 ) + 1.0 );
      8 	denom = PI * denom * denom;
      9 
     10 	return a2 / denom;
     11 }
     12 
     13 float geometry_distribution_schlick_ggx( float NdotV, float roughness ) {
     14 	float r = ( roughness + 1.0 );
     15 	float k = ( r * r ) / 8.0;
     16 
     17 	return NdotV / ( NdotV * ( 1.0 - k ) + k );
     18 }
     19 
     20 float geometry_distribution_smith( vec3 N, vec3 V, vec3 L, float roughness ) {
     21 	float NdotV = dot_sat( N, V );
     22 	float NdotL = dot_sat( N, L );
     23 	float ggx2 = geometry_distribution_schlick_ggx( NdotV, roughness );
     24 	float ggx1 = geometry_distribution_schlick_ggx( NdotL, roughness );
     25 
     26 	return ggx1 * ggx2;
     27 }
     28 
     29 vec3 fresnel_schlick( float cos_theta, vec3 F0 ) {
     30 	return F0 + ( 1.0 - F0 ) * pow( 1.0 - cos_theta, 5.0 );
     31 }
     32 
     33 vec3 cook_torrance_brdf( vec3 to_camera, vec3 surface_position, vec3 surface_normal, vec3 light_position, vec3 light_colour, vec3 albedo, float roughness, float metalness ) {
     34 	vec3 L = normalize( light_position - surface_position );
     35 	float distance = length( light_position - surface_position );
     36 	float attenuation = 1.0 / ( distance * distance );
     37 	vec3 radiance = light_colour * attenuation;
     38 
     39 	vec3 H = normalize( to_camera + L );
     40 
     41 	vec3 F0 = vec3( 0.04 );
     42 	F0 = mix( F0, albedo, metalness );
     43 
     44 	float NdotL = dot_sat( surface_normal, L );
     45 
     46 	float NDF = normal_distribution_ggx( surface_normal, H, roughness );
     47 	float G = geometry_distribution_smith( surface_normal, to_camera, L, roughness );
     48 	vec3 F = fresnel_schlick( dot_sat( H, to_camera ), F0 );
     49 	vec3 diffuse_amount = ( vec3( 1.0 ) - F ) * ( 1.0 - metalness );
     50 
     51 	float denom = 4.0 * dot_sat( to_camera, surface_normal ) * NdotL + 0.001;
     52 	vec3 specular = ( NDF * G * F ) / denom;
     53 
     54 	return ( diffuse_amount * albedo / PI + specular ) * radiance * NdotL;
     55 }