2020-07-28 08:55:48 +00:00
|
|
|
use common::{
|
|
|
|
terrain::{
|
|
|
|
map::{MapConfig, MapDebug, MapSample},
|
|
|
|
uniform_idx_as_vec2, vec2_as_uniform_idx, TerrainChunkSize,
|
|
|
|
},
|
|
|
|
vol::RectVolSize,
|
|
|
|
};
|
2020-02-21 13:52:17 +00:00
|
|
|
use rayon::prelude::*;
|
2020-01-20 20:17:55 +00:00
|
|
|
use std::{f64, io::Write, path::PathBuf, time::SystemTime};
|
2020-06-21 14:26:06 +00:00
|
|
|
use tracing::warn;
|
|
|
|
use tracing_subscriber;
|
2019-10-16 11:39:41 +00:00
|
|
|
use vek::*;
|
|
|
|
use veloren_world::{
|
2020-07-28 08:55:48 +00:00
|
|
|
sim::{self, get_horizon_map, sample_pos, sample_wpos, WorldOpts},
|
2020-02-21 13:52:17 +00:00
|
|
|
util::Sampler,
|
2020-07-28 08:55:48 +00:00
|
|
|
ColumnSample, World, CONFIG,
|
2019-10-16 11:39:41 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
const W: usize = 1024;
|
|
|
|
const H: usize = 1024;
|
|
|
|
|
2020-06-10 19:47:36 +00:00
|
|
|
#[allow(clippy::needless_update)] // TODO: Pending review in #587
|
|
|
|
#[allow(clippy::unused_io_amount)] // TODO: Pending review in #587
|
2019-10-16 11:39:41 +00:00
|
|
|
fn main() {
|
2020-06-21 14:26:06 +00:00
|
|
|
tracing_subscriber::fmt::init();
|
2019-11-11 17:14:58 +00:00
|
|
|
|
2020-02-01 20:39:39 +00:00
|
|
|
// To load a map file of your choice, replace map_file with the name of your map
|
|
|
|
// (stored locally in the map directory of your Veloren root), and swap the
|
|
|
|
// sim::FileOpts::Save line below for the sim::FileOpts::Load one.
|
2019-12-11 09:14:50 +00:00
|
|
|
let map_file =
|
|
|
|
// "map_1575990726223.bin";
|
|
|
|
// "map_1575987666972.bin";
|
2020-02-21 13:52:17 +00:00
|
|
|
// "map_1576046079066.bin";
|
2020-07-28 10:11:40 +00:00
|
|
|
// "maps/071090_2x.bin";
|
2020-02-21 13:52:17 +00:00
|
|
|
"map_1579539133272.bin";
|
2019-12-11 09:14:50 +00:00
|
|
|
let mut _map_file = PathBuf::from("./maps");
|
|
|
|
_map_file.push(map_file);
|
|
|
|
|
2020-02-01 20:39:39 +00:00
|
|
|
let world = World::generate(5284, WorldOpts {
|
|
|
|
seed_elements: false,
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
world_file: sim::FileOpts::LoadAsset(veloren_world::sim::DEFAULT_WORLD_MAP.into()),
|
|
|
|
// world_file: sim::FileOpts::Load(_map_file),
|
2020-02-21 13:52:17 +00:00
|
|
|
// world_file: sim::FileOpts::Save,
|
2020-02-01 20:39:39 +00:00
|
|
|
..WorldOpts::default()
|
|
|
|
});
|
2020-07-15 23:57:39 +00:00
|
|
|
tracing::info!("Sampling data...");
|
2020-02-21 13:52:17 +00:00
|
|
|
let sampler = world.sim();
|
2020-07-28 08:55:48 +00:00
|
|
|
let map_size_lg = sampler.map_size_lg();
|
2020-02-21 13:52:17 +00:00
|
|
|
|
|
|
|
let samples_data = {
|
|
|
|
let column_sample = world.sample_columns();
|
2020-07-28 08:55:48 +00:00
|
|
|
(0..map_size_lg.chunks_len())
|
2020-02-21 13:52:17 +00:00
|
|
|
.into_par_iter()
|
|
|
|
.map(|posi| {
|
2020-08-13 03:52:56 +00:00
|
|
|
column_sample.get((
|
2020-07-28 08:55:48 +00:00
|
|
|
uniform_idx_as_vec2(map_size_lg, posi)
|
|
|
|
* TerrainChunkSize::RECT_SIZE.map(|e| e as i32),
|
2020-08-13 03:52:56 +00:00
|
|
|
world.index(),
|
|
|
|
))
|
2020-02-21 13:52:17 +00:00
|
|
|
})
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
.into_boxed_slice()
|
|
|
|
};
|
2020-07-28 08:55:48 +00:00
|
|
|
let refresh_map_samples = |config: &MapConfig, samples: Option<&[Option<ColumnSample>]>| {
|
|
|
|
(0..map_size_lg.chunks_len())
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
.into_par_iter()
|
2020-07-28 08:55:48 +00:00
|
|
|
.map(|posi| {
|
|
|
|
sample_pos(
|
|
|
|
config,
|
|
|
|
sampler,
|
2020-08-13 03:52:56 +00:00
|
|
|
world.index(),
|
2020-07-28 08:55:48 +00:00
|
|
|
samples,
|
|
|
|
uniform_idx_as_vec2(map_size_lg, posi),
|
|
|
|
)
|
|
|
|
})
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
.collect::<Vec<_>>()
|
|
|
|
.into_boxed_slice()
|
|
|
|
};
|
|
|
|
let get_map_sample = |map_samples: &[MapSample], pos: Vec2<i32>| {
|
|
|
|
if pos.reduce_partial_min() >= 0
|
2020-07-28 08:55:48 +00:00
|
|
|
&& pos.x < map_size_lg.chunks().x as i32
|
|
|
|
&& pos.y < map_size_lg.chunks().y as i32
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
{
|
2020-07-28 08:55:48 +00:00
|
|
|
map_samples[vec2_as_uniform_idx(map_size_lg, pos)].clone()
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
} else {
|
|
|
|
MapSample {
|
|
|
|
alt: 0.0,
|
|
|
|
rgb: Rgb::new(0, 0, 0),
|
|
|
|
connections: None,
|
|
|
|
downhill_wpos: (pos + 1) * TerrainChunkSize::RECT_SIZE.map(|e| e as i32),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2020-02-21 13:52:17 +00:00
|
|
|
|
2020-07-28 08:55:48 +00:00
|
|
|
let refresh_horizons = |is_basement, is_water| {
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
get_horizon_map(
|
2020-07-28 08:55:48 +00:00
|
|
|
map_size_lg,
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
Aabr {
|
|
|
|
min: Vec2::zero(),
|
2020-07-28 08:55:48 +00:00
|
|
|
max: map_size_lg.chunks().map(|e| e as i32),
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
},
|
2020-07-28 08:55:48 +00:00
|
|
|
CONFIG.sea_level,
|
|
|
|
CONFIG.sea_level + sampler.max_height,
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
|posi| {
|
2020-07-28 08:55:48 +00:00
|
|
|
let sample = sampler.get(uniform_idx_as_vec2(map_size_lg, posi)).unwrap();
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
if is_basement {
|
2020-07-28 08:55:48 +00:00
|
|
|
sample.alt
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
} else {
|
2020-07-28 08:55:48 +00:00
|
|
|
sample.basement
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
}
|
|
|
|
.max(if is_water {
|
2020-07-28 08:55:48 +00:00
|
|
|
sample.water_alt
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
} else {
|
2020-07-28 08:55:48 +00:00
|
|
|
-f32::INFINITY
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
})
|
|
|
|
},
|
|
|
|
|a| a,
|
|
|
|
|h| h,
|
|
|
|
/* |[al, ar]| [al, ar],
|
|
|
|
* |[hl, hr]| [hl, hr], */
|
|
|
|
)
|
|
|
|
.ok()
|
2020-02-21 13:52:17 +00:00
|
|
|
};
|
2019-10-16 11:39:41 +00:00
|
|
|
|
|
|
|
let mut win =
|
|
|
|
minifb::Window::new("World Viewer", W, H, minifb::WindowOptions::default()).unwrap();
|
|
|
|
|
2019-12-03 01:07:44 +00:00
|
|
|
let mut focus = Vec3::new(0.0, 0.0, CONFIG.sea_level as f64);
|
2020-02-01 20:39:39 +00:00
|
|
|
// Altitude is divided by gain and clamped to [0, 1]; thus, decreasing gain
|
|
|
|
// makes smaller differences in altitude appear larger.
|
2020-02-21 13:52:17 +00:00
|
|
|
let mut gain = /*CONFIG.mountain_scale*/sampler.max_height;
|
2019-12-03 01:07:44 +00:00
|
|
|
// The Z component during normal calculations is multiplied by gain; thus,
|
2020-07-28 08:55:48 +00:00
|
|
|
let mut fov = 1.0;
|
Fix map image artifacts and remove unneeded allocations.
Specifically, we address three concerns (the image stretching during
rotation, artifacts around the image due to clamping to the nearest
border color when the image is drawn to a larger space than the image
itself takes up, and potential artifacts around a rotated image which
accidentally ended up in an atlas and didn't have enough extra space to
guarantee the rotation would work).
The first concern was addressed by fixing the dimensions of the map
images drawn from the UI (so that we always use a square source
rectangle, rather than a rectangular one according to the dimensions of
the map). We also fixed the way rotation was done in the fragment
shader for north-facing sources to make it properly handle aspect ratio
(this was already done for north-facing targets). Together, these fix
rendering issues peculiar to rectangular maps.
The second and third concerns were jointly addressed by adding an
optional border color to every 2D image drawn by the UI. This turns
out not to waste extra space even though we hold a full f32 color
(to avoid an extra dependency on gfx's PackedColor), since voxel
images already take up more space than Optiion<[f32; 4]> requires.
This is then implemented automatically using the "border color"
wrapping method in the attached sampler.
Since this is implemented in graphics hardware, it only works (at
least naively) if the actual image bounds match the texture bounds.
Therefore, we altered the way the graphics cache stores images
with a border color to guarantee that they are always in their own
texture, whose size exactly matches their extent. Since the easiest
currently exposed way to set a border color is to do so for an
immutable texture, we went a bit further and added a new "immutable"
texture storage type used for these cases; currently, it is always
and automatically used only when there is a specified border color,
but in theory there's no reason we couldn't provide immutable-only
images that use the default wrapping mdoe (though clamp to border
is admittedly not a great default).
To fix the maps case specifically, we set the border color to a
translucent version of the ocean border color. This may need
tweaking going forward, which shouldn't be hard.
As part of this process, we had to modify graphics replacement to
make sure immutable images are *removed* when invalidated, rather
than just having a validity flag unset (this is normally done by
the UI to try to reuse allocations in place if images are updated
in benign ways, since the texture atlases used for Ui do not
support deallocation; currently this is only used for item images,
so there should be no overlap with immutable image replacement,
so this was purely precautionary).
Since we were already touching the relevant code, we also updated
the image dependency to a newer version that provides more ways
to avoid allocations, and made a few other changes that should
hopefully eliminate redundant most of the intermediate buffer
allocations we were performing for what should be zero-cost
conversions. This may slightly improve performance in some
cases.
2020-07-29 16:29:52 +00:00
|
|
|
let mut scale =
|
|
|
|
(map_size_lg.chunks().x as f64 / W as f64).max(map_size_lg.chunks().y as f64 / H as f64);
|
2019-10-16 11:39:41 +00:00
|
|
|
|
2020-02-01 20:39:39 +00:00
|
|
|
// Right-handed coordinate system: light is going left, down, and "backwards"
|
|
|
|
// (i.e. on the map, where we translate the y coordinate on the world map to
|
|
|
|
// z in the coordinate system, the light comes from -y on the map and points
|
|
|
|
// towards +y on the map). In a right handed coordinate system, the
|
|
|
|
// "camera" points towards -z, so positive z is backwards "into" the camera.
|
2019-12-03 01:07:44 +00:00
|
|
|
//
|
2020-02-01 20:39:39 +00:00
|
|
|
// "In world space the x-axis will be pointing east, the y-axis up and the
|
|
|
|
// z-axis will be pointing south"
|
2020-02-21 13:52:17 +00:00
|
|
|
let mut light_direction = Vec3::new(-/*0.8*/1.3, -1.0, 0.3);
|
2019-11-11 17:14:58 +00:00
|
|
|
|
2019-11-19 18:34:52 +00:00
|
|
|
let mut is_basement = false;
|
2019-12-03 01:07:44 +00:00
|
|
|
let mut is_water = true;
|
2019-11-20 03:39:17 +00:00
|
|
|
let mut is_shaded = true;
|
|
|
|
let mut is_temperature = true;
|
|
|
|
let mut is_humidity = true;
|
2019-11-19 18:34:52 +00:00
|
|
|
|
2020-07-28 08:55:48 +00:00
|
|
|
let mut horizons = refresh_horizons(is_basement, is_water);
|
2020-02-21 13:52:17 +00:00
|
|
|
let mut samples = None;
|
|
|
|
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
let mut samples_changed = true;
|
|
|
|
let mut map_samples: Box<[_]> = Box::new([]);
|
2019-10-16 11:39:41 +00:00
|
|
|
while win.is_open() {
|
2020-01-13 07:10:38 +00:00
|
|
|
let config = MapConfig {
|
2020-07-28 08:55:48 +00:00
|
|
|
map_size_lg,
|
2020-01-13 07:10:38 +00:00
|
|
|
dimensions: Vec2::new(W, H),
|
|
|
|
focus,
|
|
|
|
gain,
|
2020-07-28 08:55:48 +00:00
|
|
|
fov,
|
2020-01-13 07:10:38 +00:00
|
|
|
scale,
|
|
|
|
light_direction,
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
horizons: horizons.as_ref(), /* .map(|(a, b)| (&**a, &**b)) */
|
2020-01-13 07:10:38 +00:00
|
|
|
|
|
|
|
is_basement,
|
|
|
|
is_water,
|
|
|
|
is_shaded,
|
|
|
|
is_temperature,
|
|
|
|
is_humidity,
|
|
|
|
is_debug: true,
|
|
|
|
};
|
2019-10-16 11:39:41 +00:00
|
|
|
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
if samples_changed {
|
2020-07-28 08:55:48 +00:00
|
|
|
map_samples = refresh_map_samples(&config, samples);
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
};
|
|
|
|
|
2020-01-13 07:10:38 +00:00
|
|
|
let mut buf = vec![0; W * H];
|
|
|
|
let MapDebug {
|
|
|
|
rivers,
|
|
|
|
lakes,
|
|
|
|
oceans,
|
|
|
|
quads,
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
} = config.generate(
|
|
|
|
|pos| get_map_sample(&map_samples, pos),
|
2020-07-28 08:55:48 +00:00
|
|
|
|pos| sample_wpos(&config, sampler, pos),
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
|pos, (r, g, b, a)| {
|
|
|
|
let i = pos.x;
|
|
|
|
let j = pos.y;
|
|
|
|
buf[j * W + i] = u32::from_le_bytes([b, g, r, a]);
|
|
|
|
},
|
|
|
|
);
|
2019-10-16 11:39:41 +00:00
|
|
|
|
2020-01-20 20:17:55 +00:00
|
|
|
if win.is_key_down(minifb::Key::F4) {
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
// Feedback is important since on large maps it can be hard to tell if the
|
|
|
|
// keypress registered or not.
|
|
|
|
println!("Taking screenshot...");
|
2020-01-20 20:17:55 +00:00
|
|
|
if let Some(len) = (W * H)
|
|
|
|
.checked_mul(scale as usize)
|
|
|
|
.and_then(|acc| acc.checked_mul(scale as usize))
|
|
|
|
{
|
2020-01-22 09:41:10 +00:00
|
|
|
let x = (W as f64 * scale) as usize;
|
|
|
|
let y = (H as f64 * scale) as usize;
|
2020-07-28 08:55:48 +00:00
|
|
|
let config = MapConfig {
|
2020-01-20 20:17:55 +00:00
|
|
|
dimensions: Vec2::new(x, y),
|
|
|
|
scale: 1.0,
|
|
|
|
..config
|
|
|
|
};
|
|
|
|
let mut buf = vec![0u8; 4 * len];
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
config.generate(
|
|
|
|
|pos| get_map_sample(&map_samples, pos),
|
2020-07-28 08:55:48 +00:00
|
|
|
|pos| sample_wpos(&config, sampler, pos),
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
|pos, (r, g, b, a)| {
|
|
|
|
let i = pos.x;
|
|
|
|
let j = pos.y;
|
|
|
|
(&mut buf[(j * x + i) * 4..]).write(&[r, g, b, a]).unwrap();
|
|
|
|
},
|
|
|
|
);
|
2020-01-22 13:35:13 +00:00
|
|
|
// TODO: Justify fits in u32.
|
2020-01-20 20:17:55 +00:00
|
|
|
let world_map = image::RgbaImage::from_raw(x as u32, y as u32, buf)
|
|
|
|
.expect("Image dimensions must be valid");
|
|
|
|
let mut path = PathBuf::from("./screenshots");
|
|
|
|
if !path.exists() {
|
2020-06-21 21:47:49 +00:00
|
|
|
if let Err(e) = std::fs::create_dir(&path) {
|
|
|
|
warn!(?e, ?path, "Couldn't create folder for screenshot");
|
2020-01-20 20:17:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
path.push(format!(
|
|
|
|
"worldmap_{}.png",
|
|
|
|
SystemTime::now()
|
|
|
|
.duration_since(SystemTime::UNIX_EPOCH)
|
|
|
|
.map(|d| d.as_millis())
|
|
|
|
.unwrap_or(0)
|
|
|
|
));
|
2020-06-21 21:47:49 +00:00
|
|
|
if let Err(e) = world_map.save(&path) {
|
|
|
|
warn!(?e, ?path, "Couldn't save screenshot");
|
2020-01-20 20:17:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-03 01:07:44 +00:00
|
|
|
let spd = 32.0;
|
|
|
|
let lspd = 0.1;
|
2019-11-07 20:25:30 +00:00
|
|
|
if win.is_key_down(minifb::Key::P) {
|
2019-11-11 17:14:58 +00:00
|
|
|
println!(
|
|
|
|
"\
|
2020-02-01 20:39:39 +00:00
|
|
|
Gain / Shade gain: {:?} / {:?}\nScale / Focus: {:?} / {:?}\nLight: {:?}
|
|
|
|
Land(adjacent): (X = temp, Y = humidity): {:?}\nRivers: {:?}\nLakes: \
|
|
|
|
{:?}\nOceans: {:?}\nTotal water: {:?}\nTotal land(adjacent): {:?}",
|
2019-11-22 02:55:19 +00:00
|
|
|
gain,
|
2020-07-28 08:55:48 +00:00
|
|
|
fov,
|
2019-11-22 02:55:19 +00:00
|
|
|
scale,
|
2019-12-03 01:07:44 +00:00
|
|
|
focus,
|
|
|
|
light_direction,
|
2019-11-11 17:14:58 +00:00
|
|
|
quads,
|
|
|
|
rivers,
|
|
|
|
lakes,
|
|
|
|
oceans,
|
2019-11-07 20:25:30 +00:00
|
|
|
rivers + lakes + oceans,
|
2019-11-11 17:14:58 +00:00
|
|
|
quads.iter().map(|x| x.iter().sum::<u32>()).sum::<u32>()
|
2019-11-07 20:25:30 +00:00
|
|
|
);
|
|
|
|
}
|
2019-11-11 17:14:58 +00:00
|
|
|
if win.get_mouse_down(minifb::MouseButton::Left) {
|
|
|
|
if let Some((mx, my)) = win.get_mouse_pos(minifb::MouseMode::Clamp) {
|
2020-04-17 23:29:01 +00:00
|
|
|
let chunk_pos = (Vec2::<f64>::from(focus)
|
|
|
|
+ (Vec2::new(mx as f64, my as f64) * scale))
|
2020-01-13 07:10:38 +00:00
|
|
|
.map(|e| e as i32);
|
2020-03-27 23:06:23 +00:00
|
|
|
let block_pos = chunk_pos.map2(TerrainChunkSize::RECT_SIZE, |e, f| e * f as i32);
|
2019-11-11 17:14:58 +00:00
|
|
|
println!(
|
2020-04-17 23:29:01 +00:00
|
|
|
"Block: ({}, {}), Chunk: ({}, {})",
|
|
|
|
block_pos.x, block_pos.y, chunk_pos.x, chunk_pos.y
|
2019-11-11 17:14:58 +00:00
|
|
|
);
|
2020-03-27 23:06:23 +00:00
|
|
|
if let Some(chunk) = sampler.get(chunk_pos) {
|
|
|
|
//println!("Chunk info: {:#?}", chunk);
|
2020-03-28 18:16:19 +00:00
|
|
|
if let Some(id) = &chunk.place {
|
|
|
|
let place = world.civs().place(*id);
|
|
|
|
println!("Place {} info: {:#?}", id.id(), place);
|
|
|
|
|
2020-03-30 16:46:44 +00:00
|
|
|
if let Some(site) = world.civs().sites().find(|site| site.place == *id) {
|
|
|
|
println!("Site: {}", site);
|
|
|
|
}
|
2020-03-27 23:06:23 +00:00
|
|
|
}
|
|
|
|
}
|
2019-11-11 17:14:58 +00:00
|
|
|
}
|
|
|
|
}
|
2019-12-03 01:07:44 +00:00
|
|
|
let is_camera = win.is_key_down(minifb::Key::C);
|
2019-11-19 18:34:52 +00:00
|
|
|
if win.is_key_down(minifb::Key::B) {
|
|
|
|
is_basement ^= true;
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
samples_changed = true;
|
2020-07-28 08:55:48 +00:00
|
|
|
horizons = horizons.and_then(|_| refresh_horizons(is_basement, is_water));
|
2019-11-19 18:34:52 +00:00
|
|
|
}
|
2019-11-20 03:39:17 +00:00
|
|
|
if win.is_key_down(minifb::Key::H) {
|
|
|
|
is_humidity ^= true;
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
samples_changed = true;
|
2019-11-20 03:39:17 +00:00
|
|
|
}
|
|
|
|
if win.is_key_down(minifb::Key::T) {
|
|
|
|
is_temperature ^= true;
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
samples_changed = true;
|
2019-11-20 03:39:17 +00:00
|
|
|
}
|
2019-12-03 01:07:44 +00:00
|
|
|
if win.is_key_down(minifb::Key::O) {
|
|
|
|
is_water ^= true;
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
samples_changed = true;
|
2020-07-28 08:55:48 +00:00
|
|
|
horizons = horizons.and_then(|_| refresh_horizons(is_basement, is_water));
|
2019-12-03 01:07:44 +00:00
|
|
|
}
|
2019-11-20 03:39:17 +00:00
|
|
|
if win.is_key_down(minifb::Key::L) {
|
2020-02-21 13:52:17 +00:00
|
|
|
if is_camera {
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
// TODO: implement removing horizon mapping.
|
2020-04-02 01:17:49 +00:00
|
|
|
horizons = if horizons.is_some() {
|
|
|
|
None
|
|
|
|
} else {
|
2020-07-28 08:55:48 +00:00
|
|
|
refresh_horizons(is_basement, is_water)
|
2020-04-02 01:17:49 +00:00
|
|
|
};
|
|
|
|
samples_changed = true;
|
2020-02-21 13:52:17 +00:00
|
|
|
} else {
|
|
|
|
is_shaded ^= true;
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
samples_changed = true;
|
2020-02-21 13:52:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if win.is_key_down(minifb::Key::M) {
|
|
|
|
samples = samples.xor(Some(&*samples_data));
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
samples_changed = true;
|
2019-11-20 03:39:17 +00:00
|
|
|
}
|
2019-10-16 11:39:41 +00:00
|
|
|
if win.is_key_down(minifb::Key::W) {
|
2019-12-03 01:07:44 +00:00
|
|
|
if is_camera {
|
|
|
|
light_direction.z -= lspd;
|
|
|
|
} else {
|
|
|
|
focus.y -= spd * scale;
|
|
|
|
}
|
2019-10-16 11:39:41 +00:00
|
|
|
}
|
|
|
|
if win.is_key_down(minifb::Key::A) {
|
2019-12-03 01:07:44 +00:00
|
|
|
if is_camera {
|
|
|
|
light_direction.x -= lspd;
|
|
|
|
} else {
|
|
|
|
focus.x -= spd * scale;
|
|
|
|
}
|
2019-10-16 11:39:41 +00:00
|
|
|
}
|
|
|
|
if win.is_key_down(minifb::Key::S) {
|
2019-12-03 01:07:44 +00:00
|
|
|
if is_camera {
|
|
|
|
light_direction.z += lspd;
|
|
|
|
} else {
|
|
|
|
focus.y += spd * scale;
|
|
|
|
}
|
2019-10-16 11:39:41 +00:00
|
|
|
}
|
|
|
|
if win.is_key_down(minifb::Key::D) {
|
2019-12-03 01:07:44 +00:00
|
|
|
if is_camera {
|
|
|
|
light_direction.x += lspd;
|
|
|
|
} else {
|
|
|
|
focus.x += spd * scale;
|
|
|
|
}
|
2019-10-16 11:39:41 +00:00
|
|
|
}
|
|
|
|
if win.is_key_down(minifb::Key::Q) {
|
2019-12-03 01:07:44 +00:00
|
|
|
if is_camera {
|
2020-07-28 08:55:48 +00:00
|
|
|
if (fov * 2.0).is_normal() {
|
|
|
|
fov *= 2.0;
|
2019-12-03 01:07:44 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
gain += 64.0;
|
|
|
|
}
|
2019-10-16 11:39:41 +00:00
|
|
|
}
|
|
|
|
if win.is_key_down(minifb::Key::E) {
|
2019-12-03 01:07:44 +00:00
|
|
|
if is_camera {
|
2020-07-28 08:55:48 +00:00
|
|
|
if (fov / 2.0).is_normal() {
|
|
|
|
fov /= 2.0;
|
2019-12-03 01:07:44 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
gain = (gain - 64.0).max(64.0);
|
|
|
|
}
|
2019-10-16 11:39:41 +00:00
|
|
|
}
|
|
|
|
if win.is_key_down(minifb::Key::R) {
|
2019-12-03 01:07:44 +00:00
|
|
|
if is_camera {
|
|
|
|
focus.z += spd * scale;
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
samples_changed = true;
|
2019-12-03 01:07:44 +00:00
|
|
|
} else {
|
|
|
|
if (scale * 2.0).is_normal() {
|
|
|
|
scale *= 2.0;
|
|
|
|
}
|
|
|
|
}
|
2019-10-16 11:39:41 +00:00
|
|
|
}
|
|
|
|
if win.is_key_down(minifb::Key::F) {
|
2019-12-03 01:07:44 +00:00
|
|
|
if is_camera {
|
|
|
|
focus.z -= spd * scale;
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
samples_changed = true;
|
2019-12-03 01:07:44 +00:00
|
|
|
} else {
|
|
|
|
if (scale / 2.0).is_normal() {
|
|
|
|
scale /= 2.0;
|
|
|
|
}
|
|
|
|
}
|
2019-10-16 11:39:41 +00:00
|
|
|
}
|
|
|
|
|
Horizon mapping and "layered" map generation.
Horizon mapping is a method of shadow mapping specific to height maps.
It can handle any angle between 0 and 90 degrees from the ground, as
long as know the horizontal direction in advance, by remembering only a
single angle (the "horizon angle" of the shadow map). More is explained
in common/src/msg/server.rs. We also remember the approximate height of
the largest occluder, to try to be able to generate soft shadows and
create a vertical position where the shadows can't go higher.
Additionally, map generation has been reworked. Instead of computing
everything from explicit samples, we pass in sampling functions that
return exactly what the map generator needs. This allows us to cleanly
separate the way we sample things like altitudes and colors from the map
generation process. We exploit this to generate maps *partially* on the
server (with colors and rivers, but not shading). We can then send the
partially completed map to the client, which can combine it with shadow
information to generate the final map. This is useful for two reasons:
first, it makes sure the client can apply shadow information by itself,
and second, it lets us pass the unshaded map for use with level of
detail functionality.
For similar reasons, river generation is split
out into its own layer, but for now we opt to still generate rivers on
the server (since the river wire format is more complicated to compress
and may require some extra work to make sure we have enough precision to
draw rivers well enough for LoD).
Finally, the mostly ad-hoc lighting we were performing has been (mostly)
replaced with explicit Phong reflection shading (including specular
highlights). Regularizing this seems useful and helps clarify the
"meaning" of the various light intensities, and helps us keep a more
physically plausible basis. However, its interaction with soft shadows
is still imperfect, and it's not yet clear to me what we need to do to
turn this into something useful for LoD.
2020-04-02 00:46:36 +00:00
|
|
|
win.update_with_buffer_size(&buf, W, H).unwrap();
|
2019-10-16 11:39:41 +00:00
|
|
|
}
|
|
|
|
}
|