mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
add blank graphic, ao for voxel graphics in the ui
Former-commit-id: ceaba13fdd47707a8804886b5db2260a8cbba2f1
This commit is contained in:
parent
2e69526069
commit
0b4e268dee
@ -144,7 +144,7 @@ widget_ids! {
|
||||
pub(self) struct Imgs {
|
||||
//Missing: ActionBar, Health/Mana/Energy Bar & Char Window BG/Frame
|
||||
//Logo
|
||||
v_logo: ImgId,
|
||||
//v_logo: ImgId,
|
||||
// Bag
|
||||
bag: ImgId,
|
||||
bag_hover: ImgId,
|
||||
@ -249,7 +249,7 @@ pub(self) struct Imgs {
|
||||
}
|
||||
impl Imgs {
|
||||
fn new(ui: &mut Ui, renderer: &mut Renderer) -> Imgs {
|
||||
let mut load = |filename| {
|
||||
let mut load = |filename, ui: &mut Ui| {
|
||||
let fullpath: String = ["/voxygen/", filename].concat();
|
||||
let image = image::load_from_memory(
|
||||
assets::load(fullpath.as_str())
|
||||
@ -261,113 +261,112 @@ impl Imgs {
|
||||
};
|
||||
Imgs {
|
||||
// Bag
|
||||
bag: load("element/buttons/bag/closed.png"),
|
||||
bag_hover: load("element/buttons/bag/closed_hover.png"),
|
||||
bag_press: load("element/buttons/bag/closed_press.png"),
|
||||
bag_open: load("element/buttons/bag/open.png"),
|
||||
bag_open_hover: load("element/buttons/bag/open_hover.png"),
|
||||
bag_open_press: load("element/buttons/bag/open_press.png"),
|
||||
bag_contents: load("element/frames/bag.png"),
|
||||
inv_grid: load("element/frames/inv_grid.png"),
|
||||
inv_slot: load("element/buttons/inv_slot.png"),
|
||||
bag: load("element/buttons/bag/closed.png", ui),
|
||||
bag_hover: load("element/buttons/bag/closed_hover.png", ui),
|
||||
bag_press: load("element/buttons/bag/closed_press.png", ui),
|
||||
bag_open: load("element/buttons/bag/open.png", ui),
|
||||
bag_open_hover: load("element/buttons/bag/open_hover.png", ui),
|
||||
bag_open_press: load("element/buttons/bag/open_press.png", ui),
|
||||
bag_contents: load("element/frames/bag.png", ui),
|
||||
inv_grid: load("element/frames/inv_grid.png", ui),
|
||||
inv_slot: load("element/buttons/inv_slot.png", ui),
|
||||
|
||||
// Close button
|
||||
close_button: load("element/buttons/x.png"),
|
||||
close_button_hover: load("element/buttons/x_hover.png"),
|
||||
close_button_press: load("element/buttons/x_press.png"),
|
||||
close_button: load("element/buttons/x.png", ui),
|
||||
close_button_hover: load("element/buttons/x_hover.png", ui),
|
||||
close_button_press: load("element/buttons/x_press.png", ui),
|
||||
|
||||
// Esc-Menu
|
||||
esc_bg: load("element/frames/menu.png"),
|
||||
fireplace: load("element/misc_backgrounds/fireplace.png"),
|
||||
button_dark: load("element/buttons/button_dark.png"),
|
||||
button_dark_hover: load("element/buttons/button_dark_hover.png"),
|
||||
button_dark_press: load("element/buttons/button_dark_press.png"),
|
||||
esc_bg: load("element/frames/menu.png", ui),
|
||||
fireplace: load("element/misc_backgrounds/fireplace.png", ui),
|
||||
button_dark: load("element/buttons/button_dark.png", ui),
|
||||
button_dark_hover: load("element/buttons/button_dark_hover.png", ui),
|
||||
button_dark_press: load("element/buttons/button_dark_press.png", ui),
|
||||
|
||||
// MiniMap
|
||||
mmap_frame: load("element/frames/mmap.png"),
|
||||
mmap_frame_bg: load("element/misc_backgrounds/mmap_bg.png"),
|
||||
mmap_icons: load("element/buttons/mmap_icons.png"),
|
||||
mmap_frame: load("element/frames/mmap.png", ui),
|
||||
mmap_frame_bg: load("element/misc_backgrounds/mmap_bg.png", ui),
|
||||
mmap_icons: load("element/buttons/mmap_icons.png", ui),
|
||||
|
||||
// Settings at Mini-Map
|
||||
mmap_button: load("element/buttons/border.png"),
|
||||
mmap_button_hover: load("element/buttons/border_mo.png"),
|
||||
mmap_button_press: load("element/buttons/border_press.png"),
|
||||
mmap_button_open: load("element/buttons/border_pressed.png"),
|
||||
mmap_button: load("element/buttons/border.png", ui),
|
||||
mmap_button_hover: load("element/buttons/border_mo.png", ui),
|
||||
mmap_button_press: load("element/buttons/border_press.png", ui),
|
||||
mmap_button_open: load("element/buttons/border_pressed.png", ui),
|
||||
|
||||
// Skillbar Module
|
||||
sb_grid: load("element/skill_bar/sbar_grid.png"),
|
||||
sb_grid_bg: load("element/skill_bar/sbar_grid_bg.png"),
|
||||
l_click: load("element/skill_bar/l.png"),
|
||||
r_click: load("element/skill_bar/r.png"),
|
||||
mana_bar: load("element/skill_bar/mana_bar.png"),
|
||||
health_bar: load("element/skill_bar/health_bar.png"),
|
||||
xp_bar: load("element/skill_bar/xp_bar.png"),
|
||||
sb_grid: load("element/skill_bar/sbar_grid.png", ui),
|
||||
sb_grid_bg: load("element/skill_bar/sbar_grid_bg.png", ui),
|
||||
l_click: load("element/skill_bar/l.png", ui),
|
||||
r_click: load("element/skill_bar/r.png", ui),
|
||||
mana_bar: load("element/skill_bar/mana_bar.png", ui),
|
||||
health_bar: load("element/skill_bar/health_bar.png", ui),
|
||||
xp_bar: load("element/skill_bar/xp_bar.png", ui),
|
||||
|
||||
//Buff Frame(s)
|
||||
//buff_frame: load("element/skill_bar/buff_frame.png"),
|
||||
//buff_frame_bg: load("element/skill_bar/buff_frame_bg.png"),
|
||||
//buff_frame_red: load("element/skill_bar/buff_frame_red.png"),
|
||||
//buff_frame_green: load("element/skill_bar/buff_frame_green.png"),
|
||||
//buff_frame: load("element/skill_bar/buff_frame.png", ui),
|
||||
//buff_frame_bg: load("element/skill_bar/buff_frame_bg.png", ui),
|
||||
//buff_frame_red: load("element/skill_bar/buff_frame_red.png", ui),
|
||||
//buff_frame_green: load("element/skill_bar/buff_frame_green.png", ui),
|
||||
|
||||
//Missing: Buff Frame Animation (.gif ?!) (we could do animation in ui.maintain(), or in shader?)
|
||||
window_frame: load("element/frames/window.png"),
|
||||
window_frame_2: load("element/frames/window_2.png"),
|
||||
window_frame: load("element/frames/window.png", ui),
|
||||
window_frame_2: load("element/frames/window_2.png", ui),
|
||||
|
||||
//Settings Window
|
||||
settings_bg: load("element/frames/settings.png"),
|
||||
settings_icon: load("element/icons/settings.png"),
|
||||
settings_button_mo: load("element/buttons/blue_mo.png"),
|
||||
check: load("element/buttons/check/no.png"),
|
||||
check_mo: load("element/buttons/check/no_mo.png"),
|
||||
check_press: load("element/buttons/check/press.png"),
|
||||
check_checked: load("element/buttons/check/yes.png"),
|
||||
check_checked_mo: load("element/buttons/check/yes_mo.png"),
|
||||
slider: load("element/slider/track.png"),
|
||||
slider_indicator: load("element/slider/indicator.png"),
|
||||
button_blank: load("element/nothing.png"),
|
||||
button_blue_mo: load("element/buttons/blue_mo.png"),
|
||||
button_blue_press: load("element/buttons/blue_press.png"),
|
||||
settings_bg: load("element/frames/settings.png", ui),
|
||||
settings_icon: load("element/icons/settings.png", ui),
|
||||
settings_button_mo: load("element/buttons/blue_mo.png", ui),
|
||||
check: load("element/buttons/check/no.png", ui),
|
||||
check_mo: load("element/buttons/check/no_mo.png", ui),
|
||||
check_press: load("element/buttons/check/press.png", ui),
|
||||
check_checked: load("element/buttons/check/yes.png", ui),
|
||||
check_checked_mo: load("element/buttons/check/yes_mo.png", ui),
|
||||
slider: load("element/slider/track.png", ui),
|
||||
slider_indicator: load("element/slider/indicator.png", ui),
|
||||
button_blank: ui.new_graphic(ui::Graphic::Blank),
|
||||
button_blue_mo: load("element/buttons/blue_mo.png", ui),
|
||||
button_blue_press: load("element/buttons/blue_press.png", ui),
|
||||
|
||||
// Window BG
|
||||
window_bg: load("element/misc_backgrounds/window_bg.png"),
|
||||
v_logo: load("element/v_logo.png"),
|
||||
window_bg: load("element/misc_backgrounds/window_bg.png", ui),
|
||||
|
||||
//Social Window
|
||||
social_bg: load("element/misc_backgrounds/small_bg.png"),
|
||||
social_icon: load("element/icons/social.png"),
|
||||
social_bg: load("element/misc_backgrounds/small_bg.png", ui),
|
||||
social_icon: load("element/icons/social.png", ui),
|
||||
|
||||
//Map Window
|
||||
map_bg: load("element/misc_backgrounds/small_bg.png"),
|
||||
map_icon: load("element/icons/map.png"),
|
||||
map_frame: load("element/frames/window_map.png"),
|
||||
map_bg: load("element/misc_backgrounds/small_bg.png", ui),
|
||||
map_icon: load("element/icons/map.png", ui),
|
||||
map_frame: load("element/frames/window_map.png", ui),
|
||||
|
||||
// Spell Book Window
|
||||
spellbook_bg: load("element/misc_backgrounds/small_bg.png"),
|
||||
spellbook_icon: load("element/icons/spellbook.png"),
|
||||
spellbook_bg: load("element/misc_backgrounds/small_bg.png", ui),
|
||||
spellbook_icon: load("element/icons/spellbook.png", ui),
|
||||
|
||||
//Char Window
|
||||
charwindow: load("element/misc_backgrounds/charwindow.png"),
|
||||
charwindow_icon: load("element/icons/charwindow.png"),
|
||||
charwindow_tab_bg: load("element/frames/tab.png"),
|
||||
charwindow_tab: load("element/buttons/tab.png"),
|
||||
charwindow_expbar: load("element/misc_backgrounds/small_bg.png"),
|
||||
progress_frame: load("element/frames/progress_bar.png"),
|
||||
progress: load("element/misc_backgrounds/progress.png"),
|
||||
charwindow: load("element/misc_backgrounds/charwindow.png", ui),
|
||||
charwindow_icon: load("element/icons/charwindow.png", ui),
|
||||
charwindow_tab_bg: load("element/frames/tab.png", ui),
|
||||
charwindow_tab: load("element/buttons/tab.png", ui),
|
||||
charwindow_expbar: load("element/misc_backgrounds/small_bg.png", ui),
|
||||
progress_frame: load("element/frames/progress_bar.png", ui),
|
||||
progress: load("element/misc_backgrounds/progress.png", ui),
|
||||
|
||||
//Quest-Log Window
|
||||
questlog_bg: load("element/misc_backgrounds/small_bg.png"),
|
||||
questlog_icon: load("element/icons/questlog.png"),
|
||||
questlog_bg: load("element/misc_backgrounds/small_bg.png", ui),
|
||||
questlog_icon: load("element/icons/questlog.png", ui),
|
||||
|
||||
// Chat-Arrows
|
||||
chat_arrow: load("element/buttons/arrow/chat_arrow.png"),
|
||||
chat_arrow_mo: load("element/buttons/arrow/chat_arrow_mo.png"),
|
||||
chat_arrow_press: load("element/buttons/arrow/chat_arrow_press.png"),
|
||||
chat_arrow_up: load("element/buttons/arrow/chat_arrow_up.png"),
|
||||
chat_arrow_up_mo: load("element/buttons/arrow/chat_arrow_up_mo.png"),
|
||||
chat_arrow_up_press: load("element/buttons/arrow/chat_arrow_up_press.png"),
|
||||
chat_arrow_down: load("element/buttons/arrow/chat_arrow_down.png"),
|
||||
chat_arrow_down_mo: load("element/buttons/arrow/chat_arrow_down_mo.png"),
|
||||
chat_arrow_down_press: load("element/buttons/arrow/chat_arrow_down_press.png"),
|
||||
chat_arrow: load("element/buttons/arrow/chat_arrow.png", ui),
|
||||
chat_arrow_mo: load("element/buttons/arrow/chat_arrow_mo.png", ui),
|
||||
chat_arrow_press: load("element/buttons/arrow/chat_arrow_press.png", ui),
|
||||
chat_arrow_up: load("element/buttons/arrow/chat_arrow_up.png", ui),
|
||||
chat_arrow_up_mo: load("element/buttons/arrow/chat_arrow_up_mo.png", ui),
|
||||
chat_arrow_up_press: load("element/buttons/arrow/chat_arrow_up_press.png", ui),
|
||||
chat_arrow_down: load("element/buttons/arrow/chat_arrow_down.png", ui),
|
||||
chat_arrow_down_mo: load("element/buttons/arrow/chat_arrow_down_mo.png", ui),
|
||||
chat_arrow_down_press: load("element/buttons/arrow/chat_arrow_down_press.png", ui),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,10 @@ use crate::{
|
||||
window::Window,
|
||||
DEFAULT_PUBLIC_SERVER,
|
||||
};
|
||||
use common::assets;
|
||||
use common::{
|
||||
assets,
|
||||
figure::Segment,
|
||||
};
|
||||
use conrod_core::{
|
||||
color,
|
||||
color::TRANSPARENT,
|
||||
@ -41,6 +44,7 @@ widget_ids! {
|
||||
// Error
|
||||
error_frame,
|
||||
button_ok,
|
||||
test_vox,
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,10 +66,13 @@ struct Imgs {
|
||||
button_dark: ImgId,
|
||||
button_dark_hover: ImgId,
|
||||
button_dark_press: ImgId,
|
||||
test_vox: ImgId,
|
||||
}
|
||||
impl Imgs {
|
||||
fn new(ui: &mut Ui, renderer: &mut Renderer) -> Imgs {
|
||||
// TODO: update paths
|
||||
fn load_segment(filename: &'static str) -> Segment {
|
||||
Segment::from(dot_vox::load(&(concat!(env!("CARGO_MANIFEST_DIR"), "/../assets/voxygen/").to_string() + filename)).unwrap())
|
||||
}
|
||||
let mut load = |filename| {
|
||||
let fullpath: String = ["/voxygen/", filename].concat();
|
||||
let image = image::load_from_memory(
|
||||
@ -98,6 +105,7 @@ impl Imgs {
|
||||
button_dark: load("element/buttons/button_dark.png"),
|
||||
button_dark_hover: load("element/buttons/button_dark_hover.png"),
|
||||
button_dark_press: load("element/buttons/button_dark_press.png"),
|
||||
test_vox: ui.new_graphic(ui::Graphic::Voxel(load_segment("test.vox"))),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -178,6 +186,11 @@ impl MainMenuUi {
|
||||
.label_x(Relative::Scalar(-100.0))
|
||||
.set(self.ids.v_logo, ui_widgets);
|
||||
|
||||
Image::new(self.imgs.test_vox)
|
||||
.w_h(750.0, 750.0)
|
||||
.top_right_with_margins_on(self.ids.bg, 50.0, 50.0)
|
||||
.set(self.ids.test_vox, ui_widgets);
|
||||
|
||||
// Input fields
|
||||
// Used when the login button is pressed, or enter is pressed within input field
|
||||
macro_rules! login {
|
||||
|
@ -11,6 +11,7 @@ use vek::*;
|
||||
pub enum Graphic {
|
||||
Image(DynamicImage),
|
||||
Voxel(Segment),
|
||||
Blank,
|
||||
}
|
||||
#[derive(PartialEq, Eq, Hash, Copy, Clone)]
|
||||
pub struct Id(u32);
|
||||
@ -41,6 +42,9 @@ impl GraphicCache {
|
||||
|
||||
id
|
||||
}
|
||||
pub fn get_graphic(&self, id: Id) -> Option<&Graphic> {
|
||||
self.graphic_map.get(&id)
|
||||
}
|
||||
pub fn cache_res<F>(&mut self, graphic_id: Id, dims: Vec2<u16>, source: Aabr<f64>, mut cacher: F) -> Option<Aabr<u16>> where F: FnMut(Aabr<u16>, Vec<[u8; 4]>) {
|
||||
match self.rect_map.get(&(graphic_id, dims, source.map(|e| e.to_bits()))) { //<-------- TODO: Replace this with rounded representation of source
|
||||
Some(aabr) => Some(*aabr),
|
||||
@ -74,6 +78,7 @@ impl GraphicCache {
|
||||
Graphic::Voxel(segment) => {
|
||||
super::veuc::draw_vox(&segment, aabr.size().into())
|
||||
}
|
||||
Graphic::Blank => return None,
|
||||
};
|
||||
|
||||
// Draw to allocated area
|
||||
|
@ -246,8 +246,6 @@ impl Ui {
|
||||
self.image_map.insert(self.cache.new_graphic(graphic))
|
||||
}
|
||||
|
||||
// TODO: add function that creates a blank graphic
|
||||
|
||||
pub fn new_font(&mut self, font: Font) -> FontId {
|
||||
self.ui.fonts.insert(font)
|
||||
}
|
||||
@ -320,6 +318,7 @@ impl Ui {
|
||||
let mut mesh = Mesh::new();
|
||||
|
||||
// TODO: this could be removed entirely if the draw call just used both textures
|
||||
// however this allows for flexibility if we want to interleave other draw calls later
|
||||
enum State {
|
||||
Image,
|
||||
Plain,
|
||||
@ -396,6 +395,14 @@ impl Ui {
|
||||
use conrod_core::render::PrimitiveKind;
|
||||
match kind {
|
||||
PrimitiveKind::Image { image_id, color, source_rect } => {
|
||||
let graphic_id = self.image_map.get(&image_id).expect("Image does not exist in image map");
|
||||
let (graphic_cache, cache_tex) = self.cache.graphic_cache_mut_and_tex();
|
||||
|
||||
match graphic_cache.get_graphic(*graphic_id) {
|
||||
Some(Graphic::Blank) | None => continue,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// Switch to the `Image` state for this image if we're not in it already.
|
||||
if let State::Plain = current_state {
|
||||
self.draw_commands.push(DrawCommand::plain(renderer.create_model(&mesh).unwrap()));
|
||||
@ -405,7 +412,6 @@ impl Ui {
|
||||
|
||||
let color = srgb_to_linear(color.unwrap_or(conrod_core::color::WHITE).to_fsa());
|
||||
|
||||
let (graphic_cache, cache_tex) = self.cache.graphic_cache_mut_and_tex();
|
||||
|
||||
let resolution = Vec2::new(
|
||||
(rect.w() * p_scale_factor) as u16,
|
||||
@ -429,7 +435,6 @@ impl Ui {
|
||||
max: Vec2::new(uv_r, uv_t),
|
||||
}
|
||||
};
|
||||
let graphic_id = self.image_map.get(&image_id).expect("Image does not exist in image map");
|
||||
let (cache_w, cache_h) = cache_tex.get_dimensions().map(|e| e as f32).into_tuple();
|
||||
|
||||
// Cache graphic at particular resolution
|
||||
|
@ -15,54 +15,43 @@ use common::{
|
||||
use vek::*;
|
||||
|
||||
|
||||
trait Shader {
|
||||
type VertExtra;
|
||||
type VsOut: Clone + Interpolate;
|
||||
fn vert(&self, v_color: Rgba<f32>, v_pos: Vec3<f32>, vert_extra: &Self::VertExtra) -> (Vec3<f32>, Self::VsOut);
|
||||
fn frag(&self, vs_out: &Self::VsOut) -> Rgba<f32>;
|
||||
}
|
||||
|
||||
struct Voxel<S> where S: Shader {
|
||||
struct Voxel {
|
||||
mvp: Mat4<f32>,
|
||||
shader: S,
|
||||
}
|
||||
|
||||
struct SimpleShader;
|
||||
impl Shader for SimpleShader {
|
||||
type VertExtra = ();
|
||||
#[derive(Copy, Clone)]
|
||||
struct Vert {
|
||||
pos: Vec3<f32>,
|
||||
col: Rgb<f32>,
|
||||
norm: Vec3<f32>,
|
||||
ao_level: u8,
|
||||
}
|
||||
impl Vert {
|
||||
fn new(pos: Vec3<f32>, col: Rgb<f32>, norm: Vec3<f32>, ao_level: u8) -> Self {
|
||||
Vert {
|
||||
pos,
|
||||
col,
|
||||
norm,
|
||||
ao_level,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Pipeline for Voxel {
|
||||
type Vertex = Vert;
|
||||
type VsOut = Rgba<f32>;
|
||||
fn vert(&self, v_color: Rgba<f32>, v_pos: Vec3<f32>, _: &Self::VertExtra) -> (Vec3<f32>, Self::VsOut) {
|
||||
(
|
||||
v_pos,
|
||||
v_color,
|
||||
)
|
||||
}
|
||||
fn frag(&self, vs_out: &Self::VsOut) -> Rgba<f32> {
|
||||
*vs_out
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, S> Pipeline for Voxel<S> where S: Shader {
|
||||
type Vertex = (Vec3<f32>, Rgb<f32>, S::VertExtra);
|
||||
type VsOut = S::VsOut;
|
||||
type Pixel = [u8; 4];
|
||||
|
||||
#[inline(always)]
|
||||
fn vert(&self, (v_pos, v_color, v_extra): &Self::Vertex) -> ([f32; 3], Self::VsOut) {
|
||||
let (pos, out) = self.shader.vert(
|
||||
srgb_to_linear(Rgba::from_opaque(*v_color)),
|
||||
Vec3::from(self.mvp * Vec4::from_point(*v_pos)),
|
||||
v_extra,
|
||||
);
|
||||
(
|
||||
pos.into_array(),
|
||||
out,
|
||||
)
|
||||
fn vert(&self, Vert { pos, col, norm, ao_level}: &Self::Vertex) -> ([f32; 3], Self::VsOut) {
|
||||
let light = Rgba::from_opaque(Rgb::from(*ao_level as f32 / 4.0 + 0.25));
|
||||
let color = light * srgb_to_linear(Rgba::from_opaque(*col));
|
||||
let position = Vec3::from(self.mvp * Vec4::from_point(*pos)).into_array();
|
||||
(position, color)
|
||||
}
|
||||
#[inline(always)]
|
||||
fn frag(&self, vs_out: &Self::VsOut) -> Self::Pixel {
|
||||
let color = self.shader.frag(vs_out);
|
||||
linear_to_srgb(color).map(|e| (e * 255.0) as u8).into_array()
|
||||
fn frag(&self, color: &Self::VsOut) -> Self::Pixel {
|
||||
linear_to_srgb(*color).map(|e| (e * 255.0) as u8).into_array()
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,14 +60,17 @@ pub fn draw_vox(segment: &Segment, output_size: Vec2<u16>) -> Vec<[u8; 4]> {
|
||||
let mut color = Buffer2d::new(dims, [50; 4]);
|
||||
let mut depth = Buffer2d::new(dims, 1.0);
|
||||
|
||||
let (w, h, d) = segment.get_size().map(|e| e as f32).into_tuple();
|
||||
|
||||
let mvp =
|
||||
Mat4::rotation_y(0.6) *
|
||||
Mat4::<f32>::scaling_3d(1.0 / 14.0) *
|
||||
Mat4::translation_2d([-14.0, -14.0]) *
|
||||
Mat4::rotation_x(-std::f32::consts::PI / 2.0 );
|
||||
Mat4::<f32>::orthographic_rh_no(FrustumPlanes {
|
||||
left: -1.0, right: 1.0, bottom: -1.0, top: 1.0,
|
||||
near: 0.0, far: 1.0
|
||||
}) *
|
||||
Mat4::scaling_3d(2.0 / w.max(h)) *
|
||||
Mat4::translation_3d([-w / 2.0, -h / 2.0, -d / 2.0]);
|
||||
Voxel {
|
||||
mvp,
|
||||
shader: SimpleShader,
|
||||
}
|
||||
.draw::<rasterizer::Triangles<_>, _>(
|
||||
&generate_mesh(segment, Vec3::from(0.0)),
|
||||
@ -90,25 +82,46 @@ pub fn draw_vox(segment: &Segment, output_size: Vec2<u16>) -> Vec<[u8; 4]> {
|
||||
color.as_ref().to_vec()
|
||||
}
|
||||
|
||||
type Vert = <Voxel<SimpleShader> as Pipeline>::Vertex;
|
||||
|
||||
// TODO: generalise meshing code
|
||||
fn ao_level(side1: bool, corner: bool, side2: bool) -> u8 {
|
||||
if side1 && side2 {
|
||||
0
|
||||
} else {
|
||||
3 - [side1, corner, side2].iter().filter(|e| **e).count() as u8
|
||||
}
|
||||
}
|
||||
// TODO: generalize meshing code....
|
||||
fn create_quad(
|
||||
origin: Vec3<f32>,
|
||||
unit_x: Vec3<f32>,
|
||||
unit_y: Vec3<f32>,
|
||||
//norm: Vec3<f32>,
|
||||
norm: Vec3<f32>,
|
||||
col: Rgb<f32>,
|
||||
occluders: [bool; 8],
|
||||
) -> [Vert; 6] {
|
||||
let a = (origin, col, ());
|
||||
let b = (origin + unit_x, col, ());
|
||||
let c = (origin + unit_x + unit_y, col, ());
|
||||
let d = (origin + unit_y, col, ());
|
||||
|
||||
let a_ao = ao_level(occluders[0], occluders[1], occluders[2]);
|
||||
let b_ao = ao_level(occluders[2], occluders[3], occluders[4]);
|
||||
let c_ao = ao_level(occluders[4], occluders[5], occluders[6]);
|
||||
let d_ao = ao_level(occluders[6], occluders[7], occluders[0]);
|
||||
|
||||
let a = Vert::new(origin, col, norm, a_ao);
|
||||
let b = Vert::new(origin + unit_x, col, norm, b_ao);
|
||||
let c = Vert::new(origin + unit_x + unit_y, col, norm, c_ao);
|
||||
let d = Vert::new(origin + unit_y, col, norm, d_ao);
|
||||
|
||||
// Flip to fix anisotropy
|
||||
let (a, b, c, d) = if a_ao + c_ao > b_ao + d_ao {
|
||||
(d, a, b, c)
|
||||
} else {
|
||||
(a, b, c, d)
|
||||
};
|
||||
|
||||
[
|
||||
a, b, c, // Tri 1
|
||||
c, d, a, // Tri 2
|
||||
]
|
||||
}
|
||||
|
||||
fn generate_mesh(segment: &Segment, offs: Vec3<f32>) -> Vec<Vert> {
|
||||
let mut vertices = Vec::new();
|
||||
|
||||
@ -120,82 +133,120 @@ fn generate_mesh(segment: &Segment, offs: Vec3<f32>) -> Vec<Vert> {
|
||||
{
|
||||
let col = col.map(|e| e as f32 / 255.0);
|
||||
|
||||
let is_empty = |pos| {
|
||||
segment.get(pos)
|
||||
.map(|v| v.is_empty())
|
||||
.unwrap_or(true)
|
||||
};
|
||||
|
||||
let occluders = |unit_x, unit_y, dir| {
|
||||
// would be nice to generate unit_x and unit_y from a given direction
|
||||
[
|
||||
!is_empty(pos + dir - unit_x),
|
||||
!is_empty(pos + dir - unit_x - unit_y),
|
||||
!is_empty(pos + dir - unit_y),
|
||||
!is_empty(pos + dir + unit_x - unit_y),
|
||||
!is_empty(pos + dir + unit_x),
|
||||
!is_empty(pos + dir + unit_x + unit_y),
|
||||
!is_empty(pos + dir + unit_y),
|
||||
!is_empty(pos + dir - unit_x + unit_y),
|
||||
]
|
||||
};
|
||||
|
||||
// -x
|
||||
if segment.get(pos - Vec3::unit_x())
|
||||
.map(|v| v.is_empty())
|
||||
.unwrap_or(true)
|
||||
if is_empty(pos - Vec3::unit_x())
|
||||
{
|
||||
vertices.extend_from_slice(&create_quad(
|
||||
offs + pos.map(|e| e as f32) + Vec3::unit_y(),
|
||||
-Vec3::unit_y(),
|
||||
Vec3::unit_z(),
|
||||
//-Vec3::unit_x(),
|
||||
-Vec3::unit_x(),
|
||||
col,
|
||||
occluders(
|
||||
-Vec3::unit_y(),
|
||||
Vec3::unit_z(),
|
||||
-Vec3::unit_x(),
|
||||
),
|
||||
));
|
||||
}
|
||||
// +x
|
||||
if segment.get(pos + Vec3::unit_x())
|
||||
.map(|v| v.is_empty())
|
||||
.unwrap_or(true)
|
||||
if is_empty(pos + Vec3::unit_x())
|
||||
{
|
||||
vertices.extend_from_slice(&create_quad(
|
||||
vertices.extend_from_slice(&create_quad(
|
||||
offs + pos.map(|e| e as f32) + Vec3::unit_x(),
|
||||
Vec3::unit_y(),
|
||||
Vec3::unit_z(),
|
||||
//Vec3::unit_x(),
|
||||
Vec3::unit_x(),
|
||||
col,
|
||||
occluders(
|
||||
Vec3::unit_y(),
|
||||
Vec3::unit_z(),
|
||||
Vec3::unit_x(),
|
||||
),
|
||||
));
|
||||
}
|
||||
// -y
|
||||
if segment.get(pos - Vec3::unit_y())
|
||||
.map(|v| v.is_empty())
|
||||
.unwrap_or(true)
|
||||
if is_empty(pos - Vec3::unit_y())
|
||||
{
|
||||
vertices.extend_from_slice(&create_quad(
|
||||
vertices.extend_from_slice(&create_quad(
|
||||
offs + pos.map(|e| e as f32),
|
||||
Vec3::unit_x(),
|
||||
Vec3::unit_z(),
|
||||
//-Vec3::unit_y(),
|
||||
-Vec3::unit_y(),
|
||||
col,
|
||||
occluders(
|
||||
Vec3::unit_x(),
|
||||
Vec3::unit_z(),
|
||||
-Vec3::unit_y(),
|
||||
),
|
||||
));
|
||||
}
|
||||
// +y
|
||||
if segment.get(pos + Vec3::unit_y())
|
||||
.map(|v| v.is_empty())
|
||||
.unwrap_or(true)
|
||||
if is_empty(pos + Vec3::unit_y())
|
||||
{
|
||||
vertices.extend_from_slice(&create_quad(
|
||||
vertices.extend_from_slice(&create_quad(
|
||||
offs + pos.map(|e| e as f32) + Vec3::unit_y(),
|
||||
Vec3::unit_z(),
|
||||
Vec3::unit_x(),
|
||||
//Vec3::unit_y(),
|
||||
Vec3::unit_y(),
|
||||
col,
|
||||
occluders(
|
||||
Vec3::unit_z(),
|
||||
Vec3::unit_x(),
|
||||
Vec3::unit_y(),
|
||||
),
|
||||
));
|
||||
}
|
||||
// -z
|
||||
if segment.get(pos - Vec3::unit_z())
|
||||
.map(|v| v.is_empty())
|
||||
.unwrap_or(true)
|
||||
if is_empty(pos - Vec3::unit_z())
|
||||
{
|
||||
vertices.extend_from_slice(&create_quad(
|
||||
vertices.extend_from_slice(&create_quad(
|
||||
offs + pos.map(|e| e as f32),
|
||||
Vec3::unit_y(),
|
||||
Vec3::unit_x(),
|
||||
//-Vec3::unit_z(),
|
||||
-Vec3::unit_z(),
|
||||
col,
|
||||
occluders(
|
||||
Vec3::unit_y(),
|
||||
Vec3::unit_x(),
|
||||
-Vec3::unit_z(),
|
||||
),
|
||||
));
|
||||
}
|
||||
// +z
|
||||
if segment.get(pos + Vec3::unit_z())
|
||||
.map(|v| v.is_empty())
|
||||
.unwrap_or(true)
|
||||
if is_empty(pos + Vec3::unit_z())
|
||||
{
|
||||
vertices.extend_from_slice(&create_quad(
|
||||
vertices.extend_from_slice(&create_quad(
|
||||
offs + pos.map(|e| e as f32) + Vec3::unit_z(),
|
||||
Vec3::unit_x(),
|
||||
Vec3::unit_y(),
|
||||
//Vec3::unit_z(),
|
||||
Vec3::unit_z(),
|
||||
col,
|
||||
occluders(
|
||||
Vec3::unit_x(),
|
||||
Vec3::unit_y(),
|
||||
Vec3::unit_z(),
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -206,23 +257,15 @@ fn generate_mesh(segment: &Segment, offs: Vec3<f32>) -> Vec<Vert> {
|
||||
|
||||
// TODO: put these in utility a module
|
||||
#[inline(always)]
|
||||
fn to_linear(x: f32) -> f32 {
|
||||
if x <= 0.04045 {
|
||||
x / 12.92
|
||||
} else {
|
||||
((x + 0.055) / 1.055).powf(2.4)
|
||||
}
|
||||
}
|
||||
#[inline(always)]
|
||||
fn to_srgb(x: f32) -> f32 {
|
||||
if x <= 0.0031308 {
|
||||
x * 12.92
|
||||
} else {
|
||||
x.powf(1.0 / 2.4) * 1.055 - 0.055
|
||||
}
|
||||
}
|
||||
#[inline(always)]
|
||||
fn srgb_to_linear(c: Rgba<f32>) -> Rgba<f32> {
|
||||
#[inline(always)]
|
||||
fn to_linear(x: f32) -> f32 {
|
||||
if x <= 0.04045 {
|
||||
x / 12.92
|
||||
} else {
|
||||
((x + 0.055) / 1.055).powf(2.4)
|
||||
}
|
||||
}
|
||||
Rgba {
|
||||
r: to_linear(c.r),
|
||||
g: to_linear(c.g),
|
||||
@ -232,6 +275,14 @@ fn srgb_to_linear(c: Rgba<f32>) -> Rgba<f32> {
|
||||
}
|
||||
#[inline(always)]
|
||||
fn linear_to_srgb(c: Rgba<f32>) -> Rgba<f32> {
|
||||
#[inline(always)]
|
||||
fn to_srgb(x: f32) -> f32 {
|
||||
if x <= 0.0031308 {
|
||||
x * 12.92
|
||||
} else {
|
||||
x.powf(1.0 / 2.4) * 1.055 - 0.055
|
||||
}
|
||||
}
|
||||
Rgba {
|
||||
r: to_srgb(c.r),
|
||||
g: to_srgb(c.g),
|
||||
|
Loading…
Reference in New Issue
Block a user