commit 32106351c8a51e2dc2500356b947e863a01ddcdc parent ccb3229cbc04605c52635b8156ae60d83effb94f Author: Michael Savage <mikejsavage@gmail.com> Date: Mon Aug 28 11:36:19 +0100 Use Cook-Torrance BRDF in shadow map test Diffstat:
shaders/common.glsl | | | 18 | ++++++++++++++++++ |
shaders/pbr.glsl | | | 55 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
shaders/shadowed_vertex_colours.glsl | | | 12 | +++++++----- |
shaders/skybox.glsl | | | 8 | -------- |
shadow_map.cc | | | 2 | +- |
diff --git a/shaders/common.glsl b/shaders/common.glsl @@ -1,5 +1,23 @@ +const float PI = 3.14159265359; + vec3 alu_noise( vec2 uv ) { vec3 dither = vec3( dot( vec2( 171.0, 231.0 ), uv ) ); dither = fract( dither / vec3( 103.0, 71.0, 97.0 ) ) - vec3( 0.5, 0.5, 0.5 ); return ( dither / 256.0 ) * 0.5; } + +float saturate( float x ) { + return clamp( x, 0.0, 1.0 ); +} + +float unlerp( float x, float lo, float hi ) { + return ( x - lo ) / ( hi - lo ); +} + +float unlerp_sat( float x, float lo, float hi ) { + return saturate( unlerp( x, lo, hi ) ); +} + +float dot_sat( vec3 a, vec3 b ) { + return saturate( dot( a, b ) ); +} diff --git a/shaders/pbr.glsl b/shaders/pbr.glsl @@ -0,0 +1,55 @@ +float normal_distribution_ggx( vec3 N, vec3 H, float roughness ) { + float a = roughness * roughness; + float a2 = a * a; + float NdotH = dot_sat( N, H ); + float NdotH2 = NdotH * NdotH; + + float denom = ( NdotH2 * ( a2 - 1.0 ) + 1.0 ); + denom = PI * denom * denom; + + return a2 / denom; +} + +float geometry_distribution_schlick_ggx( float NdotV, float roughness ) { + float r = ( roughness + 1.0 ); + float k = ( r * r ) / 8.0; + + return NdotV / ( NdotV * ( 1.0 - k ) + k ); +} + +float geometry_distribution_smith( vec3 N, vec3 V, vec3 L, float roughness ) { + float NdotV = dot_sat( N, V ); + float NdotL = dot_sat( N, L ); + float ggx2 = geometry_distribution_schlick_ggx( NdotV, roughness ); + float ggx1 = geometry_distribution_schlick_ggx( NdotL, roughness ); + + return ggx1 * ggx2; +} + +vec3 fresnel_schlick( float cos_theta, vec3 F0 ) { + return F0 + ( 1.0 - F0 ) * pow( 1.0 - cos_theta, 5.0 ); +} + +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 ) { + vec3 L = normalize( light_position - surface_position ); + float distance = length( light_position - surface_position ); + float attenuation = 1.0 / ( distance * distance ); + vec3 radiance = light_colour * attenuation; + + vec3 H = normalize( to_camera + L ); + + vec3 F0 = vec3( 0.04 ); + F0 = mix( F0, albedo, metalness ); + + float NdotL = dot_sat( surface_normal, L ); + + float NDF = normal_distribution_ggx( surface_normal, H, roughness ); + float G = geometry_distribution_smith( surface_normal, to_camera, L, roughness ); + vec3 F = fresnel_schlick( dot_sat( H, to_camera ), F0 ); + vec3 diffuse_amount = ( vec3( 1.0 ) - F ) * ( 1.0 - metalness ); + + float denom = 4.0 * dot_sat( to_camera, surface_normal ) * NdotL + 0.001; + vec3 specular = ( NDF * G * F ) / denom; + + return ( diffuse_amount * albedo / PI + specular ) * radiance * NdotL; +} diff --git a/shaders/shadowed_vertex_colours.glsl b/shaders/shadowed_vertex_colours.glsl @@ -5,6 +5,7 @@ layout( std140 ) uniform model { layout( std140 ) uniform view { mat4 V; mat4 P; + vec3 camera_pos; }; layout( std140 ) uniform light_view { @@ -49,11 +50,9 @@ in VSOut v2f; out vec4 screen_colour; void main() { - vec3 light_colour = vec3( 1.0, 1.0, 1.0 ); + vec3 light_colour = vec3( 400.0, 400.0, 400.0 ); vec3 lightdir = normalize( v2f.position - light_pos ); - - float ambient = 0.1; - float lambert = max( 0, dot( -lightdir, normalize( v2f.normal ) ) ); + vec3 to_camera = normalize( camera_pos - v2f.position ); vec3 light_ndc = v2f.light_space_position.xyz / v2f.light_space_position.w; vec3 light_norm = light_ndc * 0.5 + 0.5; @@ -76,7 +75,10 @@ void main() { } } - screen_colour = vec4( v2f.colour * light_colour * ( ambient + ( 1 - ambient ) * ( lambert * shadow ) ), 1.0 ); + vec3 ambient = vec3( 0.03 ) * v2f.colour; + vec3 Lo = cook_torrance_brdf( to_camera, v2f.position, v2f.normal, light_pos, light_colour, v2f.colour, 0.75, 0.0 ); + + screen_colour = vec4( ambient + Lo * shadow, 1.0 ); } #endif diff --git a/shaders/skybox.glsl b/shaders/skybox.glsl @@ -23,14 +23,6 @@ layout( std140 ) uniform sun { float sun_angle; }; -float saturate( float x ) { - return clamp( x, 0.0, 1.0 ); -} - -float unlerp_sat( float x, float lo, float hi ) { - return saturate( ( x - lo ) / ( hi - lo ) ); -} - float hdot( vec3 u, vec3 v ) { float d = dot( u, v ) * 0.5 + 0.5; return d * d; diff --git a/shadow_map.cc b/shadow_map.cc @@ -132,7 +132,7 @@ GAME_FRAME( game_frame ) { renderer_begin_frame(); - renderer_ub_easy( ub_view, V, P ); + renderer_ub_easy( ub_view, V, P, game->pos ); { m4 lightVP;