Higher detail LOD.

This commit is contained in:
Joshua Yanovski 2020-07-18 18:55:25 +02:00
parent add2cfae04
commit 2101113b46
22 changed files with 340 additions and 256 deletions

View File

@ -46,7 +46,7 @@ flat out uint f_pos_norm;
// out float f_light; // out float f_light;
// out vec3 light_pos[2]; // out vec3 light_pos[2];
const float EXTRA_NEG_Z = /*65536.0*/65536.1; const float EXTRA_NEG_Z = 65536.0/*65536.1*/;
void main() { void main() {
f_pos = vec3((uvec3(v_pos_norm) >> uvec3(0, 6, 12)) & uvec3(0x3Fu, 0x3Fu, 0x1FFFFu)) - vec3(0, 0, EXTRA_NEG_Z) + model_offs - focus_off.xyz; f_pos = vec3((uvec3(v_pos_norm) >> uvec3(0, 6, 12)) & uvec3(0x3Fu, 0x3Fu, 0x1FFFFu)) - vec3(0, 0, EXTRA_NEG_Z) + model_offs - focus_off.xyz;

View File

@ -68,4 +68,6 @@
/* /*
// When sets, shadow maps are used to cast shadows. // When sets, shadow maps are used to cast shadows.
#define HAS_SHADOW_MAPS #define HAS_SHADOW_MAPS
// When set, "full" LOD terrain informatino is available (e.g. terrain colors).
#define HAS_LOD_FULL_INFO
*/ */

View File

@ -2,7 +2,7 @@
#include <sky.glsl> #include <sky.glsl>
#include <srgb.glsl> #include <srgb.glsl>
uniform sampler2D t_map; uniform sampler2D t_alt;
uniform sampler2D t_horizon; uniform sampler2D t_horizon;
const float MIN_SHADOW = 0.33; const float MIN_SHADOW = 0.33;
@ -11,7 +11,7 @@ vec2 pos_to_uv(sampler2D sampler, vec2 pos) {
// Want: (pixel + 0.5) / W // Want: (pixel + 0.5) / W
vec2 texSize = textureSize(sampler, 0); vec2 texSize = textureSize(sampler, 0);
vec2 uv_pos = (focus_off.xy + pos + 16) / (32.0 * texSize); vec2 uv_pos = (focus_off.xy + pos + 16) / (32.0 * texSize);
return vec2(uv_pos.x, 1.0 - uv_pos.y); return vec2(uv_pos.x, /*1.0 - */uv_pos.y);
} }
vec2 pos_to_tex(vec2 pos) { vec2 pos_to_tex(vec2 pos) {
@ -35,6 +35,7 @@ vec4 cubic(float v) {
vec4 textureBicubic(sampler2D sampler, vec2 texCoords) { vec4 textureBicubic(sampler2D sampler, vec2 texCoords) {
vec2 texSize = textureSize(sampler, 0); vec2 texSize = textureSize(sampler, 0);
vec2 invTexSize = 1.0 / texSize; vec2 invTexSize = 1.0 / texSize;
/* texCoords.y = texSize.y - texCoords.y; */
texCoords = texCoords/* * texSize */ - 0.5; texCoords = texCoords/* * texSize */ - 0.5;
@ -52,8 +53,8 @@ vec4 textureBicubic(sampler2D sampler, vec2 texCoords) {
vec4 offset = c + vec4 (xcubic.yw, ycubic.yw) / s; vec4 offset = c + vec4 (xcubic.yw, ycubic.yw) / s;
offset *= invTexSize.xxyy; offset *= invTexSize.xxyy;
// Correct for map rotaton. /* // Correct for map rotaton.
offset.zw = 1.0 - offset.zw; offset.zw = 1.0 - offset.zw; */
vec4 sample0 = texture(sampler, offset.xz); vec4 sample0 = texture(sampler, offset.xz);
vec4 sample1 = texture(sampler, offset.yz); vec4 sample1 = texture(sampler, offset.yz);
@ -73,7 +74,7 @@ vec4 textureBicubic(sampler2D sampler, vec2 texCoords) {
} }
float alt_at(vec2 pos) { float alt_at(vec2 pos) {
return (texture/*textureBicubic*/(t_map, pos_to_uv(t_map, pos)).a * (/*1300.0*//*1278.7266845703125*/view_distance.w) + /*140.0*/view_distance.z - focus_off.z); return (/*round*/(texture/*textureBicubic*/(t_alt, pos_to_uv(t_alt, pos)).r * (/*1300.0*//*1278.7266845703125*/view_distance.w)) + /*140.0*/view_distance.z - focus_off.z);
//+ (texture(t_noise, pos * 0.002).x - 0.5) * 64.0; //+ (texture(t_noise, pos * 0.002).x - 0.5) * 64.0;
// return 0.0 // return 0.0
@ -87,7 +88,7 @@ float alt_at_real(vec2 pos) {
// #if (FLUID_MODE == FLUID_MODE_CHEAP) // #if (FLUID_MODE == FLUID_MODE_CHEAP)
// return alt_at(pos); // return alt_at(pos);
// #elif (FLUID_MODE == FLUID_MODE_SHINY) // #elif (FLUID_MODE == FLUID_MODE_SHINY)
return (textureBicubic(t_map, pos_to_tex(pos)).a * (/*1300.0*//*1278.7266845703125*/view_distance.w) + /*140.0*/view_distance.z - focus_off.z); return (/*round*/(textureBicubic(t_alt, pos_to_tex(pos)).r * (/*1300.0*//*1278.7266845703125*/view_distance.w)) + /*140.0*/view_distance.z - focus_off.z);
// #endif // #endif
//+ (texture(t_noise, pos * 0.002).x - 0.5) * 64.0; //+ (texture(t_noise, pos * 0.002).x - 0.5) * 64.0;
@ -201,14 +202,14 @@ vec2 splay(vec2 pos) {
const float SQRT_2 = sqrt(2.0) / 2.0; const float SQRT_2 = sqrt(2.0) / 2.0;
// /const float CBRT_2 = cbrt(2.0) / 2.0; // /const float CBRT_2 = cbrt(2.0) / 2.0;
// vec2 splayed = pos * (view_distance.x * SQRT_2 + pow(len * 0.5, 3.0) * (SPLAY_MULT - view_distance.x)); // vec2 splayed = pos * (view_distance.x * SQRT_2 + pow(len * 0.5, 3.0) * (SPLAY_MULT - view_distance.x));
vec2 splayed = pos * (view_distance.x * SQRT_2 + pow(len/* * SQRT_2*//* * 0.5*/, 3.0) * (textureSize(t_map, 0) * 32.0 - view_distance.x)); vec2 splayed = pos * (view_distance.x * SQRT_2 + pow(len/* * SQRT_2*//* * 0.5*/, 3.0) * (textureSize(t_alt, 0) * 32.0 - view_distance.x));
return splayed; return splayed;
// Radial: pos.x = r - view_distance.x from focus_pos, pos.y = θ from cam_pos to focus_pos on xy plane. // Radial: pos.x = r - view_distance.x from focus_pos, pos.y = θ from cam_pos to focus_pos on xy plane.
// const float PI_2 = 3.1415926535897932384626433832795; // const float PI_2 = 3.1415926535897932384626433832795;
// float squared = pos.x * pos.x; // float squared = pos.x * pos.x;
// // // vec2 splayed2 = pos * vec2(squared * (SPLAY_MULT - view_distance.x), PI); // // // vec2 splayed2 = pos * vec2(squared * (SPLAY_MULT - view_distance.x), PI);
// vec2 splayed2 = pos * vec2(squared * (textureSize(t_map, 0).x * 32.0 - view_distance.x), PI); // vec2 splayed2 = pos * vec2(squared * (textureSize(t_alt, 0).x * 32.0 - view_distance.x), PI);
// float r = splayed2.x + view_distance.x; // float r = splayed2.x + view_distance.x;
// vec2 theta = vec2(cos(splayed2.y), sin(splayed2.y)); // vec2 theta = vec2(cos(splayed2.y), sin(splayed2.y));
// return r * theta; // return r * theta;
@ -273,9 +274,14 @@ vec3 lod_pos(vec2 pos, vec2 focus_pos) {
return vec3(hpos, alt_at_real(hpos)); return vec3(hpos, alt_at_real(hpos));
} }
#ifdef HAS_LOD_FULL_INFO
uniform sampler2D t_map;
vec3 lod_col(vec2 pos) { vec3 lod_col(vec2 pos) {
//return vec3(0, 0.5, 0); //return vec3(0, 0.5, 0);
// return /*linear_to_srgb*/vec3(alt_at(pos), textureBicubic(t_map, pos_to_tex(pos)).gb);
return /*linear_to_srgb*/(textureBicubic(t_map, pos_to_tex(pos)).rgb) return /*linear_to_srgb*/(textureBicubic(t_map, pos_to_tex(pos)).rgb)
;//+ (texture(t_noise, pos * 0.04 + texture(t_noise, pos * 0.005).xy * 2.0 + texture(t_noise, pos * 0.06).xy * 0.6).x - 0.5) * 0.1; ;//+ (texture(t_noise, pos * 0.04 + texture(t_noise, pos * 0.005).xy * 2.0 + texture(t_noise, pos * 0.06).xy * 0.6).x - 0.5) * 0.1;
//+ (texture(t_noise, pos * 0.04 + texture(t_noise, pos * 0.005).xy * 2.0 + texture(t_noise, pos * 0.06).xy * 0.6).x - 0.5) * 0.1; //+ (texture(t_noise, pos * 0.04 + texture(t_noise, pos * 0.005).xy * 2.0 + texture(t_noise, pos * 0.06).xy * 0.6).x - 0.5) * 0.1;
} }
#endif

View File

@ -17,6 +17,8 @@
#define LIGHTING_DISTRIBUTION LIGHTING_DISTRIBUTION_BECKMANN #define LIGHTING_DISTRIBUTION LIGHTING_DISTRIBUTION_BECKMANN
#define HAS_LOD_FULL_INFO
#include <globals.glsl> #include <globals.glsl>
#include <sky.glsl> #include <sky.glsl>
#include <lod.glsl> #include <lod.glsl>

View File

@ -74,15 +74,18 @@ pub struct Client {
client_state: ClientState, client_state: ClientState,
thread_pool: ThreadPool, thread_pool: ThreadPool,
pub server_info: ServerInfo, pub server_info: ServerInfo,
/// Just the "base" layer for LOD; currently includes colors and a 1-byte /// Just the "base" layer for LOD; currently includes colors and nothing
/// approximation for height. In the future we'll add more layers, like /// else. In the future we'll add more layers, like shadows, rivers, and
/// shadows, rivers, and probably foliage, cities, roads, and other /// probably foliage, cities, roads, and other structures.
/// structures. pub lod_base: Vec<u32>,
pub lod_base: Arc<DynamicImage>, /// The "height" layer for LOD; currently includes only land altitudes, but
/// in the future should also water depth, and probably other
/// information as well.
pub lod_alt: Vec<u32>,
/// The "shadow" layer for LOD. Includes east and west horizon angles and /// The "shadow" layer for LOD. Includes east and west horizon angles and
/// an approximate max occluder height, which we use to try to /// an approximate max occluder height, which we use to try to
/// approximate soft and volumetric shadows. /// approximate soft and volumetric shadows.
pub lod_horizon: Arc<DynamicImage>, pub lod_horizon: Vec<u32>,
/// A fully rendered map image for use with the map and minimap; note that /// A fully rendered map image for use with the map and minimap; note that
/// this can be constructed dynamically by combining the layers of world /// this can be constructed dynamically by combining the layers of world
/// map data (e.g. with shadow map data or river data), but at present /// map data (e.g. with shadow map data or river data), but at present
@ -92,7 +95,7 @@ pub struct Client {
/// in chunks), and the third element holds the minimum height for any land /// in chunks), and the third element holds the minimum height for any land
/// chunk (i.e. the sea level) in its x coordinate, and the maximum land /// chunk (i.e. the sea level) in its x coordinate, and the maximum land
/// height above this height (i.e. the max height) in its y coordinate. /// height above this height (i.e. the max height) in its y coordinate.
pub world_map: (Arc<DynamicImage>, Vec2<u32>, Vec2<f32>), pub world_map: (Arc<DynamicImage>, Vec2<u16>, Vec2<f32>),
pub player_list: HashMap<Uid, PlayerInfo>, pub player_list: HashMap<Uid, PlayerInfo>,
pub character_list: CharacterList, pub character_list: CharacterList,
pub active_character_id: Option<i32>, pub active_character_id: Option<i32>,
@ -144,182 +147,203 @@ impl Client {
let mut stream = block_on(participant.open(10, PROMISES_ORDERED | PROMISES_CONSISTENCY))?; let mut stream = block_on(participant.open(10, PROMISES_ORDERED | PROMISES_CONSISTENCY))?;
// Wait for initial sync // Wait for initial sync
let (state, entity, server_info, lod_base, lod_horizon, world_map) = block_on(async { let (state, entity, server_info, lod_base, lod_alt, lod_horizon, world_map) = block_on(
loop { async {
match stream.recv().await? { loop {
ServerMsg::InitialSync { match stream.recv().await? {
entity_package, ServerMsg::InitialSync {
server_info, entity_package,
time_of_day, server_info,
world_map, time_of_day,
} => { world_map,
// TODO: Display that versions don't match in Voxygen } => {
if &server_info.git_hash != *common::util::GIT_HASH { // TODO: Display that versions don't match in Voxygen
warn!( if &server_info.git_hash != *common::util::GIT_HASH {
"Server is running {}[{}], you are running {}[{}], versions might \ warn!(
be incompatible!", "Server is running {}[{}], you are running {}[{}], versions \
server_info.git_hash, might be incompatible!",
server_info.git_date, server_info.git_hash,
common::util::GIT_HASH.to_string(), server_info.git_date,
common::util::GIT_DATE.to_string(), common::util::GIT_HASH.to_string(),
); common::util::GIT_DATE.to_string(),
}
debug!("Auth Server: {:?}", server_info.auth_provider);
// Initialize `State`
let mut state = State::default();
// Client-only components
state
.ecs_mut()
.register::<comp::Last<comp::CharacterState>>();
let entity = state.ecs_mut().apply_entity_package(entity_package);
*state.ecs_mut().write_resource() = time_of_day;
let map_size = world_map.dimensions;
let max_height = world_map.max_height;
let rgba = world_map.rgba;
assert_eq!(rgba.len(), (map_size.x * map_size.y) as usize);
let [west, east] = world_map.horizons;
let scale_angle =
|a: u8| (a as Alt / 255.0 * <Alt as FloatConst>::FRAC_PI_2()).tan();
let scale_height = |h: u8| h as Alt / 255.0 * max_height as Alt;
debug!("Preparing image...");
let unzip_horizons = |(angles, heights): &(Vec<_>, Vec<_>)| {
(
angles.iter().copied().map(scale_angle).collect::<Vec<_>>(),
heights
.iter()
.copied()
.map(scale_height)
.collect::<Vec<_>>(),
)
};
let horizons = [unzip_horizons(&west), unzip_horizons(&east)];
// Redraw map (with shadows this time).
let mut world_map = vec![0u32; rgba.len()];
let mut map_config = world::sim::MapConfig::default();
map_config.lgain = 1.0;
map_config.gain = max_height;
map_config.horizons = Some(&horizons);
// map_config.light_direction = Vec3::new(1.0, -1.0, 0.0);
map_config.focus.z = 0.0;
let rescale_height = |h: Alt| (h / max_height as Alt) as f32;
let bounds_check = |pos: Vec2<i32>| {
pos.reduce_partial_min() >= 0
&& pos.x < map_size.x as i32
&& pos.y < map_size.y as i32
};
map_config.generate(
|pos| {
let (rgba, downhill_wpos) = if bounds_check(pos) {
let posi =
pos.y as usize * map_size.x as usize + pos.x as usize;
let [r, g, b, a] = rgba[posi].to_le_bytes();
// Compute downhill.
let downhill = {
let mut best = -1;
let mut besth = a;
// TODO: Fix to work for dynamic WORLD_SIZE (i.e. map_size).
for nposi in neighbors(posi) {
let nbh = rgba[nposi].to_le_bytes()[3];
if nbh < besth {
besth = nbh;
best = nposi as isize;
}
}
best
};
let downhill_wpos = if downhill < 0 {
None
} else {
Some(
Vec2::new(
(downhill as usize % map_size.x as usize) as i32,
(downhill as usize / map_size.x as usize) as i32,
) * TerrainChunkSize::RECT_SIZE.map(|e| e as i32),
)
};
(Rgba::new(r, g, b, a), downhill_wpos)
} else {
(Rgba::zero(), None)
};
let wpos = pos * TerrainChunkSize::RECT_SIZE.map(|e| e as i32);
let downhill_wpos = downhill_wpos.unwrap_or(
wpos + TerrainChunkSize::RECT_SIZE.map(|e| e as i32),
); );
let alt = rescale_height(scale_height(rgba.a)); }
world::sim::MapSample {
rgb: Rgb::from(rgba), debug!("Auth Server: {:?}", server_info.auth_provider);
alt: alt as Alt,
downhill_wpos, // Initialize `State`
connections: None, let mut state = State::default();
} // Client-only components
}, state
|wpos| { .ecs_mut()
let pos = .register::<comp::Last<comp::CharacterState>>();
wpos.map2(TerrainChunkSize::RECT_SIZE, |e, f| e / f as i32);
rescale_height(if bounds_check(pos) { let entity = state.ecs_mut().apply_entity_package(entity_package);
let posi = *state.ecs_mut().write_resource() = time_of_day;
pos.y as usize * map_size.x as usize + pos.x as usize;
scale_height(rgba[posi].to_le_bytes()[3]) let map_size = world_map.dimensions;
} else { let max_height = world_map.max_height;
0.0 let rgba = world_map.rgba;
}) let alt = world_map.alt;
}, let expected_size =
|pos, (r, g, b, a)| { (u32::from(map_size.x) * u32::from(map_size.y)) as usize;
world_map[pos.y * map_size.x as usize + pos.x] = if rgba.len() != expected_size {
u32::from_le_bytes([r, g, b, a]); return Err(Error::Other(
}, "Server sent a bad world map image".into(),
); ));
let make_raw = |rgba| -> Result<_, Error> { }
let mut raw = vec![0u8; 4 * world_map.len()/*map_size.x * map_size.y*/]; if alt.len() != expected_size {
LittleEndian::write_u32_into(rgba, &mut raw); return Err(Error::Other("Server sent a bad altitude map.".into()));
Ok(Arc::new( }
image::DynamicImage::ImageRgba8({ let [west, east] = world_map.horizons;
let scale_angle =
|a: u8| (a as Alt / 255.0 * <Alt as FloatConst>::FRAC_PI_2()).tan();
let scale_height = |h: u8| h as Alt / 255.0 * max_height as Alt;
let scale_height_big =
|h: u32| (h >> 3) as Alt / 8191.0 * max_height as Alt;
debug!("Preparing image...");
let unzip_horizons = |(angles, heights): &(Vec<_>, Vec<_>)| {
(
angles.iter().copied().map(scale_angle).collect::<Vec<_>>(),
heights
.iter()
.copied()
.map(scale_height)
.collect::<Vec<_>>(),
)
};
let horizons = [unzip_horizons(&west), unzip_horizons(&east)];
// Redraw map (with shadows this time).
let mut world_map = vec![0u32; rgba.len()];
let mut map_config = world::sim::MapConfig::default();
map_config.lgain = 1.0;
map_config.gain = max_height;
map_config.horizons = Some(&horizons);
// map_config.light_direction = Vec3::new(1.0, -1.0, 0.0);
map_config.focus.z = 0.0;
let rescale_height = |h: Alt| (h / max_height as Alt) as f32;
let bounds_check = |pos: Vec2<i32>| {
pos.reduce_partial_min() >= 0
&& pos.x < map_size.x as i32
&& pos.y < map_size.y as i32
};
map_config.generate(
|pos| {
let (rgba, alt, downhill_wpos) = if bounds_check(pos) {
let posi =
pos.y as usize * map_size.x as usize + pos.x as usize;
let [r, g, b, a] = rgba[posi].to_le_bytes();
let alti = alt[posi];
// Compute downhill.
let downhill = {
let mut best = -1;
let mut besth = alti;
// TODO: Fix to work for dynamic WORLD_SIZE (i.e.
// map_size).
for nposi in neighbors(posi) {
let nbh = alt[nposi];
if nbh < besth {
besth = nbh;
best = nposi as isize;
}
}
best
};
let downhill_wpos = if downhill < 0 {
None
} else {
Some(
Vec2::new(
(downhill as usize % map_size.x as usize)
as i32,
(downhill as usize / map_size.x as usize)
as i32,
) * TerrainChunkSize::RECT_SIZE.map(|e| e as i32),
)
};
(Rgba::new(r, g, b, a), alti, downhill_wpos)
} else {
(Rgba::zero(), 0, None)
};
let wpos = pos * TerrainChunkSize::RECT_SIZE.map(|e| e as i32);
let downhill_wpos = downhill_wpos.unwrap_or(
wpos + TerrainChunkSize::RECT_SIZE.map(|e| e as i32),
);
let alt = rescale_height(scale_height_big(alt));
world::sim::MapSample {
rgb: Rgb::from(rgba),
alt: alt as Alt,
downhill_wpos,
connections: None,
}
},
|wpos| {
let pos =
wpos.map2(TerrainChunkSize::RECT_SIZE, |e, f| e / f as i32);
rescale_height(if bounds_check(pos) {
let posi =
pos.y as usize * map_size.x as usize + pos.x as usize;
scale_height_big(alt[posi])
} else {
0.0
})
},
|pos, (r, g, b, a)| {
world_map[pos.y * map_size.x as usize + pos.x] =
u32::from_le_bytes([r, g, b, a]);
},
);
let make_raw = |rgba| -> Result<_, Error> {
let mut raw =
vec![0u8; 4 * world_map.len()/*map_size.x * map_size.y*/];
LittleEndian::write_u32_into(rgba, &mut raw);
Ok(Arc::new(
image::DynamicImage::ImageRgba8({
// Should not fail if the dimensions are correct. // Should not fail if the dimensions are correct.
let map = let map =
image::ImageBuffer::from_raw(map_size.x, map_size.y, raw); image::ImageBuffer::from_raw(u32::from(map_size.x), u32::from(map_size.y), raw);
map.ok_or(Error::Other("Server sent a bad world map image".into()))? map.ok_or(Error::Other("Server sent a bad world map image".into()))?
}) })
// Flip the image, since Voxygen uses an orientation where rotation from // Flip the image, since Voxygen uses an orientation where rotation from
// positive x axis to positive y axis is counterclockwise around the z axis. // positive x axis to positive y axis is counterclockwise around the z axis.
.flipv(), .flipv(),
)) ))
}; };
let lod_base = make_raw(&rgba)?; let lod_base = rgba; //make_raw(&rgba)?;
let world_map = make_raw(&world_map)?; let lod_alt = alt; //make_raw(&alt)?;
let horizons = (west.0, west.1, east.0, east.1) let world_map = make_raw(&world_map)?;
.into_par_iter() let horizons = (west.0, west.1, east.0, east.1)
.map(|(wa, wh, ea, eh)| u32::from_le_bytes([wa, wh, ea, eh])) .into_par_iter()
.collect::<Vec<_>>(); .map(|(wa, wh, ea, eh)| u32::from_le_bytes([wa, wh, ea, eh]))
let lod_horizon = make_raw(&horizons)?; .collect::<Vec<_>>();
// TODO: Get sea_level from server. let lod_horizon = horizons; //make_raw(&horizons)?;
let map_bounds = Vec2::new( // TODO: Get sea_level from server.
/* map_config.focus.z */ world::CONFIG.sea_level, let map_bounds = Vec2::new(
/* map_config.gain */ max_height, /* map_config.focus.z */ world::CONFIG.sea_level,
); /* map_config.gain */ max_height,
debug!("Done preparing image..."); );
debug!("Done preparing image...");
break Ok(( break Ok((
state, state,
entity, entity,
server_info, server_info,
lod_base, lod_base,
lod_horizon, lod_alt,
(world_map, map_size, map_bounds), lod_horizon,
)); (world_map, map_size, map_bounds),
}, ));
ServerMsg::TooManyPlayers => break Err(Error::TooManyPlayers), },
err => { ServerMsg::TooManyPlayers => break Err(Error::TooManyPlayers),
warn!("whoops, server mad {:?}, ignoring", err); err => {
}, warn!("whoops, server mad {:?}, ignoring", err);
},
}
} }
} },
})?; )?;
stream.send(ClientMsg::Ping)?; stream.send(ClientMsg::Ping)?;
@ -335,6 +359,7 @@ impl Client {
server_info, server_info,
world_map, world_map,
lod_base, lod_base,
lod_alt,
lod_horizon, lod_horizon,
player_list: HashMap::new(), player_list: HashMap::new(),
character_list: CharacterList::default(), character_list: CharacterList::default(),

View File

@ -65,12 +65,17 @@ pub struct CharacterInfo {
/// shadow maps intended for height maps. /// shadow maps intended for height maps.
pub struct WorldMapMsg { pub struct WorldMapMsg {
/// World map dimensions (width × height) /// World map dimensions (width × height)
pub dimensions: Vec2<u32>, pub dimensions: Vec2<u16>,
/// Max height (used to scale altitudes). /// Max height (used to scale altitudes).
pub max_height: f32, pub max_height: f32,
/// RGB+A; the alpha channel is currently a proxy for altitude. /// RGB+A; the alpha channel is currently unused, but will be used in the
/// Entries are in the usual chunk order. /// future. Entries are in the usual chunk order.
pub rgba: Vec<u32>, pub rgba: Vec<u32>,
/// Altitudes: bits 2 to 0 are unused, then bits 15 to 3 are used for
/// altitude. The remainder are currently unused, but we have plans to
/// use 7 bits for water depth (using an integer f7 encoding), and we
/// will find other uses for the remaining 12 bits.
pub alt: Vec<u32>,
/// Horizon mapping. This is a variant of shadow mapping that is /// Horizon mapping. This is a variant of shadow mapping that is
/// specifically designed for height maps; it takes advantage of their /// specifically designed for height maps; it takes advantage of their
/// regular structure (e.g. no holes) to compress all information needed /// regular structure (e.g. no holes) to compress all information needed

View File

@ -508,7 +508,7 @@ impl Hud {
// Load world map // Load world map
let world_map = ( let world_map = (
ui.add_graphic_with_rotations(Graphic::Image(client.world_map.0.clone())), ui.add_graphic_with_rotations(Graphic::Image(client.world_map.0.clone())),
client.world_map.1, client.world_map.1.map(u32::from),
); );
// Load images. // Load images.
let imgs = Imgs::load(&mut ui).expect("Failed to load images!"); let imgs = Imgs::load(&mut ui).expect("Failed to load images!");

View File

@ -36,8 +36,8 @@ pub use self::{
Globals, Light, Shadow, Globals, Light, Shadow,
}, },
renderer::{ renderer::{
ColLightFmt, ColLightInfo, LodColorFmt, LodTextureFmt, Renderer, ShadowDepthStencilFmt, ColLightFmt, ColLightInfo, LodAltFmt, LodColorFmt, LodTextureFmt, Renderer,
TgtColorFmt, TgtDepthStencilFmt, WinColorFmt, WinDepthFmt, ShadowDepthStencilFmt, TgtColorFmt, TgtDepthStencilFmt, WinColorFmt, WinDepthFmt,
}, },
texture::Texture, texture::Texture,
}; };

View File

@ -50,7 +50,7 @@ gfx_defines! {
point_shadow_maps: gfx::TextureSampler<f32> = "t_point_shadow_maps", point_shadow_maps: gfx::TextureSampler<f32> = "t_point_shadow_maps",
directed_shadow_maps: gfx::TextureSampler<f32> = "t_directed_shadow_maps", directed_shadow_maps: gfx::TextureSampler<f32> = "t_directed_shadow_maps",
map: gfx::TextureSampler<[f32; 4]> = "t_map", alt: gfx::TextureSampler<[f32; 2]> = "t_alt",
horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
noise: gfx::TextureSampler<f32> = "t_noise", noise: gfx::TextureSampler<f32> = "t_noise",

View File

@ -25,7 +25,7 @@ gfx_defines! {
point_shadow_maps: gfx::TextureSampler<f32> = "t_point_shadow_maps", point_shadow_maps: gfx::TextureSampler<f32> = "t_point_shadow_maps",
directed_shadow_maps: gfx::TextureSampler<f32> = "t_directed_shadow_maps", directed_shadow_maps: gfx::TextureSampler<f32> = "t_directed_shadow_maps",
map: gfx::TextureSampler<[f32; 4]> = "t_map", alt: gfx::TextureSampler<[f32; 2]> = "t_alt",
horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
noise: gfx::TextureSampler<f32> = "t_noise", noise: gfx::TextureSampler<f32> = "t_noise",

View File

@ -23,6 +23,7 @@ gfx_defines! {
locals: gfx::ConstantBuffer<Locals> = "u_locals", locals: gfx::ConstantBuffer<Locals> = "u_locals",
globals: gfx::ConstantBuffer<Globals> = "u_globals", globals: gfx::ConstantBuffer<Globals> = "u_globals",
map: gfx::TextureSampler<[f32; 4]> = "t_map", map: gfx::TextureSampler<[f32; 4]> = "t_map",
alt: gfx::TextureSampler<[f32; 2]> = "t_alt",
horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
noise: gfx::TextureSampler<f32> = "t_noise", noise: gfx::TextureSampler<f32> = "t_noise",

View File

@ -33,7 +33,7 @@ gfx_defines! {
// lights: gfx::ConstantBuffer<Light> = "u_lights", // lights: gfx::ConstantBuffer<Light> = "u_lights",
// shadows: gfx::ConstantBuffer<Shadow> = "u_shadows", // shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
// map: gfx::TextureSampler<[f32; 4]> = "t_map", // alt: gfx::TextureSampler<[f32; 2]> = "t_map",
// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", // horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
// noise: gfx::TextureSampler<f32> = "t_noise", // noise: gfx::TextureSampler<f32> = "t_noise",
@ -58,7 +58,7 @@ gfx_defines! {
// lights: gfx::ConstantBuffer<Light> = "u_lights", // lights: gfx::ConstantBuffer<Light> = "u_lights",
// shadows: gfx::ConstantBuffer<Shadow> = "u_shadows", // shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
// map: gfx::TextureSampler<[f32; 4]> = "t_map", // alt: gfx::TextureSampler<[f32; 2]> = "t_map",
// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", // horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
// noise: gfx::TextureSampler<f32> = "t_noise", // noise: gfx::TextureSampler<f32> = "t_noise",

View File

@ -22,7 +22,7 @@ gfx_defines! {
locals: gfx::ConstantBuffer<Locals> = "u_locals", locals: gfx::ConstantBuffer<Locals> = "u_locals",
globals: gfx::ConstantBuffer<Globals> = "u_globals", globals: gfx::ConstantBuffer<Globals> = "u_globals",
map: gfx::TextureSampler<[f32; 4]> = "t_map", alt: gfx::TextureSampler<[f32; 2]> = "t_alt",
horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
noise: gfx::TextureSampler<f32> = "t_noise", noise: gfx::TextureSampler<f32> = "t_noise",

View File

@ -62,7 +62,7 @@ gfx_defines! {
point_shadow_maps: gfx::TextureSampler<f32> = "t_point_shadow_maps", point_shadow_maps: gfx::TextureSampler<f32> = "t_point_shadow_maps",
directed_shadow_maps: gfx::TextureSampler<f32> = "t_directed_shadow_maps", directed_shadow_maps: gfx::TextureSampler<f32> = "t_directed_shadow_maps",
map: gfx::TextureSampler<[f32; 4]> = "t_map", alt: gfx::TextureSampler<[f32; 2]> = "t_alt",
horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
noise: gfx::TextureSampler<f32> = "t_noise", noise: gfx::TextureSampler<f32> = "t_noise",

View File

@ -35,7 +35,7 @@ gfx_defines! {
point_shadow_maps: gfx::TextureSampler<f32> = "t_point_shadow_maps", point_shadow_maps: gfx::TextureSampler<f32> = "t_point_shadow_maps",
directed_shadow_maps: gfx::TextureSampler<f32> = "t_directed_shadow_maps", directed_shadow_maps: gfx::TextureSampler<f32> = "t_directed_shadow_maps",
map: gfx::TextureSampler<[f32; 4]> = "t_map", alt: gfx::TextureSampler<[f32; 2]> = "t_alt",
horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
noise: gfx::TextureSampler<f32> = "t_noise", noise: gfx::TextureSampler<f32> = "t_noise",

View File

@ -51,6 +51,9 @@ pub type WinDepthView = gfx::handle::DepthStencilView<gfx_backend::Resources, Wi
/// Represents the format of LOD shadows. /// Represents the format of LOD shadows.
pub type LodTextureFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Unorm); //[gfx::format::U8Norm; 4]; pub type LodTextureFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Unorm); //[gfx::format::U8Norm; 4];
/// Represents the format of LOD altitudes.
pub type LodAltFmt = (gfx::format::R16_G16, gfx::format::Unorm); //[gfx::format::U8Norm; 4];
/// Represents the format of LOD map colors. /// Represents the format of LOD map colors.
pub type LodColorFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Srgb); //[gfx::format::U8Norm; 4]; pub type LodColorFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Srgb); //[gfx::format::U8Norm; 4];
@ -1081,7 +1084,7 @@ impl Renderer {
model: &Model<skybox::SkyboxPipeline>, model: &Model<skybox::SkyboxPipeline>,
globals: &Consts<Globals>, globals: &Consts<Globals>,
locals: &Consts<skybox::Locals>, locals: &Consts<skybox::Locals>,
map: &Texture<LodColorFmt>, alt: &Texture<LodAltFmt>,
horizon: &Texture<LodTextureFmt>, horizon: &Texture<LodTextureFmt>,
) { ) {
self.encoder.draw( self.encoder.draw(
@ -1098,7 +1101,7 @@ impl Renderer {
locals: locals.buf.clone(), locals: locals.buf.clone(),
globals: globals.buf.clone(), globals: globals.buf.clone(),
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
map: (map.srv.clone(), map.sampler.clone()), alt: (alt.srv.clone(), alt.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()), horizon: (horizon.srv.clone(), horizon.sampler.clone()),
tgt_color: self.tgt_color_view.clone(), tgt_color: self.tgt_color_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */),
@ -1117,7 +1120,7 @@ impl Renderer {
lights: &Consts<Light>, lights: &Consts<Light>,
shadows: &Consts<Shadow>, shadows: &Consts<Shadow>,
light_shadows: &Consts<shadow::Locals>, light_shadows: &Consts<shadow::Locals>,
map: &Texture<LodColorFmt>, alt: &Texture<LodAltFmt>,
horizon: &Texture<LodTextureFmt>, horizon: &Texture<LodTextureFmt>,
) { ) {
// return; // return;
@ -1157,7 +1160,7 @@ impl Renderer {
vbuf: model.vbuf.clone(), vbuf: model.vbuf.clone(),
// abuf: atlas_model.vbuf.clone(), // abuf: atlas_model.vbuf.clone(),
col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()),
// col_lights: (map.srv.clone(), map.sampler.clone()), // col_lights: (alt.srv.clone(), alt.sampler.clone()),
locals: locals.buf.clone(), locals: locals.buf.clone(),
globals: globals.buf.clone(), globals: globals.buf.clone(),
bones: bones.buf.clone(), bones: bones.buf.clone(),
@ -1167,7 +1170,7 @@ impl Renderer {
point_shadow_maps, point_shadow_maps,
directed_shadow_maps, directed_shadow_maps,
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
map: (map.srv.clone(), map.sampler.clone()), alt: (alt.srv.clone(), alt.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()), horizon: (horizon.srv.clone(), horizon.sampler.clone()),
tgt_color: self.tgt_color_view.clone(), tgt_color: self.tgt_color_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */),
@ -1186,7 +1189,7 @@ impl Renderer {
_lights: &Consts<Light>, _lights: &Consts<Light>,
_shadows: &Consts<Shadow>, _shadows: &Consts<Shadow>,
_light_shadows: &Consts<shadow::Locals>, _light_shadows: &Consts<shadow::Locals>,
_map: &Texture<LodColorFmt>, _alt: &Texture<LodAltFmt>,
_horizon: &Texture<LodTextureFmt>, _horizon: &Texture<LodTextureFmt>,
) { ) {
return; return;
@ -1226,7 +1229,7 @@ impl Renderer {
vbuf: model.vbuf.clone(), vbuf: model.vbuf.clone(),
// abuf: atlas_model.vbuf.clone(), // abuf: atlas_model.vbuf.clone(),
col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()),
// col_lights: (map.srv.clone(), map.sampler.clone()), // col_lights: (alt.srv.clone(), alt.sampler.clone()),
locals: locals.buf.clone(), locals: locals.buf.clone(),
globals: globals.buf.clone(), globals: globals.buf.clone(),
bones: bones.buf.clone(), bones: bones.buf.clone(),
@ -1236,7 +1239,7 @@ impl Renderer {
point_shadow_maps, point_shadow_maps,
directed_shadow_maps, directed_shadow_maps,
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
map: (map.srv.clone(), map.sampler.clone()), alt: (alt.srv.clone(), alt.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()), horizon: (horizon.srv.clone(), horizon.sampler.clone()),
tgt_color: self.tgt_color_view.clone(), tgt_color: self.tgt_color_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (0, 0) */), tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (0, 0) */),
@ -1255,7 +1258,7 @@ impl Renderer {
lights: &Consts<Light>, lights: &Consts<Light>,
shadows: &Consts<Shadow>, shadows: &Consts<Shadow>,
light_shadows: &Consts<shadow::Locals>, light_shadows: &Consts<shadow::Locals>,
map: &Texture<LodColorFmt>, alt: &Texture<LodAltFmt>,
horizon: &Texture<LodTextureFmt>, horizon: &Texture<LodTextureFmt>,
) { ) {
let (point_shadow_maps, directed_shadow_maps) = let (point_shadow_maps, directed_shadow_maps) =
@ -1294,7 +1297,7 @@ impl Renderer {
vbuf: model.vbuf.clone(), vbuf: model.vbuf.clone(),
// abuf: atlas_model.vbuf.clone(), // abuf: atlas_model.vbuf.clone(),
col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()),
// col_lights: (map.srv.clone(), map.sampler.clone()), // col_lights: (alt.srv.clone(), alt.sampler.clone()),
locals: locals.buf.clone(), locals: locals.buf.clone(),
globals: globals.buf.clone(), globals: globals.buf.clone(),
bones: bones.buf.clone(), bones: bones.buf.clone(),
@ -1304,7 +1307,7 @@ impl Renderer {
point_shadow_maps, point_shadow_maps,
directed_shadow_maps, directed_shadow_maps,
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
map: (map.srv.clone(), map.sampler.clone()), alt: (alt.srv.clone(), alt.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()), horizon: (horizon.srv.clone(), horizon.sampler.clone()),
tgt_color: self.tgt_color_view.clone(), tgt_color: self.tgt_color_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */),
@ -1325,7 +1328,7 @@ impl Renderer {
lights: &Consts<Light>, lights: &Consts<Light>,
shadows: &Consts<Shadow>, shadows: &Consts<Shadow>,
light_shadows: &Consts<shadow::Locals>, light_shadows: &Consts<shadow::Locals>,
map: &Texture<LodColorFmt>, alt: &Texture<LodAltFmt>,
horizon: &Texture<LodTextureFmt>, horizon: &Texture<LodTextureFmt>,
) { ) {
let (point_shadow_maps, directed_shadow_maps) = let (point_shadow_maps, directed_shadow_maps) =
@ -1362,7 +1365,7 @@ impl Renderer {
// since we don't need it for things like shadows. // since we don't need it for things like shadows.
// abuf: atlas_model.vbuf.clone(), // abuf: atlas_model.vbuf.clone(),
col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()), col_lights: (col_lights.srv.clone(), col_lights.sampler.clone()),
// col_lights: (map.srv.clone(), map.sampler.clone()), // col_lights: (alt.srv.clone(), alt.sampler.clone()),
locals: locals.buf.clone(), locals: locals.buf.clone(),
globals: globals.buf.clone(), globals: globals.buf.clone(),
lights: lights.buf.clone(), lights: lights.buf.clone(),
@ -1371,7 +1374,7 @@ impl Renderer {
point_shadow_maps, point_shadow_maps,
directed_shadow_maps, directed_shadow_maps,
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
map: (map.srv.clone(), map.sampler.clone()), alt: (alt.srv.clone(), alt.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()), horizon: (horizon.srv.clone(), horizon.sampler.clone()),
tgt_color: self.tgt_color_view.clone(), tgt_color: self.tgt_color_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */),
@ -1390,7 +1393,7 @@ impl Renderer {
locals: &Consts<shadow::Locals>, locals: &Consts<shadow::Locals>,
/* lights: &Consts<Light>, /* lights: &Consts<Light>,
* shadows: &Consts<Shadow>, * shadows: &Consts<Shadow>,
* map: &Texture<LodColorFmt>, * alt: &Texture<LodAltFmt>,
* horizon: &Texture<LodTextureFmt>, */ * horizon: &Texture<LodTextureFmt>, */
) { ) {
if !self.mode.shadow.is_map() { if !self.mode.shadow.is_map() {
@ -1422,7 +1425,7 @@ impl Renderer {
// lights: lights.buf.clone(), // lights: lights.buf.clone(),
// shadows: shadows.buf.clone(), // shadows: shadows.buf.clone(),
// noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), // noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
// map: (map.srv.clone(), map.sampler.clone()), // alt: (alt.srv.clone(), alt.sampler.clone()),
// horizon: (horizon.srv.clone(), horizon.sampler.clone()), // horizon: (horizon.srv.clone(), horizon.sampler.clone()),
// Shadow stuff // Shadow stuff
@ -1445,7 +1448,7 @@ impl Renderer {
locals: &Consts<shadow::Locals>, locals: &Consts<shadow::Locals>,
/* lights: &Consts<Light>, /* lights: &Consts<Light>,
* shadows: &Consts<Shadow>, * shadows: &Consts<Shadow>,
* map: &Texture<LodColorFmt>, * alt: &Texture<LodAltFmt>,
* horizon: &Texture<LodTextureFmt>, */ * horizon: &Texture<LodTextureFmt>, */
) { ) {
if !self.mode.shadow.is_map() { if !self.mode.shadow.is_map() {
@ -1477,7 +1480,7 @@ impl Renderer {
// lights: lights.buf.clone(), // lights: lights.buf.clone(),
// shadows: shadows.buf.clone(), // shadows: shadows.buf.clone(),
// noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), // noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
// map: (map.srv.clone(), map.sampler.clone()), // alt: (alt.srv.clone(), alt.sampler.clone()),
// horizon: (horizon.srv.clone(), horizon.sampler.clone()), // horizon: (horizon.srv.clone(), horizon.sampler.clone()),
// Shadow stuff // Shadow stuff
@ -1501,7 +1504,7 @@ impl Renderer {
locals: &Consts<shadow::Locals>, locals: &Consts<shadow::Locals>,
/* lights: &Consts<Light>, /* lights: &Consts<Light>,
* shadows: &Consts<Shadow>, * shadows: &Consts<Shadow>,
* map: &Texture<LodColorFmt>, * alt: &Texture<LodAltFmt>,
* horizon: &Texture<LodTextureFmt>, */ * horizon: &Texture<LodTextureFmt>, */
) { ) {
if !self.mode.shadow.is_map() { if !self.mode.shadow.is_map() {
@ -1535,7 +1538,7 @@ impl Renderer {
// lights: lights.buf.clone(), // lights: lights.buf.clone(),
// shadows: shadows.buf.clone(), // shadows: shadows.buf.clone(),
// noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), // noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
// map: (map.srv.clone(), map.sampler.clone()), // alt: (alt.srv.clone(), alt.sampler.clone()),
// horizon: (horizon.srv.clone(), horizon.sampler.clone()), // horizon: (horizon.srv.clone(), horizon.sampler.clone()),
// Shadow stuff // Shadow stuff
@ -1557,7 +1560,7 @@ impl Renderer {
lights: &Consts<Light>, lights: &Consts<Light>,
shadows: &Consts<Shadow>, shadows: &Consts<Shadow>,
light_shadows: &Consts<shadow::Locals>, light_shadows: &Consts<shadow::Locals>,
map: &Texture<LodColorFmt>, alt: &Texture<LodAltFmt>,
horizon: &Texture<LodTextureFmt>, horizon: &Texture<LodTextureFmt>,
waves: &Texture, waves: &Texture,
) { ) {
@ -1598,7 +1601,7 @@ impl Renderer {
light_shadows: light_shadows.buf.clone(), light_shadows: light_shadows.buf.clone(),
point_shadow_maps, point_shadow_maps,
directed_shadow_maps, directed_shadow_maps,
map: (map.srv.clone(), map.sampler.clone()), alt: (alt.srv.clone(), alt.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()), horizon: (horizon.srv.clone(), horizon.sampler.clone()),
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
waves: (waves.srv.clone(), waves.sampler.clone()), waves: (waves.srv.clone(), waves.sampler.clone()),
@ -1623,7 +1626,7 @@ impl Renderer {
lights: &Consts<Light>, lights: &Consts<Light>,
shadows: &Consts<Shadow>, shadows: &Consts<Shadow>,
light_shadows: &Consts<shadow::Locals>, light_shadows: &Consts<shadow::Locals>,
map: &Texture<LodColorFmt>, alt: &Texture<LodAltFmt>,
horizon: &Texture<LodTextureFmt>, horizon: &Texture<LodTextureFmt>,
) { ) {
let (point_shadow_maps, directed_shadow_maps) = let (point_shadow_maps, directed_shadow_maps) =
@ -1668,7 +1671,7 @@ impl Renderer {
point_shadow_maps, point_shadow_maps,
directed_shadow_maps, directed_shadow_maps,
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
map: (map.srv.clone(), map.sampler.clone()), alt: (alt.srv.clone(), alt.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()), horizon: (horizon.srv.clone(), horizon.sampler.clone()),
tgt_color: self.tgt_color_view.clone(), tgt_color: self.tgt_color_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */),
@ -1684,6 +1687,7 @@ impl Renderer {
globals: &Consts<Globals>, globals: &Consts<Globals>,
locals: &Consts<lod_terrain::Locals>, locals: &Consts<lod_terrain::Locals>,
map: &Texture<LodColorFmt>, map: &Texture<LodColorFmt>,
alt: &Texture<LodAltFmt>,
horizon: &Texture<LodTextureFmt>, horizon: &Texture<LodTextureFmt>,
) { ) {
self.encoder.draw( self.encoder.draw(
@ -1701,6 +1705,7 @@ impl Renderer {
globals: globals.buf.clone(), globals: globals.buf.clone(),
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()), noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
map: (map.srv.clone(), map.sampler.clone()), map: (map.srv.clone(), map.sampler.clone()),
alt: (alt.srv.clone(), alt.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()), horizon: (horizon.srv.clone(), horizon.sampler.clone()),
tgt_color: self.tgt_color_view.clone(), tgt_color: self.tgt_color_view.clone(),
tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */), tgt_depth_stencil: (self.tgt_depth_stencil_view.clone()/* , (1, 1) */),

View File

@ -2013,7 +2013,7 @@ impl FigureMgr {
lights, lights,
shadows, shadows,
shadow_mats, shadow_mats,
&lod.map, &lod.alt,
&lod.horizon, &lod.horizon,
); );
} }
@ -2077,7 +2077,7 @@ impl FigureMgr {
lights, lights,
shadows, shadows,
shadow_mats, shadow_mats,
&lod.map, &lod.alt,
&lod.horizon, &lod.horizon,
); );
renderer.render_player_shadow( renderer.render_player_shadow(
@ -2089,7 +2089,7 @@ impl FigureMgr {
lights, lights,
shadows, shadows,
shadow_mats, shadow_mats,
&lod.map, &lod.alt,
&lod.horizon, &lod.horizon,
); );
} }

View File

@ -1,17 +1,19 @@
use crate::{ use crate::{
render::{ render::{
pipelines::lod_terrain::{Locals, Vertex}, pipelines::lod_terrain::{Locals, Vertex},
Consts, FilterMethod, Globals, LodColorFmt, LodTerrainPipeline, LodTextureFmt, Mesh, Model, Consts, Globals, LodAltFmt, LodColorFmt, LodTerrainPipeline, LodTextureFmt, Mesh, Model,
Quad, Renderer, Texture, WrapMode, Quad, Renderer, Texture,
}, },
settings::Settings, settings::Settings,
}; };
use client::Client; use client::Client;
use common::{spiral::Spiral2d, util::srgba_to_linear}; use common::{spiral::Spiral2d, util::srgba_to_linear};
use gfx::texture::SamplerInfo;
use vek::*; use vek::*;
pub struct LodData { pub struct LodData {
pub map: Texture<LodColorFmt>, pub map: Texture<LodColorFmt>,
pub alt: Texture<LodAltFmt>,
pub horizon: Texture<LodTextureFmt>, pub horizon: Texture<LodTextureFmt>,
pub tgt_detail: u32, pub tgt_detail: u32,
} }
@ -25,28 +27,54 @@ pub struct Lod {
impl LodData { impl LodData {
pub fn new( pub fn new(
renderer: &mut Renderer, renderer: &mut Renderer,
lod_base: &image::DynamicImage, map_size: Vec2<u16>,
lod_horizon: &image::DynamicImage, lod_base: &[u32],
lod_alt: &[u32],
lod_horizon: &[u32],
tgt_detail: u32, tgt_detail: u32,
border_color: gfx::texture::PackedColor, border_color: gfx::texture::PackedColor,
) -> Self { ) -> Self {
let kind = gfx::texture::Kind::D2(map_size.x, map_size.y, gfx::texture::AaMode::Single);
let info = gfx::texture::SamplerInfo::new(
gfx::texture::FilterMethod::Bilinear,
gfx::texture::WrapMode::Border,
);
Self { Self {
map: renderer map: renderer
.create_texture( .create_texture_immutable_raw(
lod_base, kind,
Some(FilterMethod::Bilinear), gfx::texture::Mipmap::Provided,
Some(WrapMode::Border), &[gfx::memory::cast_slice(lod_base)],
Some(border_color), SamplerInfo {
border: border_color,
..info
},
) )
.expect("Failed to generate map texture"), .expect("Failed to generate map texture"),
alt: renderer
.create_texture_immutable_raw(
kind,
gfx::texture::Mipmap::Provided,
&[gfx::memory::cast_slice(lod_alt)],
SamplerInfo {
border: [0.0, 0.0, 0.0, 0.0].into(),
..info
},
)
.expect("Failed to generate alt texture"),
horizon: renderer horizon: renderer
.create_texture( .create_texture_immutable_raw(
lod_horizon, kind,
Some(FilterMethod::Trilinear), gfx::texture::Mipmap::Provided,
Some(WrapMode::Border), &[gfx::memory::cast_slice(lod_horizon)],
Some([0.0, 1.0, 0.0, 1.0].into()), SamplerInfo {
// filter: gfx::texture::FilterMethod::Nearest,
// filter: gfx::texture::FilterMethod::TriLinear,
border: [1.0, 0.0, 1.0, 0.0].into(),
..info
},
) )
.expect("Failed to generate map texture"), .expect("Failed to generate horizon texture"),
tgt_detail, tgt_detail,
} }
} }
@ -60,7 +88,9 @@ impl Lod {
locals: renderer.create_consts(&[Locals::default()]).unwrap(), locals: renderer.create_consts(&[Locals::default()]).unwrap(),
data: LodData::new( data: LodData::new(
renderer, renderer,
client.world_map.1,
&client.lod_base, &client.lod_base,
&client.lod_alt,
&client.lod_horizon, &client.lod_horizon,
settings.graphics.lod_detail.max(100).min(2500), settings.graphics.lod_detail.max(100).min(2500),
[water_color.r, water_color.g, water_color.b, water_color.a].into(), [water_color.r, water_color.g, water_color.b, water_color.a].into(),
@ -95,6 +125,7 @@ impl Lod {
globals, globals,
&self.locals, &self.locals,
&self.data.map, &self.data.map,
&self.data.alt,
&self.data.horizon, &self.data.horizon,
); );
} }

View File

@ -1512,7 +1512,7 @@ impl Scene {
&self.skybox.model, &self.skybox.model,
&self.globals, &self.globals,
&self.skybox.locals, &self.skybox.locals,
&lod.map, &lod.alt,
&lod.horizon, &lod.horizon,
); );

View File

@ -105,16 +105,19 @@ impl Scene {
let map_bounds = Vec2::new(-65536.0, 131071.0); let map_bounds = Vec2::new(-65536.0, 131071.0);
let map_border = [0.0, 0.0, 0.0, 0.0]; let map_border = [0.0, 0.0, 0.0, 0.0];
let map_image = image::DynamicImage::ImageRgba8(image::RgbaImage::from_pixel( /* let map_image = image::DynamicImage::ImageRgba8(image::RgbaImage::from_pixel(
1, 1,
1, 1,
image::Rgba([0, 0, 0, 0]), image::Rgba([0, 0, 0, 0]),
)); )); */
let horizon_image = image::DynamicImage::ImageRgba8(image::RgbaImage::from_pixel( let map_image = [0];
let alt_image = [0];
/* let horizon_image = image::DynamicImage::ImageRgba8(image::RgbaImage::from_pixel(
1, 1,
1, 1,
image::Rgba([0, 1, 0, 1]), image::Rgba([0, 1, 0, 1]),
)); )); */
let horizon_image = [0x_00_01_00_01];
let mut camera = Camera::new(resolution.x / resolution.y, CameraMode::ThirdPerson); let mut camera = Camera::new(resolution.x / resolution.y, CameraMode::ThirdPerson);
camera.set_focus_pos(Vec3::unit_z() * 1.5); camera.set_focus_pos(Vec3::unit_z() * 1.5);
@ -139,7 +142,7 @@ impl Scene {
.create_consts(&[PostProcessLocals::default()]) .create_consts(&[PostProcessLocals::default()])
.unwrap(), .unwrap(),
}, },
lod: LodData::new(renderer, &map_image, &horizon_image, 1, map_border.into()),// Lod::new(renderer, client, settings), lod: LodData::new(renderer, Vec2::new(1, 1), &map_image, &alt_image, &horizon_image, 1, map_border.into()),// Lod::new(renderer, client, settings),
map_bounds,//: client.world_map.2, map_bounds,//: client.world_map.2,
figure_model_cache: FigureModelCache::new(), figure_model_cache: FigureModelCache::new(),
@ -333,7 +336,7 @@ impl Scene {
&self.skybox.model, &self.skybox.model,
&self.globals, &self.globals,
&self.skybox.locals, &self.skybox.locals,
&self.lod.map, &self.lod.alt,
&self.lod.horizon, &self.lod.horizon,
); );
@ -360,7 +363,7 @@ impl Scene {
&self.lights, &self.lights,
&self.shadows, &self.shadows,
&self.shadow_mats, &self.shadow_mats,
&self.lod.map, &self.lod.alt,
&self.lod.horizon, &self.lod.horizon,
); );
} }
@ -375,7 +378,7 @@ impl Scene {
&self.lights, &self.lights,
&self.shadows, &self.shadows,
&self.shadow_mats, &self.shadow_mats,
&self.lod.map, &self.lod.alt,
&self.lod.horizon, &self.lod.horizon,
); );
} }

View File

@ -3126,7 +3126,7 @@ impl<V: RectRasterableVol> Terrain<V> {
shadow_mats, shadow_mats,
/* lights, */ /* lights, */
/* shadows, /* shadows,
* &lod.map, * &lod.alt,
* &lod.horizon, */ * &lod.horizon, */
); );
}); });
@ -3148,7 +3148,7 @@ impl<V: RectRasterableVol> Terrain<V> {
shadow_mats, shadow_mats,
/* lights, */ /* lights, */
/* shadows, /* shadows,
* &lod.map, * &lod.alt,
* &lod.horizon, */ * &lod.horizon, */
); );
} }
@ -3210,7 +3210,7 @@ impl<V: RectRasterableVol> Terrain<V> {
shadow_mats, shadow_mats,
// lights, // lights,
// shadows, // shadows,
// &lod.map, // &lod.alt,
// &lod.horizon, // &lod.horizon,
); );
} }
@ -3229,7 +3229,7 @@ impl<V: RectRasterableVol> Terrain<V> {
shadow_mats, shadow_mats,
// lights, // lights,
// shadows, // shadows,
// &lod.map, // &lod.alt,
// &lod.horizon, // &lod.horizon,
); );
} }
@ -3258,7 +3258,7 @@ impl<V: RectRasterableVol> Terrain<V> {
lights, lights,
shadows, shadows,
shadow_mats, shadow_mats,
&lod.map, &lod.alt,
&lod.horizon, &lod.horizon,
); );
} }
@ -3362,7 +3362,7 @@ impl<V: RectRasterableVol> Terrain<V> {
lights, lights,
shadows, shadows,
shadow_mats, shadow_mats,
&lod.map, &lod.alt,
&lod.horizon, &lod.horizon,
); );
} }
@ -3391,7 +3391,7 @@ impl<V: RectRasterableVol> Terrain<V> {
lights, lights,
shadows, shadows,
shadow_mats, shadow_mats,
&lod.map, &lod.alt,
&lod.horizon, &lod.horizon,
&self.waves, &self.waves,
) )

View File

@ -1382,6 +1382,7 @@ impl WorldSim {
.unwrap(); .unwrap();
let mut v = vec![0u32; WORLD_SIZE.x * WORLD_SIZE.y]; let mut v = vec![0u32; WORLD_SIZE.x * WORLD_SIZE.y];
let mut alts = vec![0u32; WORLD_SIZE.x * WORLD_SIZE.y];
// TODO: Parallelize again. // TODO: Parallelize again.
let config = MapConfig { let config = MapConfig {
gain: self.max_height, gain: self.max_height,
@ -1400,15 +1401,18 @@ impl WorldSim {
self, self,
pos.map(|e| e as i32) * TerrainChunkSize::RECT_SIZE.map(|e| e as i32), pos.map(|e| e as i32) * TerrainChunkSize::RECT_SIZE.map(|e| e as i32),
); );
let a = (alt.min(1.0).max(0.0) * 255.0) as u8; let a = 0; //(alt.min(1.0).max(0.0) * 255.0) as u8;
v[pos.y * WORLD_SIZE.x + pos.x] = u32::from_le_bytes([r, g, b, a]); let posi = pos.y * WORLD_SIZE.x + pos.x;
v[posi] = u32::from_le_bytes([r, g, b, a]);
alts[posi] = (((alt.min(1.0).max(0.0) * 8191.0) as u32) & 0x1FFF) << 3;
}, },
); );
WorldMapMsg { WorldMapMsg {
dimensions: WORLD_SIZE.map(|e| e as u32), dimensions: WORLD_SIZE.map(|e| e as u16),
max_height: self.max_height, max_height: self.max_height,
rgba: v, rgba: v,
alt: alts,
horizons, horizons,
} }
} }