diff --git a/src/shader.wgsl b/src/shader.wgsl index 5a055bf..0fa21c7 100644 --- a/src/shader.wgsl +++ b/src/shader.wgsl @@ -116,6 +116,45 @@ fn BRDF( return (Fr + Fd) * NoL; } +fn sample_ibl_fake( + n_color: vec3, + s_color: vec3, + gradient: f32, + coords: vec3, +) -> vec3 { + let blend = coords.y / gradient + 0.5; + return mix(s_color, n_color, clamp(blend, 0.0, 1.0)); +} + +fn F_Schlick_Roughness(cos_theta: f32, f0: vec3, roughness: f32) -> vec3 { + return f0 + (max(vec3(1.0 - roughness), f0) - f0) * pow(clamp(1.0 - cos_theta, 0.0, 1.0), 5.0); +} + +let N_COLOR = vec3(0.7, 0.0, 1.0); +let S_COLOR = vec3(0.1, 0.1, 0.1); +let IBL_G = 1.0; + +fn fake_ibl( + n: vec3, // normalized surface normal + v: vec3, // normalized view direction + albedo: vec3, // surface albedo + metallic: f32, // surface metallic + roughness: f32, // surface roughness +) -> vec3 { + // calculate reflectance at surface incidence + let f0 = mix(vec3(0.04), albedo, metallic); + let kS = F_Schlick_Roughness(max(dot(n, v), 0.0), f0, roughness); + let kD = 1.0 - kS; + let diffuse = sample_ibl_fake(N_COLOR, S_COLOR, IBL_G, n); + + let R = normalize(reflect(-v, n)); + let specular = sample_ibl_fake(N_COLOR, S_COLOR, IBL_G, R); + + let received = kD * diffuse + kS * specular; + + return received * albedo; +} + [[stage(vertex)]] fn vs_main( [[builtin(instance_index)]] mesh_idx: u32, @@ -162,5 +201,8 @@ fn fs_main( lum = lum + (radiance * reflected); } - return vec4(lum, 1.0); + lum = lum + fake_ibl(normal, view, albedo, metallic, roughness); + + let tone_mapped = lum / (lum + 1.0); + return vec4(tone_mapped, 1.0); }