mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added glow
This commit is contained in:
parent
3bcffe1bf7
commit
51d1a2ecff
@ -82,13 +82,8 @@ void main() {
|
||||
// vec3 f_col = f_col_light.rgb;
|
||||
// float f_ao = f_col_light.a;
|
||||
|
||||
// vec2 f_uv_pos = f_uv_pos + atlas_offs.xy;
|
||||
vec4 f_col_light = texelFetch(t_col_light, ivec2(f_uv_pos)/* + uv_delta*//* - f_norm * 0.00001*/, 0);
|
||||
// vec4 f_col_light = texelFetch(t_col_light, ivec2(int(f_uv_pos.x), int(f_uv_pos.y)/* + uv_delta*//* - f_norm * 0.00001*/), 0);
|
||||
vec3 f_col = /*linear_to_srgb*//*srgb_to_linear*/(f_col_light.rgb);
|
||||
// vec3 f_col = vec3(1.0);
|
||||
// vec2 texSize = textureSize(t_col_light, 0);
|
||||
float f_ao = texture(t_col_light, (f_uv_pos + 0.5) / textureSize(t_col_light, 0)).a;//1.0;//f_col_light.a * 4.0;// f_light = float(v_col_light & 0x3Fu) / 64.0;
|
||||
float f_ao, f_glow;
|
||||
vec3 f_col = greedy_extract_col_light_glow(t_col_light, f_uv_pos, f_ao, f_glow);
|
||||
// float /*f_light*/f_ao = textureProj(t_col_light, vec3(f_uv_pos, texSize)).a;//1.0;//f_col_light.a * 4.0;// f_light = float(v_col_light & 0x3Fu) / 64.0;
|
||||
|
||||
// vec3 my_chunk_pos = (vec3((uvec3(f_pos_norm) >> uvec3(0, 9, 18)) & uvec3(0x1FFu)) - 256.0) / 2.0;
|
||||
|
@ -617,3 +617,22 @@ vec3 compute_attenuation_point(vec3 wpos, vec3 ray_dir, vec3 mu, float surface_a
|
||||
// return 1.0;
|
||||
//}
|
||||
//#endif
|
||||
|
||||
vec3 greedy_extract_col_light_glow(sampler2D t_col_light, vec2 f_uv_pos, out float f_light, out float f_glow) {
|
||||
uvec4 f_col_light = uvec4(texelFetch(t_col_light, ivec2(f_uv_pos), 0) * 255);
|
||||
vec3 f_col = vec3(
|
||||
float(((f_col_light.r >> 4u) & 0xEu) | (((f_col_light.b >> 4u) & 0xFu) << 4u)),
|
||||
float(f_col_light.a),
|
||||
float(((f_col_light.g >> 4u) & 0xEu) | (((f_col_light.b >> 0u) & 0xFu) << 4u))
|
||||
) / 255.0;
|
||||
vec2 light_00 = vec2(uvec2(f_col_light.rg) & uvec2(0x1Fu));
|
||||
vec2 light_10 = vec2(uvec2(texelFetch(t_col_light, ivec2(f_uv_pos) + ivec2(1, 0), 0).rg * 255.0) & uvec2(0x1Fu));
|
||||
vec2 light_01 = vec2(uvec2(texelFetch(t_col_light, ivec2(f_uv_pos) + ivec2(0, 1), 0).rg * 255.0) & uvec2(0x1Fu));
|
||||
vec2 light_11 = vec2(uvec2(texelFetch(t_col_light, ivec2(f_uv_pos) + ivec2(1, 1), 0).rg * 255.0) & uvec2(0x1Fu));
|
||||
vec2 light_0 = mix(light_00, light_01, fract(f_uv_pos.y));
|
||||
vec2 light_1 = mix(light_10, light_11, fract(f_uv_pos.y));
|
||||
vec2 light = mix(light_0, light_1, fract(f_uv_pos.x));
|
||||
f_light = light.x / 31.0;
|
||||
f_glow = light.y / 31.0;
|
||||
return srgb_to_linear(f_col);
|
||||
}
|
||||
|
@ -61,17 +61,8 @@ void main() {
|
||||
// vec3 dv = dFdy(f_pos);
|
||||
// vec3 f_norm = normalize(cross(du, dv));
|
||||
|
||||
// vec4 f_col_light = texture(t_col_light, (f_uv_pos + 0.5) / textureSize(t_col_light, 0)/* + uv_delta*//* - f_norm * 0.00001*/);
|
||||
// vec4 f_col_light = textureGrad(t_col_light, (f_uv_pos + 0.5) / textureSize(t_col_light, 0), vec2(0.5), vec2(0.5));
|
||||
vec4 f_col_light = texelFetch(t_col_light, ivec2(f_uv_pos)/* + uv_delta*//* - f_norm * 0.00001*/, 0);
|
||||
vec3 f_col = /*linear_to_srgb*//*srgb_to_linear*/(f_col_light.rgb);
|
||||
// vec3 f_col = vec3(1.0);
|
||||
// vec2 texSize = textureSize(t_col_light, 0);
|
||||
// float f_ao = f_col_light.a;
|
||||
// float f_ao = f_col_light.a + length(vec2(dFdx(f_col_light.a), dFdy(f_col_light.a)));
|
||||
float f_ao = texture(t_col_light, (f_uv_pos + 0.5) / textureSize(t_col_light, 0)).a;//1.0;//f_col_light.a * 4.0;// f_light = float(v_col_light & 0x3Fu) / 64.0;
|
||||
// float f_ao = 1.0;
|
||||
// float /*f_light*/f_ao = textureProj(t_col_light, vec3(f_uv_pos, texSize)).a;//1.0;//f_col_light.a * 4.0;// f_light = float(v_col_light & 0x3Fu) / 64.0;
|
||||
float f_ao, f_glow;
|
||||
vec3 f_col = greedy_extract_col_light_glow(t_col_light, f_uv_pos, f_ao, f_glow);
|
||||
|
||||
// vec3 my_chunk_pos = f_pos_norm;
|
||||
// tgt_color = vec4(hash(floor(vec4(my_chunk_pos.x, 0, 0, 0))), hash(floor(vec4(0, my_chunk_pos.y, 0, 1))), hash(floor(vec4(0, 0, my_chunk_pos.z, 2))), 1.0);
|
||||
|
@ -81,12 +81,9 @@ void main() {
|
||||
vec2 f_uv_pos = f_uv_pos + atlas_offs.xy;
|
||||
// vec4 f_col_light = textureProj(t_col_light, vec3(f_uv_pos + 0.5, textureSize(t_col_light, 0)));//(f_uv_pos/* + 0.5*/) / texSize);
|
||||
// float f_light = textureProj(t_col_light, vec3(f_uv_pos + 0.5, textureSize(t_col_light, 0))).a;//1.0;//f_col_light.a * 4.0;// f_light = float(v_col_light & 0x3Fu) / 64.0;
|
||||
vec4 f_col_light = texelFetch(t_col_light, ivec2(f_uv_pos)/* + uv_delta*//* - f_norm * 0.00001*/, 0);
|
||||
// float f_light = f_col_light.a;
|
||||
// vec4 f_col_light = texelFetch(t_col_light, ivec2(int(f_uv_pos.x), int(f_uv_pos.y)/* + uv_delta*//* - f_norm * 0.00001*/), 0);
|
||||
vec3 f_col = /*linear_to_srgb*//*srgb_to_linear*/(f_col_light.rgb);
|
||||
// vec3 f_col = vec3(1.0);
|
||||
float f_light = texture(t_col_light, (f_uv_pos + 0.5) / textureSize(t_col_light, 0)).a;//1.0;//f_col_light.a * 4.0;// f_light = float(v_col_light & 0x3Fu) / 64.0;
|
||||
float f_light, f_glow;
|
||||
vec3 f_col = greedy_extract_col_light_glow(t_col_light, f_uv_pos, f_light, f_glow);
|
||||
//float f_light = (uint(texture(t_col_light, (f_uv_pos + 0.5) / textureSize(t_col_light, 0)).r * 255.0) & 0x1Fu) / 31.0;
|
||||
// vec2 texSize = textureSize(t_col_light, 0);
|
||||
// float f_light = texture(t_col_light, f_uv_pos/* + vec2(atlas_offs.xy)*/).a;//1.0;//f_col_light.a * 4.0;// f_light = float(v_col_light & 0x3Fu) / 64.0;
|
||||
// float f_light = textureProj(t_col_light, vec3(f_uv_pos/* + vec2(atlas_offs.xy)*/, texSize.x)).a;//1.0;//f_col_light.a * 4.0;// f_light = float(v_col_light & 0x3Fu) / 64.0;
|
||||
@ -264,6 +261,8 @@ void main() {
|
||||
// emitted_light *= f_light * point_shadow * max(shade_frac, MIN_SHADOW);
|
||||
// reflected_light *= f_light * point_shadow * shade_frac;
|
||||
// max_light *= f_light * point_shadow * shade_frac;
|
||||
emitted_light += pow(f_glow, 5) * 16;
|
||||
reflected_light += pow(f_glow, 5) * 16;
|
||||
emitted_light *= f_light;
|
||||
reflected_light *= f_light;
|
||||
max_light *= f_light;
|
||||
|
@ -167,13 +167,11 @@ impl Block {
|
||||
|
||||
#[inline]
|
||||
pub fn get_glow(&self) -> Option<u8> {
|
||||
// TODO: When we have proper volumetric lighting
|
||||
// match self.get_sprite()? {
|
||||
// SpriteKind::StreetLamp | SpriteKind::StreetLampTall => Some(20),
|
||||
// SpriteKind::Velorite | SpriteKind::VeloriteFrag => Some(10),
|
||||
// _ => None,
|
||||
// }
|
||||
None
|
||||
match self.get_sprite()? {
|
||||
SpriteKind::StreetLamp | SpriteKind::StreetLampTall => Some(20),
|
||||
SpriteKind::Velorite | SpriteKind::VeloriteFrag => Some(3),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -11,7 +11,7 @@ type TodoRect = (
|
||||
Vec3<i32>,
|
||||
);
|
||||
|
||||
pub struct GreedyConfig<D, FL, FC, FO, FS, FP> {
|
||||
pub struct GreedyConfig<D, FL, FG, FC, FO, FS, FP> {
|
||||
pub data: D,
|
||||
/// The minimum position to mesh, in the coordinate system used
|
||||
/// for queries against the volume.
|
||||
@ -36,6 +36,9 @@ pub struct GreedyConfig<D, FL, FC, FO, FS, FP> {
|
||||
/// Given a position, return the lighting information for the voxel at that
|
||||
/// position.
|
||||
pub get_light: FL,
|
||||
/// Given a position, return the glow information for the voxel at that
|
||||
/// position (i.e: additional non-sun light).
|
||||
pub get_glow: FG,
|
||||
/// Given a position, return the color information for the voxel at that
|
||||
/// position.
|
||||
pub get_color: FC,
|
||||
@ -140,11 +143,12 @@ impl<'a> GreedyMesh<'a> {
|
||||
/// Returns an estimate of the bounds of the current meshed model.
|
||||
///
|
||||
/// For more information on the config parameter, see [GreedyConfig].
|
||||
pub fn push<M: PartialEq, D: 'a, FL, FC, FO, FS, FP>(
|
||||
pub fn push<M: PartialEq, D: 'a, FL, FG, FC, FO, FS, FP>(
|
||||
&mut self,
|
||||
config: GreedyConfig<D, FL, FC, FO, FS, FP>,
|
||||
config: GreedyConfig<D, FL, FG, FC, FO, FS, FP>,
|
||||
) where
|
||||
FL: for<'r> FnMut(&'r mut D, Vec3<i32>) -> f32 + 'a,
|
||||
FG: for<'r> FnMut(&'r mut D, Vec3<i32>) -> f32 + 'a,
|
||||
FC: for<'r> FnMut(&'r mut D, Vec3<i32>) -> Rgb<u8> + 'a,
|
||||
FO: for<'r> FnMut(&'r mut D, Vec3<i32>) -> bool + 'a,
|
||||
FS: for<'r> FnMut(&'r mut D, Vec3<i32>, Vec3<i32>, Vec2<Vec3<i32>>) -> Option<(bool, M)>,
|
||||
@ -173,7 +177,7 @@ impl<'a> GreedyMesh<'a> {
|
||||
span!(_guard, "finalize", "GreedyMesh::finalize");
|
||||
let cur_size = self.col_lights_size;
|
||||
let col_lights = vec![
|
||||
TerrainVertex::make_col_light(254, Rgb::broadcast(254));
|
||||
TerrainVertex::make_col_light(254, 0, Rgb::broadcast(254));
|
||||
usize::from(cur_size.x) * usize::from(cur_size.y)
|
||||
];
|
||||
let mut col_lights_info = (col_lights, cur_size);
|
||||
@ -186,7 +190,7 @@ impl<'a> GreedyMesh<'a> {
|
||||
pub fn max_size(&self) -> guillotiere::Size { self.max_size }
|
||||
}
|
||||
|
||||
fn greedy_mesh<'a, M: PartialEq, D: 'a, FL, FC, FO, FS, FP>(
|
||||
fn greedy_mesh<'a, M: PartialEq, D: 'a, FL, FG, FC, FO, FS, FP>(
|
||||
atlas: &mut guillotiere::SimpleAtlasAllocator,
|
||||
col_lights_size: &mut Vec2<u16>,
|
||||
max_size: guillotiere::Size,
|
||||
@ -196,14 +200,16 @@ fn greedy_mesh<'a, M: PartialEq, D: 'a, FL, FC, FO, FS, FP>(
|
||||
greedy_size,
|
||||
greedy_size_cross,
|
||||
get_light,
|
||||
get_glow,
|
||||
get_color,
|
||||
get_opacity,
|
||||
mut should_draw,
|
||||
mut push_quad,
|
||||
}: GreedyConfig<D, FL, FC, FO, FS, FP>,
|
||||
}: GreedyConfig<D, FL, FG, FC, FO, FS, FP>,
|
||||
) -> Box<SuspendedMesh<'a>>
|
||||
where
|
||||
FL: for<'r> FnMut(&'r mut D, Vec3<i32>) -> f32 + 'a,
|
||||
FG: for<'r> FnMut(&'r mut D, Vec3<i32>) -> f32 + 'a,
|
||||
FC: for<'r> FnMut(&'r mut D, Vec3<i32>) -> Rgb<u8> + 'a,
|
||||
FO: for<'r> FnMut(&'r mut D, Vec3<i32>) -> bool + 'a,
|
||||
FS: for<'r> FnMut(&'r mut D, Vec3<i32>, Vec3<i32>, Vec2<Vec3<i32>>) -> Option<(bool, M)>,
|
||||
@ -356,6 +362,7 @@ where
|
||||
todo_rects,
|
||||
draw_delta,
|
||||
get_light,
|
||||
get_glow,
|
||||
get_color,
|
||||
get_opacity,
|
||||
TerrainVertex::make_col_light,
|
||||
@ -511,9 +518,10 @@ fn draw_col_lights<D>(
|
||||
todo_rects: Vec<TodoRect>,
|
||||
draw_delta: Vec3<i32>,
|
||||
mut get_light: impl FnMut(&mut D, Vec3<i32>) -> f32,
|
||||
mut get_glow: impl FnMut(&mut D, Vec3<i32>) -> f32,
|
||||
mut get_color: impl FnMut(&mut D, Vec3<i32>) -> Rgb<u8>,
|
||||
mut get_opacity: impl FnMut(&mut D, Vec3<i32>) -> bool,
|
||||
mut make_col_light: impl FnMut(u8, Rgb<u8>) -> <<ColLightFmt as gfx::format::Formatted>::Surface as gfx::format::SurfaceTyped>::DataType,
|
||||
mut make_col_light: impl FnMut(u8, u8, Rgb<u8>) -> <<ColLightFmt as gfx::format::Formatted>::Surface as gfx::format::SurfaceTyped>::DataType,
|
||||
) {
|
||||
todo_rects.into_iter().for_each(|(pos, uv, rect, delta)| {
|
||||
// NOTE: Conversions are safe because width, height, and offset must be
|
||||
@ -579,8 +587,9 @@ fn draw_col_lights<D>(
|
||||
}
|
||||
) / 4.0;
|
||||
let col = get_color(data, pos);
|
||||
let light = (darkness * 255.0) as u8;
|
||||
*col_light = make_col_light(light, col);
|
||||
let light = (darkness * 31.5) as u8;
|
||||
let glow = (get_glow(data, light_pos) * 31.5) as u8;
|
||||
*col_light = make_col_light(light, glow, col);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -77,6 +77,7 @@ where
|
||||
0.0
|
||||
}
|
||||
};
|
||||
let get_glow = |vol: &mut V, pos: Vec3<i32>| 0.0;
|
||||
let get_color = |vol: &mut V, pos: Vec3<i32>| {
|
||||
vol.get(pos)
|
||||
.ok()
|
||||
@ -100,6 +101,7 @@ where
|
||||
greedy_size,
|
||||
greedy_size_cross,
|
||||
get_light,
|
||||
get_glow,
|
||||
get_color,
|
||||
get_opacity,
|
||||
should_draw,
|
||||
@ -179,6 +181,7 @@ where
|
||||
0.0
|
||||
}
|
||||
};
|
||||
let get_glow = |vol: &mut V, pos: Vec3<i32>| 0.0;
|
||||
let get_color = |vol: &mut V, pos: Vec3<i32>| {
|
||||
vol.get(pos)
|
||||
.ok()
|
||||
@ -201,6 +204,7 @@ where
|
||||
greedy_size,
|
||||
greedy_size_cross,
|
||||
get_light,
|
||||
get_glow,
|
||||
get_color,
|
||||
get_opacity,
|
||||
should_draw,
|
||||
@ -273,6 +277,7 @@ where
|
||||
0.0
|
||||
}
|
||||
};
|
||||
let get_glow = |vol: &mut V, pos: Vec3<i32>| 0.0;
|
||||
let get_color = |vol: &mut V, pos: Vec3<i32>| {
|
||||
vol.get(pos)
|
||||
.ok()
|
||||
@ -295,6 +300,7 @@ where
|
||||
greedy_size,
|
||||
greedy_size_cross,
|
||||
get_light,
|
||||
get_glow,
|
||||
get_color,
|
||||
get_opacity,
|
||||
should_draw,
|
||||
|
@ -4,6 +4,7 @@ use crate::{
|
||||
MeshGen, Meshable,
|
||||
},
|
||||
render::{self, ColLightInfo, FluidPipeline, Mesh, ShadowPipeline, TerrainPipeline},
|
||||
scene::terrain::BlocksOfInterest,
|
||||
};
|
||||
use common::{
|
||||
span,
|
||||
@ -30,9 +31,10 @@ enum FaceKind {
|
||||
}
|
||||
|
||||
const SUNLIGHT: u8 = 24;
|
||||
const _MAX_LIGHT_DIST: i32 = SUNLIGHT as i32;
|
||||
const MAX_LIGHT_DIST: i32 = SUNLIGHT as i32;
|
||||
|
||||
fn calc_light<V: RectRasterableVol<Vox = Block> + ReadVol + Debug>(
|
||||
is_sunlight: bool,
|
||||
bounds: Aabb<i32>,
|
||||
vol: &VolGrid2d<V>,
|
||||
lit_blocks: impl Iterator<Item = (Vec3<i32>, u8)>,
|
||||
@ -57,32 +59,34 @@ fn calc_light<V: RectRasterableVol<Vox = Block> + ReadVol + Debug>(
|
||||
let mut prop_que = lit_blocks
|
||||
.map(|(pos, light)| {
|
||||
let rpos = pos - outer.min;
|
||||
light_map[lm_idx(rpos.x, rpos.y, rpos.z)] = light;
|
||||
light_map[lm_idx(rpos.x, rpos.y, rpos.z)] = light.min(SUNLIGHT); // Brightest light
|
||||
(rpos.x as u8, rpos.y as u8, rpos.z as u16)
|
||||
})
|
||||
.collect::<VecDeque<_>>();
|
||||
// Start sun rays
|
||||
for x in 0..outer.size().w {
|
||||
for y in 0..outer.size().h {
|
||||
let z = outer.size().d - 1;
|
||||
let is_air = vol_cached
|
||||
.get(outer.min + Vec3::new(x, y, z))
|
||||
.ok()
|
||||
.map_or(false, |b| b.is_air());
|
||||
|
||||
light_map[lm_idx(x, y, z)] = if is_air {
|
||||
if vol_cached
|
||||
.get(outer.min + Vec3::new(x, y, z - 1))
|
||||
if is_sunlight {
|
||||
for x in 0..outer.size().w {
|
||||
for y in 0..outer.size().h {
|
||||
let z = outer.size().d - 1;
|
||||
let is_air = vol_cached
|
||||
.get(outer.min + Vec3::new(x, y, z))
|
||||
.ok()
|
||||
.map_or(false, |b| b.is_air())
|
||||
{
|
||||
light_map[lm_idx(x, y, z - 1)] = SUNLIGHT;
|
||||
prop_que.push_back((x as u8, y as u8, z as u16));
|
||||
}
|
||||
SUNLIGHT
|
||||
} else {
|
||||
OPAQUE
|
||||
};
|
||||
.map_or(false, |b| b.is_air());
|
||||
|
||||
light_map[lm_idx(x, y, z)] = if is_air {
|
||||
if vol_cached
|
||||
.get(outer.min + Vec3::new(x, y, z - 1))
|
||||
.ok()
|
||||
.map_or(false, |b| b.is_air())
|
||||
{
|
||||
light_map[lm_idx(x, y, z - 1)] = SUNLIGHT;
|
||||
prop_que.push_back((x as u8, y as u8, z as u16));
|
||||
}
|
||||
SUNLIGHT
|
||||
} else {
|
||||
OPAQUE
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,7 +127,7 @@ fn calc_light<V: RectRasterableVol<Vox = Block> + ReadVol + Debug>(
|
||||
let light = light_map[lm_idx(pos.x, pos.y, pos.z)];
|
||||
|
||||
// If ray propagate downwards at full strength
|
||||
if light == SUNLIGHT {
|
||||
if is_sunlight && light == SUNLIGHT {
|
||||
// Down is special cased and we know up is a ray
|
||||
// Special cased ray propagation
|
||||
let pos = Vec3::new(pos.x, pos.y, pos.z - 1);
|
||||
@ -218,7 +222,7 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
|
||||
type Pipeline = TerrainPipeline;
|
||||
type Result = (Aabb<f32>, ColLightInfo);
|
||||
type ShadowPipeline = ShadowPipeline;
|
||||
type Supplement = (Aabb<i32>, Vec2<u16>);
|
||||
type Supplement = (Aabb<i32>, Vec2<u16>, &'a BlocksOfInterest);
|
||||
type TranslucentPipeline = FluidPipeline;
|
||||
|
||||
#[allow(clippy::collapsible_if)]
|
||||
@ -229,21 +233,42 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
|
||||
|
||||
fn generate_mesh(
|
||||
self,
|
||||
(range, max_texture_size): Self::Supplement,
|
||||
(range, max_texture_size, boi): Self::Supplement,
|
||||
) -> MeshGen<TerrainPipeline, FluidPipeline, Self> {
|
||||
span!(
|
||||
_guard,
|
||||
"generate_mesh",
|
||||
"<&VolGrid2d as Meshable<_, _>>::generate_mesh"
|
||||
);
|
||||
|
||||
// Find blocks that should glow
|
||||
// FIXME: Replace with real lit blocks when we actually have blocks that glow.
|
||||
let lit_blocks = core::iter::empty();
|
||||
// TODO: Search neighbouring chunks too!
|
||||
// let glow_blocks = boi.lights
|
||||
// .iter()
|
||||
// .map(|(pos, glow)| (*pos + range.min.xy(), *glow));
|
||||
/* DefaultVolIterator::new(self, range.min - MAX_LIGHT_DIST, range.max + MAX_LIGHT_DIST)
|
||||
.filter_map(|(pos, block)| block.get_glow().map(|glow| (pos, glow))); */
|
||||
|
||||
let mut glow_blocks = Vec::new();
|
||||
|
||||
// TODO: This expensive, use BlocksOfInterest instead
|
||||
let mut volume = self.cached();
|
||||
for x in -MAX_LIGHT_DIST..range.size().w + MAX_LIGHT_DIST {
|
||||
for y in -MAX_LIGHT_DIST..range.size().h + MAX_LIGHT_DIST {
|
||||
for z in -1..range.size().d + 1 {
|
||||
let wpos = range.min + Vec3::new(x, y, z);
|
||||
volume
|
||||
.get(wpos)
|
||||
.ok()
|
||||
.and_then(|b| b.get_glow())
|
||||
.map(|glow| glow_blocks.push((wpos, glow)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate chunk lighting
|
||||
let mut light = calc_light(range, self, lit_blocks);
|
||||
let mut light = calc_light(true, range, self, core::iter::empty());
|
||||
let mut glow = calc_light(false, range, self, glow_blocks.into_iter());
|
||||
|
||||
let mut opaque_limits = None::<Limits>;
|
||||
let mut fluid_limits = None::<Limits>;
|
||||
@ -265,8 +290,9 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
|
||||
for x in 0..range.size().w {
|
||||
for y in 0..range.size().h {
|
||||
for z in -1..range.size().d + 1 {
|
||||
let wpos = range.min + Vec3::new(x, y, z);
|
||||
let block = volume
|
||||
.get(range.min + Vec3::new(x, y, z))
|
||||
.get(wpos)
|
||||
.map(|b| *b)
|
||||
// TODO: Replace with None or some other more reasonable value,
|
||||
// since it's not clear this will work properly with liquid.
|
||||
@ -342,6 +368,7 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
|
||||
let draw_delta = Vec3::new(1, 1, z_start);
|
||||
|
||||
let get_light = |_: &mut (), pos: Vec3<i32>| light(pos + range.min);
|
||||
let get_glow = |_: &mut (), pos: Vec3<i32>| glow(pos + range.min);
|
||||
let get_color =
|
||||
|_: &mut (), pos: Vec3<i32>| flat_get(pos).get_color().unwrap_or(Rgb::zero());
|
||||
let get_opacity = |_: &mut (), pos: Vec3<i32>| !flat_get(pos).is_opaque();
|
||||
@ -365,6 +392,7 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
|
||||
greedy_size,
|
||||
greedy_size_cross,
|
||||
get_light,
|
||||
get_glow,
|
||||
get_color,
|
||||
get_opacity,
|
||||
should_draw,
|
||||
|
@ -99,11 +99,34 @@ impl Vertex {
|
||||
}
|
||||
|
||||
pub fn make_col_light(
|
||||
// 0 to 31
|
||||
light: u8,
|
||||
// 0 to 31
|
||||
glow: u8,
|
||||
col: Rgb<u8>,
|
||||
) -> <<ColLightFmt as gfx::format::Formatted>::Surface as gfx::format::SurfaceTyped>::DataType
|
||||
{
|
||||
[col.r, col.g, col.b, light]
|
||||
//[col.r, col.g, col.b, light]
|
||||
// It would be nice for this to be cleaner, but we want to squeeze 5 fields into 4.
|
||||
// We can do this because both `light` and `glow` go from 0 to 31, meaning that they
|
||||
// can both fit into 5 bits. If we steal a bit from red and blue each (not green,
|
||||
// human eyes are more sensitive to changes in green) then we get just enough to
|
||||
// expand the nibbles of the alpha field enough to fit both `light` and `glow`.
|
||||
//
|
||||
// However, we now have a problem. In the shader code with use hardware filtering to
|
||||
// get at the `light` and `glow` attributes (but not colour, that remains constant
|
||||
// across a block). How to we resolve this if we're twiddling bits? The answer is to
|
||||
// very carefully manipulate the bit pattern such that the fields we want to filter
|
||||
// (`light` and `glow`) always sit as the lower bits of the fields. Then, we can do
|
||||
// some modulation magic to extract them from the filtering unharmed and use
|
||||
// unfiltered texture access (i.e: `texelFetch`) to access the colours, plus a little
|
||||
// bit-fiddling.
|
||||
[
|
||||
((col.r & 0b1110) << 4) | light.min(31),
|
||||
((col.b & 0b1110) << 4) | glow.min(31),
|
||||
(col.r & 0b11110000) | (col.b >> 4),
|
||||
col.g, // Green is lucky, it remains unscathed
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ pub type LodAltFmt = (gfx::format::R16_G16, gfx::format::Unorm);
|
||||
pub type LodColorFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Srgb);
|
||||
|
||||
/// Represents the format of greedy meshed color-light textures.
|
||||
pub type ColLightFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Srgb);
|
||||
pub type ColLightFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Unorm);
|
||||
|
||||
/// A handle to a shadow depth target.
|
||||
pub type ShadowDepthStencilView =
|
||||
@ -994,13 +994,18 @@ impl Renderer {
|
||||
}
|
||||
|
||||
/// Update a texture with the provided offset, size, and data.
|
||||
pub fn update_texture(
|
||||
pub fn update_texture<T: gfx::format::Formatted>(
|
||||
&mut self,
|
||||
texture: &Texture,
|
||||
texture: &Texture<T>,
|
||||
offset: [u16; 2],
|
||||
size: [u16; 2],
|
||||
data: &[[u8; 4]],
|
||||
) -> Result<(), RenderError> {
|
||||
data: &[<<T as gfx::format::Formatted>::Surface as gfx::format::SurfaceTyped>::DataType],
|
||||
) -> Result<(), RenderError>
|
||||
where
|
||||
<T as gfx::format::Formatted>::Surface: gfx::format::TextureSurface,
|
||||
<T as gfx::format::Formatted>::Channel: gfx::format::TextureChannel,
|
||||
<<T as gfx::format::Formatted>::Surface as gfx::format::SurfaceTyped>::DataType: Copy,
|
||||
{
|
||||
texture.update(&mut self.encoder, offset, size, data)
|
||||
}
|
||||
|
||||
|
@ -138,8 +138,9 @@ fn mesh_worker<V: BaseVol<Vox = Block> + RectRasterableVol + ReadVol + Debug>(
|
||||
sprite_config: &SpriteSpec,
|
||||
) -> MeshWorkerResponse {
|
||||
span!(_guard, "mesh_worker");
|
||||
let blocks_of_interest = BlocksOfInterest::from_chunk(&chunk);
|
||||
let (opaque_mesh, fluid_mesh, _shadow_mesh, (bounds, col_lights_info)) =
|
||||
volume.generate_mesh((range, Vec2::new(max_texture_size, max_texture_size)));
|
||||
volume.generate_mesh((range, Vec2::new(max_texture_size, max_texture_size), &blocks_of_interest));
|
||||
MeshWorkerResponse {
|
||||
pos,
|
||||
z_bounds: (bounds.min.z, bounds.max.z),
|
||||
@ -199,7 +200,7 @@ fn mesh_worker<V: BaseVol<Vox = Block> + RectRasterableVol + ReadVol + Debug>(
|
||||
|
||||
instances
|
||||
},
|
||||
blocks_of_interest: BlocksOfInterest::from_chunk(&chunk),
|
||||
blocks_of_interest,
|
||||
started_tick,
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ pub struct BlocksOfInterest {
|
||||
// Note: these are only needed for chunks within the iteraction range so this is a potential
|
||||
// area for optimization
|
||||
pub interactables: Vec<Vec3<i32>>,
|
||||
pub lights: Vec<(Vec3<i32>, u8)>,
|
||||
}
|
||||
|
||||
impl BlocksOfInterest {
|
||||
@ -30,6 +31,7 @@ impl BlocksOfInterest {
|
||||
let mut reeds = Vec::new();
|
||||
let mut flowers = Vec::new();
|
||||
let mut interactables = Vec::new();
|
||||
let mut lights = Vec::new();
|
||||
|
||||
chunk
|
||||
.vol_iter(
|
||||
@ -73,6 +75,9 @@ impl BlocksOfInterest {
|
||||
if block.is_collectible() {
|
||||
interactables.push(pos);
|
||||
}
|
||||
if let Some(glow) = block.get_glow() {
|
||||
lights.push((pos, glow));
|
||||
}
|
||||
});
|
||||
|
||||
Self {
|
||||
@ -84,6 +89,7 @@ impl BlocksOfInterest {
|
||||
reeds,
|
||||
flowers,
|
||||
interactables,
|
||||
lights,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user