From acde421dc70eb573e5f66b1874118e18d8de92f5 Mon Sep 17 00:00:00 2001 From: robtfm <50659922+robtfm@users.noreply.github.com> Date: Fri, 22 Jul 2022 17:33:01 +0100 Subject: [PATCH 1/4] add ambient occlusion hook --- crates/bevy_pbr/src/lib.rs | 8 ++++++++ crates/bevy_pbr/src/render/pbr.wgsl | 6 ++++-- crates/bevy_pbr/src/render/pbr_occlusion.wgsl | 5 +++++ 3 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 crates/bevy_pbr/src/render/pbr_occlusion.wgsl diff --git a/crates/bevy_pbr/src/lib.rs b/crates/bevy_pbr/src/lib.rs index 5d190540579ea..9963e187f7bcd 100644 --- a/crates/bevy_pbr/src/lib.rs +++ b/crates/bevy_pbr/src/lib.rs @@ -69,6 +69,8 @@ pub const PBR_SHADER_HANDLE: HandleUntyped = HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 4805239651767701046); pub const PBR_FUNCTIONS_HANDLE: HandleUntyped = HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 16550102964439850292); +pub const PBR_OCCLUSION_HANDLE: HandleUntyped = + HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 2441520459096337034); pub const SHADOW_SHADER_HANDLE: HandleUntyped = HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 1836745567947005696); @@ -115,6 +117,12 @@ impl Plugin for PbrPlugin { "render/pbr_functions.wgsl", Shader::from_wgsl ); + load_internal_asset!( + app, + PBR_OCCLUSION_HANDLE, + "render/pbr_occlusion.wgsl", + Shader::from_wgsl + ); load_internal_asset!(app, PBR_SHADER_HANDLE, "render/pbr.wgsl", Shader::from_wgsl); load_internal_asset!( app, diff --git a/crates/bevy_pbr/src/render/pbr.wgsl b/crates/bevy_pbr/src/render/pbr.wgsl index b70b5b333943c..fa764d283e5c7 100644 --- a/crates/bevy_pbr/src/render/pbr.wgsl +++ b/crates/bevy_pbr/src/render/pbr.wgsl @@ -7,6 +7,7 @@ #import bevy_pbr::lighting #import bevy_pbr::shadows #import bevy_pbr::pbr_functions +#import bevy_pbr::pbr_occlusion struct FragmentInput { @builtin(front_facing) is_front: bool, @@ -65,8 +66,6 @@ fn fragment(in: FragmentInput) -> @location(0) vec4 { occlusion = textureSample(occlusion_texture, occlusion_sampler, in.uv).r; } #endif - pbr_input.occlusion = occlusion; - pbr_input.frag_coord = in.frag_coord; pbr_input.world_position = in.world_position; pbr_input.world_normal = in.world_normal; @@ -88,6 +87,9 @@ fn fragment(in: FragmentInput) -> @location(0) vec4 { ); pbr_input.V = calculate_view(in.world_position, pbr_input.is_orthographic); + occlusion = ambient_occlusion(occlusion, pbr_input.world_position, pbr_input.N); + pbr_input.occlusion = occlusion; + output_color = tone_mapping(pbr(pbr_input)); } diff --git a/crates/bevy_pbr/src/render/pbr_occlusion.wgsl b/crates/bevy_pbr/src/render/pbr_occlusion.wgsl new file mode 100644 index 0000000000000..07088423a710b --- /dev/null +++ b/crates/bevy_pbr/src/render/pbr_occlusion.wgsl @@ -0,0 +1,5 @@ +#define_import_path bevy_pbr::pbr_occlusion + +fn ambient_occlusion(occlusion: f32, world_position: vec4, world_normal: vec3) -> f32 { + return occlusion; +} \ No newline at end of file From 58150a78a1934dac4181bb5630cadeebe8efae02 Mon Sep 17 00:00:00 2001 From: robtfm <50659922+robtfm@users.noreply.github.com> Date: Sun, 24 Jul 2022 21:17:08 +0100 Subject: [PATCH 2/4] ambient hook --- crates/bevy_pbr/src/lib.rs | 6 +++--- crates/bevy_pbr/src/render/pbr.wgsl | 3 +-- crates/bevy_pbr/src/render/pbr_ambient.wgsl | 18 ++++++++++++++++++ crates/bevy_pbr/src/render/pbr_functions.wgsl | 9 +++------ crates/bevy_pbr/src/render/pbr_occlusion.wgsl | 5 ----- 5 files changed, 25 insertions(+), 16 deletions(-) create mode 100644 crates/bevy_pbr/src/render/pbr_ambient.wgsl delete mode 100644 crates/bevy_pbr/src/render/pbr_occlusion.wgsl diff --git a/crates/bevy_pbr/src/lib.rs b/crates/bevy_pbr/src/lib.rs index 9963e187f7bcd..c59fb11990263 100644 --- a/crates/bevy_pbr/src/lib.rs +++ b/crates/bevy_pbr/src/lib.rs @@ -69,7 +69,7 @@ pub const PBR_SHADER_HANDLE: HandleUntyped = HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 4805239651767701046); pub const PBR_FUNCTIONS_HANDLE: HandleUntyped = HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 16550102964439850292); -pub const PBR_OCCLUSION_HANDLE: HandleUntyped = +pub const PBR_AMBIENT_HANDLE: HandleUntyped = HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 2441520459096337034); pub const SHADOW_SHADER_HANDLE: HandleUntyped = HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 1836745567947005696); @@ -119,8 +119,8 @@ impl Plugin for PbrPlugin { ); load_internal_asset!( app, - PBR_OCCLUSION_HANDLE, - "render/pbr_occlusion.wgsl", + PBR_AMBIENT_HANDLE, + "render/pbr_ambient.wgsl", Shader::from_wgsl ); load_internal_asset!(app, PBR_SHADER_HANDLE, "render/pbr.wgsl", Shader::from_wgsl); diff --git a/crates/bevy_pbr/src/render/pbr.wgsl b/crates/bevy_pbr/src/render/pbr.wgsl index fa764d283e5c7..679fca5817fe6 100644 --- a/crates/bevy_pbr/src/render/pbr.wgsl +++ b/crates/bevy_pbr/src/render/pbr.wgsl @@ -5,9 +5,9 @@ #import bevy_pbr::utils #import bevy_pbr::clustered_forward #import bevy_pbr::lighting +#import bevy_pbr::pbr_ambient #import bevy_pbr::shadows #import bevy_pbr::pbr_functions -#import bevy_pbr::pbr_occlusion struct FragmentInput { @builtin(front_facing) is_front: bool, @@ -87,7 +87,6 @@ fn fragment(in: FragmentInput) -> @location(0) vec4 { ); pbr_input.V = calculate_view(in.world_position, pbr_input.is_orthographic); - occlusion = ambient_occlusion(occlusion, pbr_input.world_position, pbr_input.N); pbr_input.occlusion = occlusion; output_color = tone_mapping(pbr(pbr_input)); diff --git a/crates/bevy_pbr/src/render/pbr_ambient.wgsl b/crates/bevy_pbr/src/render/pbr_ambient.wgsl new file mode 100644 index 0000000000000..cb8ff6d4fbc9e --- /dev/null +++ b/crates/bevy_pbr/src/render/pbr_ambient.wgsl @@ -0,0 +1,18 @@ +#define_import_path bevy_pbr::pbr_ambient + +fn ambient_light( + world_position: vec4, + world_normal: vec3, + V: vec3, + diffuse_color: vec3, + specular_color: vec3, + perceptual_roughness: f32, + occlusion: f32, +) -> vec3 { + let NdotV = max(dot(world_normal, V), 0.0001); + + let diffuse_ambient = EnvBRDFApprox(diffuse_color, 1.0, NdotV); + let specular_ambient = EnvBRDFApprox(specular_color, perceptual_roughness, NdotV); + + return (diffuse_ambient + specular_ambient) * lights.ambient_color.rgb * occlusion; +} \ No newline at end of file diff --git a/crates/bevy_pbr/src/render/pbr_functions.wgsl b/crates/bevy_pbr/src/render/pbr_functions.wgsl index cd922bf74412c..89dfd2770f4b7 100644 --- a/crates/bevy_pbr/src/render/pbr_functions.wgsl +++ b/crates/bevy_pbr/src/render/pbr_functions.wgsl @@ -213,13 +213,10 @@ fn pbr( light_accum = light_accum + light_contrib * shadow; } - let diffuse_ambient = EnvBRDFApprox(diffuse_color, 1.0, NdotV); - let specular_ambient = EnvBRDFApprox(F0, perceptual_roughness, NdotV); + let ambient_contrib = ambient_light(in.world_position, in.N, in.V, diffuse_color, F0, perceptual_roughness, occlusion); output_color = vec4( - light_accum + - (diffuse_ambient + specular_ambient) * lights.ambient_color.rgb * occlusion + - emissive.rgb * output_color.a, + light_accum + ambient_contrib + emissive.rgb * output_color.a, output_color.a); output_color = cluster_debug_visualization( @@ -240,4 +237,4 @@ fn tone_mapping(in: vec4) -> vec4 { // Gamma correction. // Not needed with sRGB buffer // output_color.rgb = pow(output_color.rgb, vec3(1.0 / 2.2)); -} +} \ No newline at end of file diff --git a/crates/bevy_pbr/src/render/pbr_occlusion.wgsl b/crates/bevy_pbr/src/render/pbr_occlusion.wgsl deleted file mode 100644 index 07088423a710b..0000000000000 --- a/crates/bevy_pbr/src/render/pbr_occlusion.wgsl +++ /dev/null @@ -1,5 +0,0 @@ -#define_import_path bevy_pbr::pbr_occlusion - -fn ambient_occlusion(occlusion: f32, world_position: vec4, world_normal: vec3) -> f32 { - return occlusion; -} \ No newline at end of file From 6af4af8608cf023c4c073f9866f979e3a83e97c0 Mon Sep 17 00:00:00 2001 From: atlas dostal Date: Mon, 16 Jan 2023 14:22:10 -0800 Subject: [PATCH 3/4] Pass precomputed NdotV --- crates/bevy_pbr/src/render/pbr_ambient.wgsl | 13 ++++++------- crates/bevy_pbr/src/render/pbr_functions.wgsl | 3 +-- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/crates/bevy_pbr/src/render/pbr_ambient.wgsl b/crates/bevy_pbr/src/render/pbr_ambient.wgsl index cb8ff6d4fbc9e..5f336f8771652 100644 --- a/crates/bevy_pbr/src/render/pbr_ambient.wgsl +++ b/crates/bevy_pbr/src/render/pbr_ambient.wgsl @@ -1,16 +1,15 @@ #define_import_path bevy_pbr::pbr_ambient fn ambient_light( - world_position: vec4, - world_normal: vec3, - V: vec3, - diffuse_color: vec3, - specular_color: vec3, + world_position: vec4, + world_normal: vec3, + V: vec3, + NdotV: f32, + diffuse_color: vec3, + specular_color: vec3, perceptual_roughness: f32, occlusion: f32, ) -> vec3 { - let NdotV = max(dot(world_normal, V), 0.0001); - let diffuse_ambient = EnvBRDFApprox(diffuse_color, 1.0, NdotV); let specular_ambient = EnvBRDFApprox(specular_color, perceptual_roughness, NdotV); diff --git a/crates/bevy_pbr/src/render/pbr_functions.wgsl b/crates/bevy_pbr/src/render/pbr_functions.wgsl index 8bfa3a5a93aa9..4e3bf3d8ea9e4 100644 --- a/crates/bevy_pbr/src/render/pbr_functions.wgsl +++ b/crates/bevy_pbr/src/render/pbr_functions.wgsl @@ -231,7 +231,7 @@ fn pbr( light_accum = light_accum + light_contrib * shadow; } - let ambient_contrib = ambient_light(in.world_position, in.N, in.V, diffuse_color, F0, perceptual_roughness, occlusion); + let ambient_contrib = ambient_light(in.world_position, in.N, in.V, NdotV, diffuse_color, F0, perceptual_roughness, occlusion); output_color = vec4( light_accum + ambient_contrib + emissive.rgb * output_color.a, @@ -264,4 +264,3 @@ fn dither(color: vec4, pos: vec2) -> vec4 { return vec4(color.rgb + screen_space_dither(pos.xy), color.a); } #endif - From fa88d767ad7a1fb843729d423b3ccec951acce2d Mon Sep 17 00:00:00 2001 From: atlas dostal Date: Mon, 16 Jan 2023 14:24:22 -0800 Subject: [PATCH 4/4] Document NdotV vs N and V --- crates/bevy_pbr/src/render/pbr_ambient.wgsl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/bevy_pbr/src/render/pbr_ambient.wgsl b/crates/bevy_pbr/src/render/pbr_ambient.wgsl index 5f336f8771652..8ef380ac5a2f1 100644 --- a/crates/bevy_pbr/src/render/pbr_ambient.wgsl +++ b/crates/bevy_pbr/src/render/pbr_ambient.wgsl @@ -1,5 +1,7 @@ #define_import_path bevy_pbr::pbr_ambient +// A precomputed `NdotV` is provided because it is computed regardless, +// but `world_normal` and the view vector `V` are provided separately for more advanced uses. fn ambient_light( world_position: vec4, world_normal: vec3,