Directional baked lights for figures

This commit is contained in:
Joshua Barretto 2021-02-10 19:38:37 +00:00
parent c7e82aea26
commit 100cafa91b
9 changed files with 52 additions and 13 deletions

View File

@ -50,6 +50,7 @@ uniform u_locals {
mat4 model_mat;
vec4 highlight_col;
vec4 model_light;
vec4 model_glow;
ivec4 atlas_offs;
vec3 model_pos;
// bit 0 - is player
@ -181,7 +182,7 @@ void main() {
float ao = f_ao * sqrt(f_ao);//0.25 + f_ao * 0.75; ///*pow(f_ao, 0.5)*/f_ao * 0.85 + 0.15;
vec3 glow = pow(model_light.y, 3) * 4 * GLOW_COLOR;
vec3 glow = pow(pow(model_glow.w, 2.0) * (max(dot(f_norm, normalize(model_glow.xyz)), 0.0) * 1.0 + max(1.0 - length(model_glow.xyz), 0.0)), 1) * 4 * GLOW_COLOR;
emitted_light += glow;
reflected_light *= ao;

View File

@ -28,6 +28,7 @@ uniform u_locals {
mat4 model_mat;
vec4 highlight_col;
vec4 model_light;
vec4 model_glow;
ivec4 atlas_offs;
vec3 model_pos;
// bit 0 - is player

View File

@ -40,6 +40,7 @@ uniform u_locals {
mat4 model_mat;
vec4 highlight_col;
vec4 model_light;
vec4 model_glow;
ivec4 atlas_offs;
vec3 model_pos;
// bit 0 - is player

View File

@ -26,6 +26,7 @@ uniform u_locals {
mat4 model_mat;
vec4 highlight_col;
vec4 model_light;
vec4 model_glow;
ivec4 atlas_offs;
vec3 model_pos;
int flags;

View File

@ -266,7 +266,7 @@ void main() {
max_light *= f_light;
// TODO: Apply AO after this
vec3 glow = GLOW_COLOR * (pow(f_glow, 6) * 8 + pow(f_glow, 2) * 0.5);
vec3 glow = GLOW_COLOR * (pow(f_glow, 6) * 8 + pow(f_glow, 1.5) * 1.0);
emitted_light += glow;
reflected_light += glow;

View File

@ -30,8 +30,8 @@ enum FaceKind {
Fluid,
}
const SUNLIGHT: u8 = 24;
const MAX_LIGHT_DIST: i32 = SUNLIGHT as i32;
pub const SUNLIGHT: u8 = 24;
pub const MAX_LIGHT_DIST: i32 = SUNLIGHT as i32;
fn calc_light<V: RectRasterableVol<Vox = Block> + ReadVol + Debug>(
is_sunlight: bool,

View File

@ -14,6 +14,7 @@ gfx_defines! {
model_mat: [[f32; 4]; 4] = "model_mat",
highlight_col: [f32; 4] = "highlight_col",
model_light: [f32; 4] = "model_light",
model_glow: [f32; 4] = "model_glow",
atlas_offs: [i32; 4] = "atlas_offs",
model_pos: [f32; 3] = "model_pos",
flags: u32 = "flags",
@ -60,7 +61,7 @@ impl Locals {
atlas_offs: Vec2<i32>,
is_player: bool,
light: f32,
glow: f32,
glow: (Vec3<f32>, f32),
) -> Self {
let mut flags = 0;
flags |= is_player as u32;
@ -70,7 +71,8 @@ impl Locals {
highlight_col: [col.r, col.g, col.b, 1.0],
model_pos: pos.into_array(),
atlas_offs: Vec4::from(atlas_offs).into_array(),
model_light: [light, glow, 1.0, 1.0],
model_light: [light, 1.0, 1.0, 1.0],
model_glow: [glow.0.x, glow.0.y, glow.0.z, glow.1],
flags,
}
}
@ -85,7 +87,7 @@ impl Default for Locals {
Vec2::default(),
false,
1.0,
0.0,
(Vec3::zero(), 0.0),
)
}
}

View File

@ -4602,7 +4602,7 @@ pub struct FigureStateMeta {
last_pos: Option<anim::vek::Vec3<f32>>,
avg_vel: anim::vek::Vec3<f32>,
last_light: f32,
last_glow: f32,
last_glow: (Vec3<f32>, f32),
acc_vel: f32,
}
@ -4649,7 +4649,7 @@ impl<S: Skeleton> FigureState<S> {
last_pos: None,
avg_vel: anim::vek::Vec3::zero(),
last_light: 1.0,
last_glow: 0.0,
last_glow: (Vec3::zero(), 0.0),
acc_vel: 0.0,
},
skeleton,
@ -4743,14 +4743,15 @@ impl<S: Skeleton> FigureState<S> {
let s = Lerp::lerp(s_10, s_11, (wpos.x.fract() - 0.5).abs() * 2.0);
*/
Vec2::new(t.light_at_wpos(wposi), t.glow_at_wpos(wposi)).into_tuple()
(t.light_at_wpos(wposi), t.glow_normal_at_wpos(wpos))
})
.unwrap_or((1.0, 0.0));
.unwrap_or((1.0, (Vec3::zero(), 0.0)));
// Fade between light and glow levels
// TODO: Making this temporal rather than spatial is a bit dumb but it's a very
// subtle difference
self.last_light = vek::Lerp::lerp(self.last_light, light, 16.0 * dt);
self.last_glow = vek::Lerp::lerp(self.last_glow, glow, 16.0 * dt);
self.last_glow.0 = vek::Lerp::lerp(self.last_glow.0, glow.0, 16.0 * dt);
self.last_glow.1 = vek::Lerp::lerp(self.last_glow.1, glow.1, 16.0 * dt);
let locals = FigureLocals::new(
mat,

View File

@ -3,7 +3,7 @@ mod watcher;
pub use self::watcher::BlocksOfInterest;
use crate::{
mesh::{greedy::GreedyMesh, Meshable},
mesh::{greedy::GreedyMesh, Meshable, terrain::SUNLIGHT},
render::{
ColLightFmt, ColLightInfo, Consts, FluidPipeline, GlobalModel, Instances, Mesh, Model,
RenderError, Renderer, ShadowPipeline, SpriteInstance, SpriteLocals, SpritePipeline,
@ -508,6 +508,38 @@ impl<V: RectRasterableVol> Terrain<V> {
.unwrap_or(0.0)
}
pub fn glow_normal_at_wpos(&self, wpos: Vec3<f32>) -> (Vec3<f32>, f32) {
let wpos_chunk = wpos.xy().map2(TerrainChunk::RECT_SIZE, |e: f32, sz| {
(e as i32).div_euclid(sz as i32)
});
const AMBIANCE: f32 = 0.2; // 0-1, the proportion of light that should illuminate the rear of an object
let (bias, total, max) = Spiral2d::new()
.take(9)
.map(|rpos| {
let chunk_pos = wpos_chunk + rpos;
self.chunks
.get(&chunk_pos)
.map(|c| c.blocks_of_interest.lights.iter())
.into_iter()
.flatten()
.map(move |(lpos, level)| (Vec3::<i32>::from(chunk_pos * TerrainChunk::RECT_SIZE.map(|e| e as i32)) + *lpos, level))
})
.flatten()
.fold((Vec3::broadcast(0.001), 0.0, 0.0f32), |(bias, total, max), (lpos, level)| {
let rpos = lpos.map(|e| e as f32 + 0.5) - wpos;
let level = (*level as f32 - rpos.magnitude()).max(0.0) / SUNLIGHT as f32;
(
bias + rpos.try_normalized().unwrap_or_else(Vec3::zero) * level * (1.0 - AMBIANCE),
total + level,
max.max(level),
)
});
(bias.try_normalized().unwrap_or_else(Vec3::zero) / total.max(0.001), self.glow_at_wpos(wpos.map(|e| e.floor() as i32)))
}
/// Maintain terrain data. To be called once per tick.
#[allow(clippy::for_loops_over_fallibles)] // TODO: Pending review in #587
#[allow(clippy::len_zero)] // TODO: Pending review in #587