Liquid rendering
This commit is contained in:
parent
d7bc0b2b0f
commit
3738c5a0c0
|
@ -5,6 +5,7 @@ use std::sync::{Arc, RwLock};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use byteorder::{WriteBytesExt, NativeEndian};
|
use byteorder::{WriteBytesExt, NativeEndian};
|
||||||
use world;
|
use world;
|
||||||
|
use world::block;
|
||||||
use render;
|
use render;
|
||||||
use resources;
|
use resources;
|
||||||
use model;
|
use model;
|
||||||
|
@ -147,7 +148,20 @@ fn build_func(id: usize, models: Arc<RwLock<model::Factory>>, work_recv: mpsc::R
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Liquids need a special case
|
match block {
|
||||||
|
block::Block::Water{..} | block::Block::FlowingWater{..} => {
|
||||||
|
let tex = models.read().unwrap().textures.clone();
|
||||||
|
trans_count += model::liquid::render_liquid(tex, false, &snapshot, x, y, z, &mut trans_buffer);
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
block::Block::Lava{..} | block::Block::FlowingLava{..} => {
|
||||||
|
let tex = models.read().unwrap().textures.clone();
|
||||||
|
solid_count += model::liquid::render_liquid(tex, true, &snapshot, x, y, z, &mut solid_buffer);
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
|
||||||
let model_name = block.get_model();
|
let model_name = block.get_model();
|
||||||
let variant = block.get_model_variant();
|
let variant = block.get_model_variant();
|
||||||
if !mat.transparent {
|
if !mat.transparent {
|
||||||
|
|
|
@ -0,0 +1,139 @@
|
||||||
|
|
||||||
|
use std::io::Write;
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
use world::{self, block};
|
||||||
|
use chunk_builder::Direction;
|
||||||
|
use render;
|
||||||
|
|
||||||
|
pub fn render_liquid<W: Write>(textures: Arc<RwLock<render::TextureManager>>,lava: bool, snapshot: &world::Snapshot, x: i32, y: i32, z: i32, buf: &mut W) -> usize {
|
||||||
|
let get_liquid = if lava {
|
||||||
|
get_lava_level
|
||||||
|
} else {
|
||||||
|
get_water_level
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut count = 0;
|
||||||
|
|
||||||
|
let (tl, tr, bl, br) = if get_liquid(snapshot, x, y + 1, z).is_some() {
|
||||||
|
(8, 8, 8, 8)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
average_liquid_level(get_liquid, snapshot, x, y, z),
|
||||||
|
average_liquid_level(get_liquid, snapshot, x+1, y, z),
|
||||||
|
average_liquid_level(get_liquid, snapshot, x, y, z+1),
|
||||||
|
average_liquid_level(get_liquid, snapshot, x+1, y, z+1)
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let tex = match snapshot.get_block(x, y, z) {
|
||||||
|
block::Block::Water{..} => render::Renderer::get_texture(&textures, "minecraft:blocks/water_still"),
|
||||||
|
block::Block::FlowingWater{..} => render::Renderer::get_texture(&textures, "minecraft:blocks/water_flow"),
|
||||||
|
block::Block::Lava{..} => render::Renderer::get_texture(&textures, "minecraft:blocks/lava_still"),
|
||||||
|
block::Block::FlowingLava{..} => render::Renderer::get_texture(&textures, "minecraft:blocks/lava_flow"),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
let ux1 = 0i16;
|
||||||
|
let ux2 = 16i16 * tex.get_width() as i16;
|
||||||
|
let uy1 = 0i16;
|
||||||
|
let uy2 = 16i16 * tex.get_height() as i16;
|
||||||
|
|
||||||
|
for dir in Direction::all() {
|
||||||
|
let (ox, oy, oz) = dir.get_offset();
|
||||||
|
let special = dir == Direction::Up && (tl < 8 || tr < 8 || bl < 8 || br < 8);
|
||||||
|
let block = snapshot.get_block(x+ox, y+oy, z+oz);
|
||||||
|
if special || (!block.get_material().should_cull_against && get_liquid(snapshot, x+ox, y+oy, z+oz).is_none()) {
|
||||||
|
let verts = dir.get_verts();
|
||||||
|
for vert in verts {
|
||||||
|
let mut vert = vert.clone();
|
||||||
|
vert.tx = tex.get_x() as u16;
|
||||||
|
vert.ty = tex.get_y() as u16;
|
||||||
|
vert.tw = tex.get_width() as u16;
|
||||||
|
vert.th = tex.get_height() as u16;
|
||||||
|
vert.tatlas = tex.atlas as i16;
|
||||||
|
vert.r = 255;
|
||||||
|
vert.g = 255;
|
||||||
|
vert.b = 255;
|
||||||
|
|
||||||
|
if vert.y == 0.0 {
|
||||||
|
vert.y = y as f32;
|
||||||
|
} else {
|
||||||
|
let height = match (vert.x, vert.z) {
|
||||||
|
(0.0, 0.0) => ((16.0 / 8.0) * (tl as f32)) as i32,
|
||||||
|
(_, 0.0) => ((16.0 / 8.0) * (tr as f32)) as i32,
|
||||||
|
(0.0, _) => ((16.0 / 8.0) * (bl as f32)) as i32,
|
||||||
|
(_, _) => ((16.0 / 8.0) * (br as f32)) as i32,
|
||||||
|
};
|
||||||
|
vert.y = (height as f32)/16.0 + (y as f32);
|
||||||
|
}
|
||||||
|
|
||||||
|
vert.x += x as f32;
|
||||||
|
vert.z += z as f32;
|
||||||
|
|
||||||
|
let (bl, sl) = super::calculate_light(
|
||||||
|
&snapshot,
|
||||||
|
x, y, z,
|
||||||
|
vert.x as f64,
|
||||||
|
vert.y as f64,
|
||||||
|
vert.z as f64,
|
||||||
|
dir,
|
||||||
|
!lava,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
vert.block_light = bl;
|
||||||
|
vert.sky_light = sl;
|
||||||
|
|
||||||
|
if vert.toffsetx == 0 {
|
||||||
|
vert.toffsetx = ux1;
|
||||||
|
} else {
|
||||||
|
vert.toffsetx = ux2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if vert.toffsety == 0 {
|
||||||
|
vert.toffsety = uy1;
|
||||||
|
} else {
|
||||||
|
vert.toffsety = uy2;
|
||||||
|
}
|
||||||
|
|
||||||
|
vert.write(buf);
|
||||||
|
}
|
||||||
|
count += 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
count
|
||||||
|
}
|
||||||
|
|
||||||
|
fn average_liquid_level(
|
||||||
|
get: fn(&world::Snapshot, i32, i32, i32) -> Option<i32>,
|
||||||
|
snapshot: &world::Snapshot, x: i32, y: i32, z: i32
|
||||||
|
) -> i32 {
|
||||||
|
let mut level = 0;
|
||||||
|
for xx in -1 .. 1 {
|
||||||
|
for zz in -1 .. 1 {
|
||||||
|
if get(snapshot, x+xx, y+1, z+zz).is_some() {
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
if let Some(l) = get(snapshot, x+xx, y, z+zz) {
|
||||||
|
let nl = 7 - (l & 0x7);
|
||||||
|
if nl > level {
|
||||||
|
level = nl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
level
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_water_level(snapshot: &world::Snapshot, x: i32, y: i32, z: i32) -> Option<i32> {
|
||||||
|
match snapshot.get_block(x, y, z) {
|
||||||
|
block::Block::Water{level} | block::Block::FlowingWater{level} => Some(level),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_lava_level(snapshot: &world::Snapshot, x: i32, y: i32, z: i32) -> Option<i32> {
|
||||||
|
match snapshot.get_block(x, y, z) {
|
||||||
|
block::Block::Lava{level} | block::Block::FlowingLava{level} => Some(level),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
|
|
||||||
|
pub mod liquid;
|
||||||
|
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
@ -17,7 +19,7 @@ use image::{self, GenericImage};
|
||||||
|
|
||||||
pub struct Factory {
|
pub struct Factory {
|
||||||
resources: Arc<RwLock<resources::Manager>>,
|
resources: Arc<RwLock<resources::Manager>>,
|
||||||
textures: Arc<RwLock<render::TextureManager>>,
|
pub textures: Arc<RwLock<render::TextureManager>>,
|
||||||
|
|
||||||
models: HashMap<Key, StateModel, BuildHasherDefault<FNVHash>>,
|
models: HashMap<Key, StateModel, BuildHasherDefault<FNVHash>>,
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,7 @@ init_shader! {
|
||||||
offset => "offset",
|
offset => "offset",
|
||||||
texture => "textures",
|
texture => "textures",
|
||||||
light_level => "lightLevel",
|
light_level => "lightLevel",
|
||||||
sky_offset => "sky_offset",
|
sky_offset => "skyOffset",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -322,34 +322,40 @@ define_blocks! {
|
||||||
},
|
},
|
||||||
model { ("minecraft", "bedrock" ) },
|
model { ("minecraft", "bedrock" ) },
|
||||||
}
|
}
|
||||||
FlowingWater { // TODO
|
FlowingWater {
|
||||||
props {
|
props {
|
||||||
|
level: i32 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
||||||
},
|
},
|
||||||
|
data Some(level as usize),
|
||||||
material Material {
|
material Material {
|
||||||
renderable: true,
|
renderable: true,
|
||||||
should_cull_against: true,
|
should_cull_against: false,
|
||||||
force_shade: false,
|
force_shade: false,
|
||||||
transparent: false,
|
transparent: true,
|
||||||
},
|
},
|
||||||
model { ("minecraft", "water" ) },
|
model { ("minecraft", "water" ) },
|
||||||
}
|
}
|
||||||
Water { // TODO
|
Water {
|
||||||
props {
|
props {
|
||||||
|
level: i32 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
||||||
},
|
},
|
||||||
|
data Some(level as usize),
|
||||||
material Material {
|
material Material {
|
||||||
renderable: true,
|
renderable: true,
|
||||||
should_cull_against: true,
|
should_cull_against: false,
|
||||||
force_shade: false,
|
force_shade: false,
|
||||||
transparent: false,
|
transparent: true,
|
||||||
},
|
},
|
||||||
model { ("minecraft", "water" ) },
|
model { ("minecraft", "water" ) },
|
||||||
}
|
}
|
||||||
FlowingLava { // TODO
|
FlowingLava {
|
||||||
props {
|
props {
|
||||||
|
level: i32 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
||||||
},
|
},
|
||||||
|
data Some(level as usize),
|
||||||
material Material {
|
material Material {
|
||||||
renderable: true,
|
renderable: true,
|
||||||
should_cull_against: true,
|
should_cull_against: false,
|
||||||
force_shade: false,
|
force_shade: false,
|
||||||
transparent: false,
|
transparent: false,
|
||||||
},
|
},
|
||||||
|
@ -357,10 +363,12 @@ define_blocks! {
|
||||||
}
|
}
|
||||||
Lava {
|
Lava {
|
||||||
props {
|
props {
|
||||||
|
level: i32 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
||||||
},
|
},
|
||||||
|
data Some(level as usize),
|
||||||
material Material {
|
material Material {
|
||||||
renderable: true,
|
renderable: true,
|
||||||
should_cull_against: true,
|
should_cull_against: false,
|
||||||
force_shade: false,
|
force_shade: false,
|
||||||
transparent: false,
|
transparent: false,
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue