JonahPlusPlus / bevy_atmosphere

A procedural sky plugin for bevy
Apache License 2.0
264 stars 19 forks source link

EnvironmentMapLight #55

Open tbillington opened 1 year ago

tbillington commented 1 year ago

Bevy now supports EnvironmentMapLight as of 0.11.

I don't know how possible it is, but being able to derive the environment map from from the bevy_atmosphere skybox would be handy.

mattdm commented 1 year ago

That would tend to make ambient light the color of the sky — strongly blue, usually. Most of the time, the environmental light should be pure white, right?

It would be kind of cool to have bevy_atmosphere keep track of sun position and provide a DirectionalLight that syncs with the sky. There are two sun-position libraries on crates.io that I see, both kind of awkward, unfortunately — they are ports of a javascript library and have weird conventions like "time in milliseconds".) Plus, they've got extra steps, because there's no real reason to deal with timezones for this purpose — just assume times are UTC and the longitude is 0. Also, like the Nishita model here, the constants that represent earth should be configurable for alien environments.

peterellisjones commented 7 months ago

I'm using this for sun position, adapted from https://stackoverflow.com/questions/8708048/position-of-the-sun-given-time-of-day-latitude-and-longitude and using it to both set the sun position in the model and its inverse for a directional light for shadows

fn sun_direction(time_of_day: f32, latitude: f32, time_of_year: f32) -> Vec3 {
    // Convert time of day from [0, 1] to [-π, π]
    let solar_time_rads = 2.0 * PI * (time_of_day - 0.5);

    // Convert time of year from [0, 1] to [-0.41, 0.41]
    // offset by 0.25 so declination is 0 at equinoxes
    let declination_rads = (2.0 * PI * (time_of_year - 0.25)).sin() * 23.45f32.to_radians();

    // Convert latitude from [0, 1] to [-π/2, π/2]
    let latitude_rads = PI * (latitude - 0.5);

    // equations adapted from https://stackoverflow.com/questions/8708048/position-of-the-sun-given-time-of-day-latitude-and-longitude
    let zenith_rads = (latitude_rads.sin() * declination_rads.sin()
        + latitude_rads.cos() * declination_rads.cos() * solar_time_rads.cos())
    .acos();

    let mut azimuth_rads = ((latitude_rads.sin() * zenith_rads.cos() - declination_rads.sin())
        / (latitude_rads.cos() * zenith_rads.sin()))
    .acos();

    let elevation_rads = (declination_rads.sin() * latitude_rads.sin()
        + declination_rads.cos() * latitude_rads.cos() * solar_time_rads.cos())
    .asin();

    if solar_time_rads > 0.0f32 {
        azimuth_rads = azimuth_rads + PI;
    } else {
        azimuth_rads = 3.0 * PI - azimuth_rads;
    }

    let x = azimuth_rads.sin() * elevation_rads.cos();
    let y = elevation_rads.sin();
    let z = azimuth_rads.cos() * elevation_rads.cos();

    Vec3::new(x, y, z)
}