diff --git a/voxygen/src/render/pipelines/ui.rs b/voxygen/src/render/pipelines/ui.rs index 0f3a3b4800..0c2147c667 100644 --- a/voxygen/src/render/pipelines/ui.rs +++ b/voxygen/src/render/pipelines/ui.rs @@ -65,13 +65,13 @@ impl Mode { } } -pub fn create_quad(rect: Aabr, uv_rect: Aabr, color: [f32; 4], mode: Mode) -> Quad { +pub fn create_quad(rect: Aabr, uv_rect: Aabr, color: Rgba, mode: Mode) -> Quad { let mode_val = mode.value(); let v = |pos, uv| { Vertex { pos, uv, - color, + color: color.into_array(), mode: mode_val, } }; @@ -90,13 +90,13 @@ pub fn create_quad(rect: Aabr, uv_rect: Aabr, color: [f32; 4], mode: M ) } -pub fn create_tri(tri: [[f32; 2]; 3], uv_tri: [[f32; 2]; 3], color: [f32; 4], mode: Mode) -> Tri { +pub fn create_tri(tri: [[f32; 2]; 3], uv_tri: [[f32; 2]; 3], color: Rgba, mode: Mode) -> Tri { let mode_val = mode.value(); let v = |pos, uv| { Vertex { pos, uv, - color, + color: color.into_array(), mode: mode_val, } }; diff --git a/voxygen/src/ui/graphic.rs b/voxygen/src/ui/graphic/graphic.rs similarity index 62% rename from voxygen/src/ui/graphic.rs rename to voxygen/src/ui/graphic/graphic.rs index 0affe2012f..0a53580a67 100644 --- a/voxygen/src/ui/graphic.rs +++ b/voxygen/src/ui/graphic/graphic.rs @@ -1,11 +1,7 @@ use common::figure::Segment; -use image::DynamicImage; -use guillotiere::{ - AtlasAllocator, - Allocation, - size2, -}; use fnv::FnvHashMap; +use guillotiere::{size2, Allocation, AtlasAllocator}; +use image::DynamicImage; use vek::*; pub enum Graphic { @@ -45,14 +41,30 @@ impl GraphicCache { pub fn get_graphic(&self, id: Id) -> Option<&Graphic> { self.graphic_map.get(&id) } - pub fn cache_res(&mut self, graphic_id: Id, dims: Vec2, source: Aabr, mut cacher: F) -> Option> where F: FnMut(Aabr, 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 + pub fn cache_res( + &mut self, + graphic_id: Id, + dims: Vec2, + source: Aabr, + mut cacher: F, + ) -> Option> + where + F: FnMut(Aabr, 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), None => match self.graphic_map.get(&graphic_id) { Some(graphic) => { // Allocate rectangle - let aabr = match self.atlas.allocate(size2(i32::from(dims.x + 2), i32::from(dims.y + 2))) { - Some(Allocation{id, rectangle}) => { + let aabr = match self + .atlas + .allocate(size2(i32::from(dims.x + 2), i32::from(dims.y + 2))) + { + Some(Allocation { id, rectangle }) => { let (min, max) = (rectangle.min, rectangle.max); Aabr { min: Vec2::new(min.x as u16 + 1, min.y as u16 + 1), @@ -67,16 +79,18 @@ impl GraphicCache { // Render image // TODO: use source let data = match graphic { - Graphic::Image(ref image) => { - image - .resize_exact(u32::from(aabr.size().w), u32::from(aabr.size().h), image::FilterType::Nearest) - .to_rgba() - .pixels() - .map(|p| p.data) - .collect::>() - } + Graphic::Image(ref image) => image + .resize_exact( + u32::from(aabr.size().w), + u32::from(aabr.size().h), + image::FilterType::Nearest, + ) + .to_rgba() + .pixels() + .map(|p| p.data) + .collect::>(), Graphic::Voxel(segment) => { - super::veuc::draw_vox(&segment, aabr.size().into()) + super::renderer::draw_vox(&segment, aabr.size().into()) } Graphic::Blank => return None, }; @@ -85,13 +99,14 @@ impl GraphicCache { cacher(aabr, data); // Insert area into map for retrieval - self.rect_map.insert((graphic_id, dims, source.map(|e| e.to_bits())), aabr); + self.rect_map + .insert((graphic_id, dims, source.map(|e| e.to_bits())), aabr); // Return area Some(aabr) } None => None, - } + }, } } -} \ No newline at end of file +} diff --git a/voxygen/src/ui/graphic/mod.rs b/voxygen/src/ui/graphic/mod.rs new file mode 100644 index 0000000000..a7b96f903f --- /dev/null +++ b/voxygen/src/ui/graphic/mod.rs @@ -0,0 +1,4 @@ +mod graphic; +mod renderer; + +pub use graphic::{Graphic, GraphicCache, Id}; diff --git a/voxygen/src/ui/veuc.rs b/voxygen/src/ui/graphic/renderer.rs similarity index 61% rename from voxygen/src/ui/veuc.rs rename to voxygen/src/ui/graphic/renderer.rs index 6f89dae2fd..36aecf47f4 100644 --- a/voxygen/src/ui/veuc.rs +++ b/voxygen/src/ui/graphic/renderer.rs @@ -1,20 +1,11 @@ -use euc::{ - Pipeline, - rasterizer, - buffer::Buffer2d, - Interpolate, -}; +use super::super::{linear_to_srgb, srgb_to_linear}; use common::{ figure::Segment, - vol::{ - Vox, - SizedVol, - ReadVol, - }, + vol::{ReadVol, SizedVol, Vox}, }; +use euc::{buffer::Buffer2d, rasterizer, Pipeline}; use vek::*; - struct Voxel { mvp: Mat4, } @@ -43,15 +34,25 @@ impl<'a> Pipeline for Voxel { type Pixel = [u8; 4]; #[inline(always)] - 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)); + 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, color: &Self::VsOut) -> Self::Pixel { - linear_to_srgb(*color).map(|e| (e * 255.0) as u8).into_array() + linear_to_srgb(*color) + .map(|e| (e * 255.0) as u8) + .into_array() } } @@ -62,17 +63,16 @@ pub fn draw_vox(segment: &Segment, output_size: Vec2) -> Vec<[u8; 4]> { let (w, h, d) = segment.get_size().map(|e| e as f32).into_tuple(); - let mvp = - Mat4::::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, - } - .draw::, _>( + let mvp = Mat4::::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 }.draw::, _>( &generate_mesh(segment, Vec3::from(0.0)), &mut color, &mut depth, @@ -98,7 +98,6 @@ fn create_quad( col: Rgb, occluders: [bool; 8], ) -> [Vert; 6] { - 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]); @@ -126,18 +125,10 @@ fn generate_mesh(segment: &Segment, offs: Vec3) -> Vec { let mut vertices = Vec::new(); for pos in segment.iter_positions() { - if let Some(col) = segment - .get(pos) - .ok() - .and_then(|vox| vox.get_color()) - { + if let Some(col) = segment.get(pos).ok().and_then(|vox| vox.get_color()) { 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 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 @@ -154,99 +145,69 @@ fn generate_mesh(segment: &Segment, offs: Vec3) -> Vec { }; // -x - if is_empty(pos - Vec3::unit_x()) - { + 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(), col, - occluders( - -Vec3::unit_y(), - Vec3::unit_z(), - -Vec3::unit_x(), - ), + occluders(-Vec3::unit_y(), Vec3::unit_z(), -Vec3::unit_x()), )); } // +x - if is_empty(pos + Vec3::unit_x()) - { + if is_empty(pos + Vec3::unit_x()) { 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(), col, - occluders( - Vec3::unit_y(), - Vec3::unit_z(), - Vec3::unit_x(), - ), + occluders(Vec3::unit_y(), Vec3::unit_z(), Vec3::unit_x()), )); } // -y - if is_empty(pos - Vec3::unit_y()) - { + if is_empty(pos - Vec3::unit_y()) { vertices.extend_from_slice(&create_quad( offs + pos.map(|e| e as f32), Vec3::unit_x(), Vec3::unit_z(), -Vec3::unit_y(), col, - occluders( - Vec3::unit_x(), - Vec3::unit_z(), - -Vec3::unit_y(), - ), + occluders(Vec3::unit_x(), Vec3::unit_z(), -Vec3::unit_y()), )); } // +y - if is_empty(pos + Vec3::unit_y()) - { + if is_empty(pos + Vec3::unit_y()) { 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(), col, - occluders( - Vec3::unit_z(), - Vec3::unit_x(), - Vec3::unit_y(), - ), + occluders(Vec3::unit_z(), Vec3::unit_x(), Vec3::unit_y()), )); } // -z - if is_empty(pos - Vec3::unit_z()) - { + if is_empty(pos - Vec3::unit_z()) { vertices.extend_from_slice(&create_quad( offs + pos.map(|e| e as f32), Vec3::unit_y(), Vec3::unit_x(), -Vec3::unit_z(), col, - occluders( - Vec3::unit_y(), - Vec3::unit_x(), - -Vec3::unit_z(), - ), + occluders(Vec3::unit_y(), Vec3::unit_x(), -Vec3::unit_z()), )); } // +z - if is_empty(pos + Vec3::unit_z()) - { + if is_empty(pos + Vec3::unit_z()) { 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(), col, - occluders( - Vec3::unit_x(), - Vec3::unit_y(), - Vec3::unit_z(), - ), + occluders(Vec3::unit_x(), Vec3::unit_y(), Vec3::unit_z()), )); } } @@ -254,39 +215,3 @@ fn generate_mesh(segment: &Segment, offs: Vec3) -> Vec { vertices } - -// TODO: put these in utility a module -#[inline(always)] -fn srgb_to_linear(c: Rgba) -> Rgba { - #[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), - b: to_linear(c.b), - a: c.a, - } -} -#[inline(always)] -fn linear_to_srgb(c: Rgba) -> Rgba { - #[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), - b: to_srgb(c.b), - a: c.a, - } -} \ No newline at end of file diff --git a/voxygen/src/ui/mod.rs b/voxygen/src/ui/mod.rs index f91c83934a..2a20caaae1 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -1,15 +1,15 @@ mod widgets; mod graphic; -mod veuc; +mod util; pub use widgets::toggle_button::ToggleButton; pub use graphic::Graphic; +pub(self) use util::{srgb_to_linear, linear_to_srgb}; use graphic::{ GraphicCache, Id as GraphicId, }; -use image::DynamicImage; use conrod_core::{ Ui as CrUi, UiBuilder, @@ -23,7 +23,7 @@ use conrod_core::{ widget::{Id as WidgId, id::Generator}, render::Primitive, event::Input, - input::{touch::Touch, Widget, Motion, Button, MouseButton}, + input::{touch::Touch, Widget, Motion, Button}, }; use vek::*; use crate::{ @@ -410,7 +410,7 @@ impl Ui { current_state = State::Image; } - let color = srgb_to_linear(color.unwrap_or(conrod_core::color::WHITE).to_fsa()); + let color = srgb_to_linear(color.unwrap_or(conrod_core::color::WHITE).to_fsa().into()); let resolution = Vec2::new( @@ -481,7 +481,7 @@ impl Ui { renderer.update_texture(cache_tex, offset, size, &new_data); }).unwrap(); - let color = srgb_to_linear(color.to_fsa()); + let color = srgb_to_linear(color.to_fsa().into()); for g in positioned_glyphs { if let Ok(Some((uv_rect, screen_rect))) = glyph_cache.rect_for(font_id.index(), g) { @@ -509,7 +509,7 @@ impl Ui { } } PrimitiveKind::Rectangle { color } => { - let color = srgb_to_linear(color.to_fsa()); + let color = srgb_to_linear(color.to_fsa().into()); // Don't draw a transparent rectangle if color[3] == 0.0 { continue; @@ -529,7 +529,7 @@ impl Ui { } PrimitiveKind::TrianglesSingleColor { color, triangles } => { // Don't draw transparent triangle or switch state if there are actually no triangles - let color: [f32; 4] = srgb_to_linear(color.into()); + let color = srgb_to_linear(Rgba::from(Into::<[f32; 4]>::into(color))); if triangles.is_empty() || color[3] == 0.0 { continue; } @@ -561,9 +561,10 @@ impl Ui { } _ => {} - // TODO: Add these - //PrimitiveKind::Other {..} => {println!("primitive kind other with id {:?}", id);} + // TODO: Add this //PrimitiveKind::TrianglesMultiColor {..} => {println!("primitive kind multicolor with id {:?}", id);} + // Other uneeded for now + //PrimitiveKind::Other {..} => {println!("primitive kind other with id {:?}", id);} } } // Enter the final command @@ -612,16 +613,4 @@ fn default_scissor(renderer: &mut Renderer) -> Aabr { min: Vec2 { x: 0, y: 0 }, max: Vec2 { x: screen_w, y: screen_h } } -} - -fn srgb_to_linear(color: [f32; 4]) -> [f32; 4] { - fn linearize(comp: f32) -> f32 { - if comp <= 0.04045 { - comp / 12.92 - } else { - ((comp + 0.055) / 1.055).powf(2.4) - } - } - - [linearize(color[0]), linearize(color[1]), linearize(color[2]), color[3]] -} +} \ No newline at end of file diff --git a/voxygen/src/ui/util.rs b/voxygen/src/ui/util.rs new file mode 100644 index 0000000000..6359ddd8dd --- /dev/null +++ b/voxygen/src/ui/util.rs @@ -0,0 +1,36 @@ +use vek::*; + +#[inline(always)] +pub fn srgb_to_linear(c: Rgba) -> Rgba { + #[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), + b: to_linear(c.b), + a: c.a, + } +} +#[inline(always)] +pub fn linear_to_srgb(c: Rgba) -> Rgba { + #[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), + b: to_srgb(c.b), + a: c.a, + } +}