-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
Procedural atmospheric scattering #16314
Open
ecoskey
wants to merge
113
commits into
bevyengine:main
Choose a base branch
from
ecoskey:proc_sky
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+2,585
−24
Open
Changes from 110 commits
Commits
Show all changes
113 commits
Select commit
Hold shift + click to select a range
9d948ab
wip
ecoskey 515dfde
WIP
ecoskey ceb4af1
Merge branch 'main' into proc_sky
ecoskey 534f505
WIP
ecoskey 3fa0980
use buffer binding
ecoskey d5c58f0
WIP + example
ecoskey 28bd632
bind groups and more prep
ecoskey 4c3de51
WIP
ecoskey e18baec
add ground albedo to bind groups
ecoskey 823a338
add apply pass
ecoskey 222b11d
bwah
ecoskey 39c1075
WIP + finished aerial view lut
ecoskey a682732
small fixes
ecoskey fdc86c5
update bindings
ecoskey 6f3a7c5
Merge branch 'main' into proc_sky
ecoskey 0096c59
WIP
ecoskey bad3819
use buffer binding
ecoskey c1c73a1
WIP + example
ecoskey 6ed73d4
bind groups and more prep
ecoskey 1b215d8
WIP
ecoskey 6050cb3
add ground albedo to bind groups
ecoskey 3c4420f
add apply pass
ecoskey 98285f3
bwah
ecoskey 5cabba8
WIP + finished aerial view lut
ecoskey 6e9251b
small fixes
ecoskey 33ded2f
update bindings
ecoskey 40a9b54
Merge branch 'proc_sky' of github.com:ecoskey/bevy into proc_sky
ecoskey 7f05f5d
sky_view_lut progress
ecoskey 9be3e7b
fix bindings and such
ecoskey 7f1ed99
misc fixes
ecoskey 818d556
partially working thing maybe
ecoskey af99fe3
gwah
ecoskey 73c56c1
progress???
ecoskey dbfbcc9
cleanup and bindings
ecoskey 7c1d767
wip
ecoskey 966266c
fix a bunch of things
ecoskey cbf6d78
transforms and stuff
ecoskey 1202bca
fix bindings layout
ecoskey b4366b9
fix extraction
ecoskey ac1ee5b
Merge branch 'main' into proc_sky
ecoskey d03c2bb
more small progress
ecoskey 490cc5b
format toml
ecoskey ac4663d
Merge branch 'main' into proc_sky
ecoskey cfce3a5
fix readme examples
ecoskey 69bca4e
approaching correctness
ecoskey 06b5ba6
basic sun disk rendering
ecoskey cb3edf8
fix features list
ecoskey bbb1b45
Merge branch 'main' into proc_sky
ecoskey d27aa05
move to cubemap
ecoskey 0d3471e
WIP atmo transformations
ecoskey 40c5eaf
remove gunk
ecoskey e3ca9fe
fixes
ecoskey febb5b0
lots of progress somehow
ecoskey b30782a
Update multiscattering_lut.wgsl
ecoskey bed80b9
revert sky_view_lut behavior
ecoskey f27a0fd
fix transforms
ecoskey 448cd2a
fix sky_view_lut radius
ecoskey 7d51144
multiscattering and sampling
ecoskey 6cb9c59
fix multiscattering
ecoskey 41b801f
first cleanup/docs pass
ecoskey 301c880
docs pass 2
ecoskey 895de1a
remove old code
ecoskey e85809b
more docs
ecoskey 901ab54
fix
ecoskey 62ab0a5
comment
ecoskey 8bdc1c4
Add MSAA support
JMS55 f1fd5dc
Fix
JMS55 d39d742
Fix import
JMS55 f553018
Merge pull request #2 from JMS55/depth-proc-sky
ecoskey 31d88b0
specialize pipelines
ecoskey 6b3e016
partial multiscattering fix
ecoskey 4322495
small docs changes
ecoskey 050e29f
why does this fix things
ecoskey ebf5363
minor docs
ecoskey 4c470c0
density scaling
ecoskey 5dda6aa
fix transmittance LUT
ecoskey d6f4fb2
fix horizon
ecoskey fbaccc9
blargh
64082da
fast math
f1c2fe1
fast math 2
7a11933
back to 2d sky-view
74ddce0
cleanup
b16b9cb
done????
9aa5b65
fix lat-long parametrization
e92d705
cleanup
649a2a4
cleanup
e704dcd
Merge branch 'main' into proc_sky
6bd299d
Merge branch 'main' into proc_sky
ff2c5ac
fix imports
43923dd
fix typos
dc39a89
fix ci
615dd5e
fix imports
7bd44dd
fmt
20745ec
taplo
d634e2d
cargo features
890a840
Update fast_math.wgsl
e05a8c8
fix meshlet mesh ref
ad5852c
Merge branch 'main' into proc_sky
998d19a
fix examples
21a2db7
fix formatting
a6da721
add note
ecoskey ae8e4e6
minor math fixes
ecoskey 646c5b3
minor math fixes
ecoskey d57759d
fix conflicts
ecoskey 941a8a5
Analyitical integration method and fix multiple scattering calculation
mate-h 9f59275
Merge pull request #3 from mate-h/proc_sky
ecoskey 9a8d701
small cleanup pass
ecoskey e9891c3
Merge branch 'bevyengine:main' into proc_sky
ecoskey 2634eda
fix lints
ecoskey bd56cf3
fix CI
ecoskey 406196a
use white light for sun
ecoskey 7cae04b
bloom and sun disks
ecoskey af7fda3
typos and moon
ecoskey File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
#import bevy_pbr::{ | ||
mesh_view_types::{Lights, DirectionalLight}, | ||
atmosphere::{ | ||
types::{Atmosphere, AtmosphereSettings}, | ||
bindings::{atmosphere, settings, view, lights, aerial_view_lut_out}, | ||
functions::{ | ||
sample_transmittance_lut, sample_atmosphere, rayleigh, henyey_greenstein, | ||
sample_multiscattering_lut, AtmosphereSample, sample_local_inscattering, | ||
get_local_r, get_local_up, view_radius, uv_to_ndc, position_ndc_to_world, depth_ndc_to_view_z, | ||
max_atmosphere_distance, uv_to_ray_direction | ||
}, | ||
} | ||
} | ||
|
||
|
||
@group(0) @binding(13) var aerial_view_lut_out: texture_storage_3d<rgba16float, write>; | ||
|
||
@compute | ||
@workgroup_size(16, 16, 1) //TODO: this approach makes it so closer slices get fewer samples. But we also expect those to have less scattering. So win/win? | ||
fn main(@builtin(global_invocation_id) idx: vec3<u32>) { | ||
if any(idx.xy > settings.aerial_view_lut_size.xy) { return; } | ||
|
||
let uv = (vec2<f32>(idx.xy) + 0.5) / vec2<f32>(settings.aerial_view_lut_size.xy); | ||
let ray_dir = uv_to_ray_direction(uv); | ||
let r = view_radius(); | ||
let mu = ray_dir.y; | ||
let t_max = max_atmosphere_distance(r, mu); | ||
|
||
var prev_t = 0.0; | ||
var total_inscattering = vec3(0.0); | ||
var optical_depth = vec3(0.0); | ||
var throughput = vec3(1.0); | ||
|
||
// The aerial view LUT is in NDC space, so it uses bevy's reverse z convention. Since | ||
// we write multiple slices from each thread, we need to iterate in order near->far, which | ||
// is why the indices are reversed. | ||
for (var slice_i: i32 = i32(settings.aerial_view_lut_size.z - 1); slice_i >= 0; slice_i--) { | ||
var sum_transmittance = 0.0; | ||
for (var step_i: i32 = i32(settings.aerial_view_lut_samples - 1); step_i >= 0; step_i--) { | ||
let sample_depth = depth_at_sample(slice_i, step_i); | ||
//view_dir.w is the cosine of the angle between the view vector and the camera forward vector, used to correct the step length. | ||
let t_i = -depth_ndc_to_view_z(sample_depth) / ray_dir.w * settings.scene_units_to_km; | ||
let dt = (t_i - prev_t); | ||
prev_t = t_i; | ||
|
||
let local_r = get_local_r(r, mu, t_i); | ||
let local_up = get_local_up(r, t_i, ray_dir.xyz); | ||
|
||
let local_atmosphere = sample_atmosphere(local_r); | ||
let sample_optical_depth = local_atmosphere.extinction * dt; | ||
let sample_transmittance = exp(-sample_optical_depth); | ||
optical_depth += sample_optical_depth; | ||
|
||
// use beer's law to get transmittance from optical density | ||
let transmittance_to_sample = exp(-optical_depth); | ||
|
||
// evaluate one segment of the integral | ||
var inscattering = sample_local_inscattering(local_atmosphere, ray_dir.xyz, local_r, local_up); | ||
|
||
// Analytical integration of the single scattering term in the radiance transfer equation | ||
let s_int = (inscattering - inscattering * sample_transmittance) / local_atmosphere.extinction; | ||
total_inscattering += throughput * s_int; | ||
|
||
throughput *= sample_transmittance; | ||
if all(throughput < vec3(0.001)) { | ||
break; | ||
} | ||
|
||
sum_transmittance += transmittance_to_sample.r + transmittance_to_sample.g + transmittance_to_sample.b; | ||
} | ||
//We only have one channel to store transmittance, so we store the mean | ||
let mean_transmittance = sum_transmittance / (f32(settings.aerial_view_lut_samples) * 3.0); | ||
textureStore(aerial_view_lut_out, vec3(vec2<i32>(idx.xy), slice_i), vec4(total_inscattering, mean_transmittance)); | ||
} | ||
} | ||
|
||
// linearly interpolates from 0..1 on the domain of slice_i, using step_i as a substep index | ||
fn depth_at_sample(slice_i: i32, step_i: i32) -> f32 { | ||
return (f32(slice_i) + ((f32(step_i) + 0.5) / f32(settings.aerial_view_lut_samples))) / f32(settings.aerial_view_lut_size.z); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#define_import_path bevy_pbr::atmosphere::bindings | ||
|
||
#import bevy_render::view::View; | ||
|
||
#import bevy_pbr::{ | ||
mesh_view_types::Lights, | ||
atmosphere::types::{Atmosphere, AtmosphereSettings, AtmosphereTransforms} | ||
} | ||
|
||
@group(0) @binding(0) var<uniform> atmosphere: Atmosphere; | ||
@group(0) @binding(1) var<uniform> settings: AtmosphereSettings; | ||
@group(0) @binding(2) var<uniform> atmosphere_transforms: AtmosphereTransforms; | ||
@group(0) @binding(3) var<uniform> view: View; | ||
@group(0) @binding(4) var<uniform> lights: Lights; | ||
@group(0) @binding(5) var transmittance_lut: texture_2d<f32>; | ||
@group(0) @binding(6) var transmittance_lut_sampler: sampler; | ||
@group(0) @binding(7) var multiscattering_lut: texture_2d<f32>; | ||
@group(0) @binding(8) var multiscattering_lut_sampler: sampler; | ||
@group(0) @binding(9) var sky_view_lut: texture_2d<f32>; | ||
@group(0) @binding(10) var sky_view_lut_sampler: sampler; | ||
@group(0) @binding(11) var aerial_view_lut: texture_3d<f32>; | ||
@group(0) @binding(12) var aerial_view_lut_sampler: sampler; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
// Copyright (c) 2017 Eric Bruneton | ||
// All rights reserved. | ||
// | ||
// Redistribution and use in source and binary forms, with or without | ||
// modification, are permitted provided that the following conditions | ||
// are met: | ||
// 1. Redistributions of source code must retain the above copyright | ||
// notice, this list of conditions and the following disclaimer. | ||
// 2. Redistributions in binary form must reproduce the above copyright | ||
// notice, this list of conditions and the following disclaimer in the | ||
// documentation and/or other materials provided with the distribution. | ||
// 3. Neither the name of the copyright holders nor the names of its | ||
// contributors may be used to endorse or promote products derived from | ||
// this software without specific prior written permission. | ||
// | ||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||
// THE POSSIBILITY OF SUCH DAMAGE. | ||
// | ||
// Precomputed Atmospheric Scattering | ||
// Copyright (c) 2008 INRIA | ||
// All rights reserved. | ||
// | ||
// Redistribution and use in source and binary forms, with or without | ||
// modification, are permitted provided that the following conditions | ||
// are met: | ||
// 1. Redistributions of source code must retain the above copyright | ||
// notice, this list of conditions and the following disclaimer. | ||
// 2. Redistributions in binary form must reproduce the above copyright | ||
// notice, this list of conditions and the following disclaimer in the | ||
// documentation and/or other materials provided with the distribution. | ||
// 3. Neither the name of the copyright holders nor the names of its | ||
// contributors may be used to endorse or promote products derived from | ||
// this software without specific prior written permission. | ||
// | ||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||
// THE POSSIBILITY OF SUCH DAMAGE. | ||
|
||
#define_import_path bevy_pbr::atmosphere::bruneton_functions | ||
|
||
#import bevy_pbr::atmosphere::{ | ||
types::Atmosphere, | ||
bindings::atmosphere, | ||
} | ||
|
||
// Mapping from view height (r) and zenith cos angle (mu) to UV coordinates in the transmittance LUT | ||
// Assuming r between ground and top atmosphere boundary, and mu= cos(zenith_angle) | ||
// Chosen to increase precision near the ground and to work around a discontinuity at the horizon | ||
// See Bruneton and Neyret 2008, "Precomputed Atmospheric Scattering" section 4 | ||
fn transmittance_lut_r_mu_to_uv(r: f32, mu: f32) -> vec2<f32> { | ||
// Distance along a horizontal ray from the ground to the top atmosphere boundary | ||
let H = sqrt(atmosphere.top_radius * atmosphere.top_radius - atmosphere.bottom_radius * atmosphere.bottom_radius); | ||
|
||
// Distance from a point at height r to the horizon | ||
// ignore the case where r <= atmosphere.bottom_radius | ||
let rho = sqrt(max(r * r - atmosphere.bottom_radius * atmosphere.bottom_radius, 0.0)); | ||
|
||
// Distance from a point at height r to the top atmosphere boundary at zenith angle mu | ||
let d = distance_to_top_atmosphere_boundary(r, mu); | ||
|
||
// Minimum and maximum distance to the top atmosphere boundary from a point at height r | ||
let d_min = atmosphere.top_radius - r; // length of the ray straight up to the top atmosphere boundary | ||
let d_max = rho + H; // length of the ray to the top atmosphere boundary and grazing the horizon | ||
|
||
let u = (d - d_min) / (d_max - d_min); | ||
let v = rho / H; | ||
return vec2<f32>(u, v); | ||
} | ||
|
||
// Inverse of the mapping above, mapping from UV coordinates in the transmittance LUT to view height (r) and zenith cos angle (mu) | ||
fn transmittance_lut_uv_to_r_mu(uv: vec2<f32>) -> vec2<f32> { | ||
// Distance to top atmosphere boundary for a horizontal ray at ground level | ||
let H = sqrt(atmosphere.top_radius * atmosphere.top_radius - atmosphere.bottom_radius * atmosphere.bottom_radius); | ||
|
||
// Distance to the horizon, from which we can compute r: | ||
let rho = H * uv.y; | ||
let r = sqrt(rho * rho + atmosphere.bottom_radius * atmosphere.bottom_radius); | ||
|
||
// Distance to the top atmosphere boundary for the ray (r,mu), and its minimum | ||
// and maximum values over all mu- obtained for (r,1) and (r,mu_horizon) - | ||
// from which we can recover mu: | ||
let d_min = atmosphere.top_radius - r; | ||
let d_max = rho + H; | ||
let d = d_min + uv.x * (d_max - d_min); | ||
|
||
var mu: f32; | ||
if d == 0.0 { | ||
mu = 1.0; | ||
} else { | ||
mu = (H * H - rho * rho - d * d) / (2.0 * r * d); | ||
} | ||
|
||
mu = clamp(mu, -1.0, 1.0); | ||
|
||
return vec2<f32>(r, mu); | ||
} | ||
|
||
/// Simplified ray-sphere intersection | ||
/// where: | ||
/// Ray origin, o = [0,0,r] with r <= atmosphere.top_radius | ||
/// mu is the cosine of spherical coordinate theta (-1.0 <= mu <= 1.0) | ||
/// so ray direction in spherical coordinates is [1,acos(mu),0] which needs to be converted to cartesian | ||
/// Direction of ray, u = [0,sqrt(1-mu*mu),mu] | ||
/// Center of sphere, c = [0,0,0] | ||
/// Radius of sphere, r = atmosphere.top_radius | ||
/// This function solves the quadratic equation for line-sphere intersection simplified under these assumptions | ||
fn distance_to_top_atmosphere_boundary(r: f32, mu: f32) -> f32 { | ||
// ignore the case where r > atmosphere.top_radius | ||
let positive_discriminant = max(r * r * (mu * mu - 1.0) + atmosphere.top_radius * atmosphere.top_radius, 0.0); | ||
return max(-r * mu + sqrt(positive_discriminant), 0.0); | ||
} | ||
|
||
/// Simplified ray-sphere intersection | ||
/// as above for intersections with the ground | ||
fn distance_to_bottom_atmosphere_boundary(r: f32, mu: f32) -> f32 { | ||
let positive_discriminant = max(r * r * (mu * mu - 1.0) + atmosphere.bottom_radius * atmosphere.bottom_radius, 0.0); | ||
return max(-r * mu - sqrt(positive_discriminant), 0.0); | ||
} | ||
|
||
fn ray_intersects_ground(r: f32, mu: f32) -> bool { | ||
return mu < 0.0 && r * r * (mu * mu - 1.0) + atmosphere.bottom_radius * atmosphere.bottom_radius >= 0.0; | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 think this is supposed to be alphabetical