rearrange ui graphic code

Former-commit-id: d0ea7feee59a1daf4ad93e9b9224750deb75ee45
This commit is contained in:
Imbris
2019-04-19 14:55:38 -04:00
parent 3f6855d12d
commit 43aaef75b4
6 changed files with 132 additions and 163 deletions

View File

@ -65,13 +65,13 @@ impl Mode {
} }
} }
pub fn create_quad(rect: Aabr<f32>, uv_rect: Aabr<f32>, color: [f32; 4], mode: Mode) -> Quad<UiPipeline> { pub fn create_quad(rect: Aabr<f32>, uv_rect: Aabr<f32>, color: Rgba<f32>, mode: Mode) -> Quad<UiPipeline> {
let mode_val = mode.value(); let mode_val = mode.value();
let v = |pos, uv| { let v = |pos, uv| {
Vertex { Vertex {
pos, pos,
uv, uv,
color, color: color.into_array(),
mode: mode_val, mode: mode_val,
} }
}; };
@ -90,13 +90,13 @@ pub fn create_quad(rect: Aabr<f32>, uv_rect: Aabr<f32>, color: [f32; 4], mode: M
) )
} }
pub fn create_tri(tri: [[f32; 2]; 3], uv_tri: [[f32; 2]; 3], color: [f32; 4], mode: Mode) -> Tri<UiPipeline> { pub fn create_tri(tri: [[f32; 2]; 3], uv_tri: [[f32; 2]; 3], color: Rgba<f32>, mode: Mode) -> Tri<UiPipeline> {
let mode_val = mode.value(); let mode_val = mode.value();
let v = |pos, uv| { let v = |pos, uv| {
Vertex { Vertex {
pos, pos,
uv, uv,
color, color: color.into_array(),
mode: mode_val, mode: mode_val,
} }
}; };

View File

@ -1,11 +1,7 @@
use common::figure::Segment; use common::figure::Segment;
use image::DynamicImage;
use guillotiere::{
AtlasAllocator,
Allocation,
size2,
};
use fnv::FnvHashMap; use fnv::FnvHashMap;
use guillotiere::{size2, Allocation, AtlasAllocator};
use image::DynamicImage;
use vek::*; use vek::*;
pub enum Graphic { pub enum Graphic {
@ -45,14 +41,30 @@ impl GraphicCache {
pub fn get_graphic(&self, id: Id) -> Option<&Graphic> { pub fn get_graphic(&self, id: Id) -> Option<&Graphic> {
self.graphic_map.get(&id) 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]>) { pub fn cache_res<F>(
match self.rect_map.get(&(graphic_id, dims, source.map(|e| e.to_bits()))) { //<-------- TODO: Replace this with rounded representation of source &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), Some(aabr) => Some(*aabr),
None => match self.graphic_map.get(&graphic_id) { None => match self.graphic_map.get(&graphic_id) {
Some(graphic) => { Some(graphic) => {
// Allocate rectangle // Allocate rectangle
let aabr = match self.atlas.allocate(size2(i32::from(dims.x + 2), i32::from(dims.y + 2))) { let aabr = match self
Some(Allocation{id, rectangle}) => { .atlas
.allocate(size2(i32::from(dims.x + 2), i32::from(dims.y + 2)))
{
Some(Allocation { id, rectangle }) => {
let (min, max) = (rectangle.min, rectangle.max); let (min, max) = (rectangle.min, rectangle.max);
Aabr { Aabr {
min: Vec2::new(min.x as u16 + 1, min.y as u16 + 1), min: Vec2::new(min.x as u16 + 1, min.y as u16 + 1),
@ -67,16 +79,18 @@ impl GraphicCache {
// Render image // Render image
// TODO: use source // TODO: use source
let data = match graphic { let data = match graphic {
Graphic::Image(ref image) => { Graphic::Image(ref image) => image
image .resize_exact(
.resize_exact(u32::from(aabr.size().w), u32::from(aabr.size().h), image::FilterType::Nearest) u32::from(aabr.size().w),
.to_rgba() u32::from(aabr.size().h),
.pixels() image::FilterType::Nearest,
.map(|p| p.data) )
.collect::<Vec<[u8; 4]>>() .to_rgba()
} .pixels()
.map(|p| p.data)
.collect::<Vec<[u8; 4]>>(),
Graphic::Voxel(segment) => { Graphic::Voxel(segment) => {
super::veuc::draw_vox(&segment, aabr.size().into()) super::renderer::draw_vox(&segment, aabr.size().into())
} }
Graphic::Blank => return None, Graphic::Blank => return None,
}; };
@ -85,13 +99,14 @@ impl GraphicCache {
cacher(aabr, data); cacher(aabr, data);
// Insert area into map for retrieval // 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 // Return area
Some(aabr) Some(aabr)
} }
None => None, None => None,
} },
} }
} }
} }

View File

@ -0,0 +1,4 @@
mod graphic;
mod renderer;
pub use graphic::{Graphic, GraphicCache, Id};

View File

@ -1,20 +1,11 @@
use euc::{ use super::super::{linear_to_srgb, srgb_to_linear};
Pipeline,
rasterizer,
buffer::Buffer2d,
Interpolate,
};
use common::{ use common::{
figure::Segment, figure::Segment,
vol::{ vol::{ReadVol, SizedVol, Vox},
Vox,
SizedVol,
ReadVol,
},
}; };
use euc::{buffer::Buffer2d, rasterizer, Pipeline};
use vek::*; use vek::*;
struct Voxel { struct Voxel {
mvp: Mat4<f32>, mvp: Mat4<f32>,
} }
@ -43,15 +34,25 @@ impl<'a> Pipeline for Voxel {
type Pixel = [u8; 4]; type Pixel = [u8; 4];
#[inline(always)] #[inline(always)]
fn vert(&self, Vert { pos, col, norm, ao_level}: &Self::Vertex) -> ([f32; 3], Self::VsOut) { fn vert(
let light = Rgba::from_opaque(Rgb::from(*ao_level as f32 / 4.0 + 0.25)); &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 color = light * srgb_to_linear(Rgba::from_opaque(*col));
let position = Vec3::from(self.mvp * Vec4::from_point(*pos)).into_array(); let position = Vec3::from(self.mvp * Vec4::from_point(*pos)).into_array();
(position, color) (position, color)
} }
#[inline(always)] #[inline(always)]
fn frag(&self, color: &Self::VsOut) -> Self::Pixel { 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<u16>) -> Vec<[u8; 4]> {
let (w, h, d) = segment.get_size().map(|e| e as f32).into_tuple(); let (w, h, d) = segment.get_size().map(|e| e as f32).into_tuple();
let mvp = let mvp = Mat4::<f32>::orthographic_rh_no(FrustumPlanes {
Mat4::<f32>::orthographic_rh_no(FrustumPlanes { left: -1.0,
left: -1.0, right: 1.0, bottom: -1.0, top: 1.0, right: 1.0,
near: 0.0, far: 1.0 bottom: -1.0,
}) * top: 1.0,
Mat4::scaling_3d(2.0 / w.max(h)) * near: 0.0,
Mat4::translation_3d([-w / 2.0, -h / 2.0, -d / 2.0]); far: 1.0,
Voxel { }) * Mat4::scaling_3d(2.0 / w.max(h))
mvp, * Mat4::translation_3d([-w / 2.0, -h / 2.0, -d / 2.0]);
} Voxel { mvp }.draw::<rasterizer::Triangles<_>, _>(
.draw::<rasterizer::Triangles<_>, _>(
&generate_mesh(segment, Vec3::from(0.0)), &generate_mesh(segment, Vec3::from(0.0)),
&mut color, &mut color,
&mut depth, &mut depth,
@ -98,7 +98,6 @@ fn create_quad(
col: Rgb<f32>, col: Rgb<f32>,
occluders: [bool; 8], occluders: [bool; 8],
) -> [Vert; 6] { ) -> [Vert; 6] {
let a_ao = ao_level(occluders[0], occluders[1], occluders[2]); let a_ao = ao_level(occluders[0], occluders[1], occluders[2]);
let b_ao = ao_level(occluders[2], occluders[3], occluders[4]); let b_ao = ao_level(occluders[2], occluders[3], occluders[4]);
let c_ao = ao_level(occluders[4], occluders[5], occluders[6]); let c_ao = ao_level(occluders[4], occluders[5], occluders[6]);
@ -126,18 +125,10 @@ fn generate_mesh(segment: &Segment, offs: Vec3<f32>) -> Vec<Vert> {
let mut vertices = Vec::new(); let mut vertices = Vec::new();
for pos in segment.iter_positions() { for pos in segment.iter_positions() {
if let Some(col) = segment if let Some(col) = segment.get(pos).ok().and_then(|vox| vox.get_color()) {
.get(pos)
.ok()
.and_then(|vox| vox.get_color())
{
let col = col.map(|e| e as f32 / 255.0); let col = col.map(|e| e as f32 / 255.0);
let is_empty = |pos| { let is_empty = |pos| segment.get(pos).map(|v| v.is_empty()).unwrap_or(true);
segment.get(pos)
.map(|v| v.is_empty())
.unwrap_or(true)
};
let occluders = |unit_x, unit_y, dir| { let occluders = |unit_x, unit_y, dir| {
// would be nice to generate unit_x and unit_y from a given direction // 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<f32>) -> Vec<Vert> {
}; };
// -x // -x
if is_empty(pos - Vec3::unit_x()) 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_y(), offs + pos.map(|e| e as f32) + Vec3::unit_y(),
-Vec3::unit_y(), -Vec3::unit_y(),
Vec3::unit_z(), Vec3::unit_z(),
-Vec3::unit_x(), -Vec3::unit_x(),
col, col,
occluders( occluders(-Vec3::unit_y(), Vec3::unit_z(), -Vec3::unit_x()),
-Vec3::unit_y(),
Vec3::unit_z(),
-Vec3::unit_x(),
),
)); ));
} }
// +x // +x
if is_empty(pos + Vec3::unit_x()) 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(), offs + pos.map(|e| e as f32) + Vec3::unit_x(),
Vec3::unit_y(), Vec3::unit_y(),
Vec3::unit_z(), Vec3::unit_z(),
Vec3::unit_x(), Vec3::unit_x(),
col, col,
occluders( occluders(Vec3::unit_y(), Vec3::unit_z(), Vec3::unit_x()),
Vec3::unit_y(),
Vec3::unit_z(),
Vec3::unit_x(),
),
)); ));
} }
// -y // -y
if is_empty(pos - Vec3::unit_y()) 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), offs + pos.map(|e| e as f32),
Vec3::unit_x(), Vec3::unit_x(),
Vec3::unit_z(), Vec3::unit_z(),
-Vec3::unit_y(), -Vec3::unit_y(),
col, col,
occluders( occluders(Vec3::unit_x(), Vec3::unit_z(), -Vec3::unit_y()),
Vec3::unit_x(),
Vec3::unit_z(),
-Vec3::unit_y(),
),
)); ));
} }
// +y // +y
if is_empty(pos + Vec3::unit_y()) 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(), offs + pos.map(|e| e as f32) + Vec3::unit_y(),
Vec3::unit_z(), Vec3::unit_z(),
Vec3::unit_x(), Vec3::unit_x(),
Vec3::unit_y(), Vec3::unit_y(),
col, col,
occluders( occluders(Vec3::unit_z(), Vec3::unit_x(), Vec3::unit_y()),
Vec3::unit_z(),
Vec3::unit_x(),
Vec3::unit_y(),
),
)); ));
} }
// -z // -z
if is_empty(pos - Vec3::unit_z()) 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), offs + pos.map(|e| e as f32),
Vec3::unit_y(), Vec3::unit_y(),
Vec3::unit_x(), Vec3::unit_x(),
-Vec3::unit_z(), -Vec3::unit_z(),
col, col,
occluders( occluders(Vec3::unit_y(), Vec3::unit_x(), -Vec3::unit_z()),
Vec3::unit_y(),
Vec3::unit_x(),
-Vec3::unit_z(),
),
)); ));
} }
// +z // +z
if is_empty(pos + Vec3::unit_z()) 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(), offs + pos.map(|e| e as f32) + Vec3::unit_z(),
Vec3::unit_x(), Vec3::unit_x(),
Vec3::unit_y(), Vec3::unit_y(),
Vec3::unit_z(), Vec3::unit_z(),
col, col,
occluders( occluders(Vec3::unit_x(), Vec3::unit_y(), Vec3::unit_z()),
Vec3::unit_x(),
Vec3::unit_y(),
Vec3::unit_z(),
),
)); ));
} }
} }
@ -254,39 +215,3 @@ fn generate_mesh(segment: &Segment, offs: Vec3<f32>) -> Vec<Vert> {
vertices vertices
} }
// TODO: put these in utility a module
#[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),
b: to_linear(c.b),
a: c.a,
}
}
#[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),
b: to_srgb(c.b),
a: c.a,
}
}

View File

@ -1,15 +1,15 @@
mod widgets; mod widgets;
mod graphic; mod graphic;
mod veuc; mod util;
pub use widgets::toggle_button::ToggleButton; pub use widgets::toggle_button::ToggleButton;
pub use graphic::Graphic; pub use graphic::Graphic;
pub(self) use util::{srgb_to_linear, linear_to_srgb};
use graphic::{ use graphic::{
GraphicCache, GraphicCache,
Id as GraphicId, Id as GraphicId,
}; };
use image::DynamicImage;
use conrod_core::{ use conrod_core::{
Ui as CrUi, Ui as CrUi,
UiBuilder, UiBuilder,
@ -23,7 +23,7 @@ use conrod_core::{
widget::{Id as WidgId, id::Generator}, widget::{Id as WidgId, id::Generator},
render::Primitive, render::Primitive,
event::Input, event::Input,
input::{touch::Touch, Widget, Motion, Button, MouseButton}, input::{touch::Touch, Widget, Motion, Button},
}; };
use vek::*; use vek::*;
use crate::{ use crate::{
@ -410,7 +410,7 @@ impl Ui {
current_state = State::Image; 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( let resolution = Vec2::new(
@ -481,7 +481,7 @@ impl Ui {
renderer.update_texture(cache_tex, offset, size, &new_data); renderer.update_texture(cache_tex, offset, size, &new_data);
}).unwrap(); }).unwrap();
let color = srgb_to_linear(color.to_fsa()); let color = srgb_to_linear(color.to_fsa().into());
for g in positioned_glyphs { for g in positioned_glyphs {
if let Ok(Some((uv_rect, screen_rect))) = glyph_cache.rect_for(font_id.index(), g) { 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 } => { 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 // Don't draw a transparent rectangle
if color[3] == 0.0 { if color[3] == 0.0 {
continue; continue;
@ -529,7 +529,7 @@ impl Ui {
} }
PrimitiveKind::TrianglesSingleColor { color, triangles } => { PrimitiveKind::TrianglesSingleColor { color, triangles } => {
// Don't draw transparent triangle or switch state if there are actually no 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 { if triangles.is_empty() || color[3] == 0.0 {
continue; continue;
} }
@ -561,9 +561,10 @@ impl Ui {
} }
_ => {} _ => {}
// TODO: Add these // TODO: Add this
//PrimitiveKind::Other {..} => {println!("primitive kind other with id {:?}", id);}
//PrimitiveKind::TrianglesMultiColor {..} => {println!("primitive kind multicolor with id {:?}", id);} //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 // Enter the final command
@ -612,16 +613,4 @@ fn default_scissor(renderer: &mut Renderer) -> Aabr<u16> {
min: Vec2 { x: 0, y: 0 }, min: Vec2 { x: 0, y: 0 },
max: Vec2 { x: screen_w, y: screen_h } 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]]
}

36
voxygen/src/ui/util.rs Normal file
View File

@ -0,0 +1,36 @@
use vek::*;
#[inline(always)]
pub 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),
b: to_linear(c.b),
a: c.a,
}
}
#[inline(always)]
pub 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),
b: to_srgb(c.b),
a: c.a,
}
}