mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Enabled AO in darkness, better light attenuation
This commit is contained in:
parent
525cba5029
commit
c4879e991d
@ -25,7 +25,9 @@ vec3 illuminate(vec3 color, vec3 light, vec3 diffuse, vec3 ambience) {
|
||||
}
|
||||
|
||||
float attenuation_strength(vec3 rpos) {
|
||||
return 0.3 / pow(rpos.x * rpos.x + rpos.y * rpos.y + rpos.z * rpos.z, 0.5);
|
||||
// This is not how light attenuation works at all, but it produces visually pleasing and mechanically useful properties
|
||||
float d2 = rpos.x * rpos.x + rpos.y * rpos.y + rpos.z * rpos.z;
|
||||
return max(2.0 / pow(d2 + 10, 0.35) - pow(d2 / 50000.0, 0.8), 0.0);
|
||||
}
|
||||
|
||||
vec3 light_at(vec3 wpos, vec3 wnorm) {
|
||||
@ -43,7 +45,7 @@ vec3 light_at(vec3 wpos, vec3 wnorm) {
|
||||
// Pre-calculate difference between light and fragment
|
||||
vec3 difference = light_pos - wpos;
|
||||
|
||||
float strength = pow(attenuation_strength(difference), 0.6);
|
||||
float strength = attenuation_strength(difference);
|
||||
|
||||
// Multiply the vec3 only once
|
||||
vec3 color = srgb_to_linear(L.light_col.rgb) * (strength * L.light_col.a);
|
||||
|
@ -6,6 +6,7 @@ in vec3 f_pos;
|
||||
flat in uint f_pos_norm;
|
||||
in vec3 f_col;
|
||||
in float f_light;
|
||||
in float f_ao;
|
||||
|
||||
layout (std140)
|
||||
uniform u_locals {
|
||||
@ -29,14 +30,18 @@ void main() {
|
||||
// Use an array to avoid conditional branching
|
||||
vec3 f_norm = normals[(f_pos_norm >> 29) & 0x7u];
|
||||
|
||||
float ao = pow(f_ao, 0.5) * 0.9 + 0.1;
|
||||
|
||||
vec3 light, diffuse_light, ambient_light;
|
||||
get_sun_diffuse(f_norm, time_of_day.x, light, diffuse_light, ambient_light, 1.0);
|
||||
float point_shadow = shadow_at(f_pos, f_norm);
|
||||
diffuse_light *= f_light * point_shadow;
|
||||
ambient_light *= f_light * point_shadow;
|
||||
diffuse_light *= point_shadow;
|
||||
ambient_light *= point_shadow;
|
||||
vec3 point_light = light_at(f_pos, f_norm);
|
||||
light += point_light;
|
||||
diffuse_light += point_light;
|
||||
ambient_light *= min(f_light, ao);
|
||||
diffuse_light *= min(f_light, ao);
|
||||
diffuse_light += point_light * ao;
|
||||
vec3 surf_color = illuminate(srgb_to_linear(f_col), light, diffuse_light, ambient_light);
|
||||
|
||||
float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x);
|
||||
|
@ -16,6 +16,7 @@ out vec3 f_pos;
|
||||
flat out uint f_pos_norm;
|
||||
out vec3 f_col;
|
||||
out float f_light;
|
||||
out float f_ao;
|
||||
|
||||
const float EXTRA_NEG_Z = 65536.0;
|
||||
|
||||
@ -27,7 +28,8 @@ void main() {
|
||||
|
||||
f_col = vec3((uvec3(v_col_light) >> uvec3(8, 16, 24)) & uvec3(0xFFu)) / 255.0;
|
||||
|
||||
f_light = float(v_col_light & 0xFFu) / 255.0;
|
||||
f_light = float(v_col_light & 0x3Fu) / 64.0;
|
||||
f_ao = float((v_col_light >> 6u) & 3u) / 4.0;
|
||||
|
||||
f_pos_norm = v_pos_norm;
|
||||
|
||||
|
@ -31,6 +31,7 @@ impl Meshable<FigurePipeline, FigurePipeline> for Segment {
|
||||
offs + pos.map(|e| e as f32),
|
||||
&[[[Rgba::from_opaque(col); 3]; 3]; 3],
|
||||
|origin, norm, col, ao, light| {
|
||||
let ao = ao * 0.95 + 0.05;
|
||||
FigureVertex::new(
|
||||
origin,
|
||||
norm,
|
||||
@ -39,7 +40,7 @@ impl Meshable<FigurePipeline, FigurePipeline> for Segment {
|
||||
)
|
||||
},
|
||||
&{
|
||||
let mut ls = [[[0.0; 3]; 3]; 3];
|
||||
let mut ls = [[[None; 3]; 3]; 3];
|
||||
for x in 0..3 {
|
||||
for y in 0..3 {
|
||||
for z in 0..3 {
|
||||
@ -48,9 +49,9 @@ impl Meshable<FigurePipeline, FigurePipeline> for Segment {
|
||||
.map(|v| v.is_empty())
|
||||
.unwrap_or(true)
|
||||
{
|
||||
1.0
|
||||
Some(1.0)
|
||||
} else {
|
||||
0.0
|
||||
None
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -84,6 +85,7 @@ impl Meshable<SpritePipeline, SpritePipeline> for Segment {
|
||||
offs + pos.map(|e| e as f32),
|
||||
&[[[Rgba::from_opaque(col); 3]; 3]; 3],
|
||||
|origin, norm, col, ao, light| {
|
||||
let ao = ao * 0.95 + 0.05;
|
||||
SpriteVertex::new(
|
||||
origin,
|
||||
norm,
|
||||
@ -91,7 +93,7 @@ impl Meshable<SpritePipeline, SpritePipeline> for Segment {
|
||||
)
|
||||
},
|
||||
&{
|
||||
let mut ls = [[[0.0; 3]; 3]; 3];
|
||||
let mut ls = [[[None; 3]; 3]; 3];
|
||||
for x in 0..3 {
|
||||
for y in 0..3 {
|
||||
for z in 0..3 {
|
||||
@ -100,9 +102,9 @@ impl Meshable<SpritePipeline, SpritePipeline> for Segment {
|
||||
.map(|v| v.is_empty())
|
||||
.unwrap_or(true)
|
||||
{
|
||||
1.0
|
||||
Some(1.0)
|
||||
} else {
|
||||
0.0
|
||||
None
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ impl Blendable for BlockKind {
|
||||
fn calc_light<V: RectRasterableVol<Vox = Block> + ReadVol + Debug>(
|
||||
bounds: Aabb<i32>,
|
||||
vol: &VolGrid2d<V>,
|
||||
) -> impl Fn(Vec3<i32>) -> f32 {
|
||||
) -> impl FnMut(Vec3<i32>) -> Option<f32> + '_ {
|
||||
const UNKNOWN: u8 = 255;
|
||||
const OPAQUE: u8 = 254;
|
||||
const SUNLIGHT: u8 = 24;
|
||||
@ -189,12 +189,20 @@ fn calc_light<V: RectRasterableVol<Vox = Block> + ReadVol + Debug>(
|
||||
}
|
||||
|
||||
move |wpos| {
|
||||
let pos = wpos - outer.min;
|
||||
light_map
|
||||
.get(lm_idx(pos.x, pos.y, pos.z))
|
||||
.filter(|l| **l != OPAQUE && **l != UNKNOWN)
|
||||
.map(|l| *l as f32 / SUNLIGHT as f32)
|
||||
.unwrap_or(0.0)
|
||||
if vol_cached
|
||||
.get(wpos)
|
||||
.map(|block| block.is_opaque())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
None
|
||||
} else {
|
||||
let pos = wpos - outer.min;
|
||||
Some(light_map
|
||||
.get(lm_idx(pos.x, pos.y, pos.z))
|
||||
.filter(|l| **l != OPAQUE && **l != UNKNOWN)
|
||||
.map(|l| *l as f32 / SUNLIGHT as f32)
|
||||
.unwrap_or(0.0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -212,7 +220,7 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
|
||||
let mut opaque_mesh = Mesh::new();
|
||||
let mut fluid_mesh = Mesh::new();
|
||||
|
||||
let light = calc_light(range, self);
|
||||
let mut light = calc_light(range, self);
|
||||
|
||||
let mut lowest_opaque = range.size().d;
|
||||
let mut highest_opaque = 0;
|
||||
@ -292,7 +300,7 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
|
||||
.min(range.size().d - 1);
|
||||
for x in 1..range.size().w - 1 {
|
||||
for y in 1..range.size().w - 1 {
|
||||
let mut lights = [[[0.0; 3]; 3]; 3];
|
||||
let mut lights = [[[None; 3]; 3]; 3];
|
||||
for i in 0..3 {
|
||||
for j in 0..3 {
|
||||
for k in 0..3 {
|
||||
@ -373,8 +381,10 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
|
||||
faces_to_make(&blocks, false, |vox| !vox.is_opaque()),
|
||||
offs,
|
||||
&colors,
|
||||
|pos, norm, col, ao, light| {
|
||||
let light = (light.min(ao) * 255.0) as u32;
|
||||
|pos, norm, col, light, ao| {
|
||||
//let light = (light.min(ao) * 255.0) as u32;
|
||||
let light = (light * 255.0) as u32;
|
||||
let ao = (ao * 255.0) as u32;
|
||||
let norm = if norm.x != 0.0 {
|
||||
if norm.x < 0.0 { 0 } else { 1 }
|
||||
} else if norm.y != 0.0 {
|
||||
@ -382,7 +392,7 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
|
||||
} else {
|
||||
if norm.z < 0.0 { 4 } else { 5 }
|
||||
};
|
||||
TerrainVertex::new(norm, light, pos, col)
|
||||
TerrainVertex::new(norm, light, ao, pos, col)
|
||||
},
|
||||
&lights,
|
||||
);
|
||||
@ -392,7 +402,7 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
|
||||
faces_to_make(&blocks, false, |vox| vox.is_air()),
|
||||
offs,
|
||||
&colors,
|
||||
|pos, norm, col, _ao, light| {
|
||||
|pos, norm, col, light, _ao| {
|
||||
FluidVertex::new(pos, norm, col, light, 0.3)
|
||||
},
|
||||
&lights,
|
||||
|
@ -12,7 +12,7 @@ use crate::render::{
|
||||
fn get_ao_quad(
|
||||
shift: Vec3<i32>,
|
||||
dirs: &[Vec3<i32>],
|
||||
darknesses: &[[[f32; 3]; 3]; 3],
|
||||
darknesses: &[[[Option<f32>; 3]; 3]; 3],
|
||||
) -> Vec4<(f32, f32)> {
|
||||
dirs.windows(2)
|
||||
.map(|offs| {
|
||||
@ -23,7 +23,7 @@ fn get_ao_quad(
|
||||
.get_unchecked(pos.z)
|
||||
.get_unchecked(pos.y)
|
||||
.get_unchecked(pos.x)
|
||||
<= &0.0
|
||||
.is_none()
|
||||
}
|
||||
};
|
||||
|
||||
@ -41,17 +41,21 @@ fn get_ao_quad(
|
||||
);
|
||||
|
||||
let mut darkness = 0.0;
|
||||
let mut total = 0.0f32;
|
||||
for x in 0..2 {
|
||||
for y in 0..2 {
|
||||
let dark_pos = shift + offs[0] * x + offs[1] * y + 1;
|
||||
darkness += unsafe {
|
||||
darknesses
|
||||
.get_unchecked(dark_pos.z as usize)
|
||||
.get_unchecked(dark_pos.y as usize)
|
||||
.get_unchecked(dark_pos.x as usize)
|
||||
} / 4.0;
|
||||
if let Some(dark) = unsafe { darknesses
|
||||
.get_unchecked(dark_pos.z as usize)
|
||||
.get_unchecked(dark_pos.y as usize)
|
||||
.get_unchecked(dark_pos.x as usize) }
|
||||
{
|
||||
darkness += dark;
|
||||
total += 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
let darkness = darkness / total.max(1.0);
|
||||
|
||||
(
|
||||
darkness,
|
||||
@ -60,7 +64,7 @@ fn get_ao_quad(
|
||||
} else {
|
||||
let corner = vox_opaque(shift + offs[0] + offs[1]);
|
||||
// Map both 1 and 2 neighbors to 0.5 occlusion.
|
||||
if s1 || s2 || corner { 0.5 } else { 1.0 }
|
||||
if s1 || s2 || corner { 0.4 } else { 1.0 }
|
||||
},
|
||||
)
|
||||
})
|
||||
@ -112,7 +116,7 @@ fn create_quad<P: Pipeline, F: Fn(Vec3<f32>, Vec3<f32>, Rgb<f32>, f32, f32) -> P
|
||||
let darkness = darkness_ao.map(|e| e.0);
|
||||
let ao = darkness_ao.map(|e| e.1);
|
||||
|
||||
let ao_map = ao * 0.85 + 0.15;
|
||||
let ao_map = ao;
|
||||
|
||||
if ao[0].min(ao[2]).min(darkness[0]).min(darkness[2])
|
||||
< ao[1].min(ao[3]).min(darkness[1]).min(darkness[3])
|
||||
@ -151,7 +155,7 @@ pub fn push_vox_verts<P: Pipeline>(
|
||||
offs: Vec3<f32>,
|
||||
cols: &[[[Rgba<u8>; 3]; 3]; 3],
|
||||
vcons: impl Fn(Vec3<f32>, Vec3<f32>, Rgb<f32>, f32, f32) -> P::Vertex,
|
||||
darknesses: &[[[f32; 3]; 3]; 3],
|
||||
darknesses: &[[[Option<f32>; 3]; 3]; 3],
|
||||
) {
|
||||
let (x, y, z) = (Vec3::unit_x(), Vec3::unit_y(), Vec3::unit_z());
|
||||
|
||||
|
@ -37,7 +37,7 @@ gfx_defines! {
|
||||
}
|
||||
|
||||
impl Vertex {
|
||||
pub fn new(norm_bits: u32, light: u32, pos: Vec3<f32>, col: Rgb<f32>) -> Self {
|
||||
pub fn new(norm_bits: u32, light: u32, ao: u32, pos: Vec3<f32>, col: Rgb<f32>) -> Self {
|
||||
const EXTRA_NEG_Z: f32 = 65536.0;
|
||||
|
||||
Self {
|
||||
@ -50,7 +50,8 @@ impl Vertex {
|
||||
| ((col.r.mul(255.0) as u32) & 0xFF) << 8
|
||||
| ((col.g.mul(255.0) as u32) & 0xFF) << 16
|
||||
| ((col.b.mul(255.0) as u32) & 0xFF) << 24
|
||||
| (light & 0xFF) << 0,
|
||||
| (ao >> 6) << 6
|
||||
| ((light >> 2) & 0x3F) << 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -216,7 +216,7 @@ impl Floor {
|
||||
// Ensure no overlap
|
||||
if self.rooms
|
||||
.iter()
|
||||
.any(|r| r.collides_with_rect(room_border))// || r.contains_point(self.stair_tile))
|
||||
.any(|r| r.collides_with_rect(room_border) || r.contains_point(self.stair_tile))
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user