-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Use a LUT for F_AB #23737
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Use a LUT for F_AB #23737
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| use crate::LtcLuts; | ||
| use crate::{FabLut, LtcLuts}; | ||
| use alloc::sync::Arc; | ||
| use bevy_core_pipeline::{ | ||
| oit::{resolve::is_oit_supported, OitBuffers, OrderIndependentTransparencySettings}, | ||
|
|
@@ -450,6 +450,14 @@ pub fn layout_entries( | |
| ), | ||
| (39, sampler(SamplerBindingType::Filtering)), | ||
| )); | ||
| // F_AB | ||
| entries = entries.extend_with_indices(( | ||
| ( | ||
| 40, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I hope we're not close to hitting binding limits on this 😬 if we are might consider reusing a linear sampler
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We are, hitting |
||
| texture_2d(TextureSampleType::Float { filterable: true }), | ||
| ), | ||
| (41, sampler(SamplerBindingType::Filtering)), | ||
| )); | ||
| let mut binding_array_entries = DynamicBindGroupLayoutEntries::new(ShaderStages::FRAGMENT); | ||
| binding_array_entries = binding_array_entries.extend_with_indices(( | ||
| (0, environment_map_entries[0]), | ||
|
|
@@ -648,13 +656,22 @@ pub fn prepare_mesh_view_bind_groups( | |
| Res<ContactShadowsBuffer>, | ||
| ), | ||
| oit_buffers: Res<OitBuffers>, | ||
| (decals_buffer, render_decals, atmosphere_buffer, atmosphere_sampler, blue_noise, ltc_luts): ( | ||
| ( | ||
| decals_buffer, | ||
| render_decals, | ||
| atmosphere_buffer, | ||
| atmosphere_sampler, | ||
| blue_noise, | ||
| ltc_luts, | ||
| fab_lut, | ||
| ): ( | ||
| Res<DecalsBuffer>, | ||
| Res<RenderClusteredDecals>, | ||
| Option<Res<AtmosphereBuffer>>, | ||
| Option<Res<AtmosphereSampler>>, | ||
| Res<Bluenoise>, | ||
| Res<LtcLuts>, | ||
| Res<FabLut>, | ||
| ), | ||
| ) { | ||
| if let ( | ||
|
|
@@ -842,6 +859,13 @@ pub fn prepare_mesh_view_bind_groups( | |
| (39, ltc2_sampler), | ||
| )); | ||
|
|
||
| // F_AB | ||
| let (fab_view, fab_sampler) = images | ||
| .get(&fab_lut.texture) | ||
| .map(|img| (&img.texture_view, &img.sampler)) | ||
| .unwrap_or((&fallback_image.d2.texture_view, &fallback_image.d2.sampler)); | ||
| entries = entries.extend_with_indices(((40, fab_view), (41, fab_sampler))); | ||
|
|
||
| let mut entries_binding_array = DynamicBindGroupEntries::new(); | ||
|
|
||
| let environment_map_bind_group_entries = RenderViewEnvironmentMapBindGroupEntries::get( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -526,16 +526,8 @@ fn Fd_Burley( | |
| } | ||
|
|
||
| // Scale/bias approximation | ||
| // https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile | ||
| // TODO: Use a LUT (more accurate) | ||
| fn F_AB(perceptual_roughness: f32, NdotV: f32) -> vec2<f32> { | ||
| let c0 = vec4<f32>(-1.0, -0.0275, -0.572, 0.022); | ||
| let c1 = vec4<f32>(1.0, 0.0425, 1.04, -0.04); | ||
| let r = perceptual_roughness * c0 + c1; | ||
| let a004 = min(r.x * r.x, exp2(-9.28 * NdotV)) * r.x + r.y; | ||
| // Keep F_ab positive to avoid divide-by-zero in downstream BRDF terms. | ||
| let f_ab_epsilon = 0.00005; | ||
| return max(vec2<f32>(-1.04, 1.04) * a004 + r.zw, vec2<f32>(f_ab_epsilon)); | ||
| return textureSampleLevel(view_bindings::f_ab_lut, view_bindings::f_ab_lut_sampler, vec2<f32>(NdotV, perceptual_roughness), 0.0).rg; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wouldn't completely replace the polynomial approximation with the lut lets keep both. Add a shader def and enable the LUT with a feature flag. We should discuss whether this should be opt in or on by default. |
||
| } | ||
|
|
||
| fn EnvBRDFApprox(F0: vec3<f32>, F_ab: vec2<f32>) -> vec3<f32> { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we need to gate this behind the ktx2 feature?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should feature gate this in general. Including these bytes here will increase the size of the binary so it should be opt in.
I explored this BRDF lut approach earlier for the PR from a month ago (clamp FAB)
https://github.com/mate-h/bevy/tree/m/brdf-lut
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll go with @mate-h's suggestion to feature-gate the LUT so ktx2 can just be enabled when we need it.
The LTC LUTs have the same problem, I'll open an issue.