diff --git a/Cargo.toml b/Cargo.toml index 96f41eb..dd3a379 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,6 +51,7 @@ femtovg = "0.9.2" [features] default = ["sdf_font"] +sdfer_use_f64_instead_of_f32 = [] normal_font = [] sdf_font = [] inparser = [] diff --git a/src/camera.rs b/src/camera.rs index dd768a2..b611238 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -33,14 +33,26 @@ impl Camera { self.upward } + pub fn get_center(&self) -> Vec3 { + self.center + } + pub fn set_upward(&mut self, upward: Vec3) { self.upward = upward; } + pub fn set_center(&mut self, center: Vec3) { + self.center = center; + } + pub fn get_view_matrix(&self) -> Mat4x4 { let l = self.center; look_at(&self.pos, &l, &self.upward) } + + pub fn front(&self) -> Vec3 { + self.center - self.pos + } } impl Default for Camera { diff --git a/src/graphics/collections/agg_fast_path.rs b/src/graphics/collections/agg_fast_path.rs index 942283d..0f8b5d1 100644 --- a/src/graphics/collections/agg_fast_path.rs +++ b/src/graphics/collections/agg_fast_path.rs @@ -137,6 +137,15 @@ impl AttaWithBuffer for AggFastPath { config: &::Config, ) -> Result<(Vec, Option>, i32)> { let points = data.iter().map(|v| &v.points).flatten().collect::>(); + + let mut lens = Vec::with_capacity(data.len()); + let mut sum = 0; + for num in data.iter().map(|v| v.len()) { + lens.push(sum); + sum += num; + } + + let point_lens = data.iter().map(|d| d.len()).collect::>(); let mut vbo = Vec::with_capacity(points.len() * 10); for p in points { vbo.extend_from_slice(&[ @@ -145,8 +154,17 @@ impl AttaWithBuffer for AggFastPath { ]); } let mut ebo = vec![]; - for e in data.iter().map(|v| &v.ebo).flatten() { - ebo.extend_from_slice(e); + for (idx, e) in data.iter().map(|v| &v.ebo).enumerate() { + if idx > 0 { + let len = lens[idx - 1] as u32; + for e in e.iter() { + ebo.extend_from_slice(&[e[0] + len, e[1] + len, e[2] + len]); + } + } else { + for e in e.iter() { + ebo.extend_from_slice(e); + } + } } let len = ebo.len() as i32; diff --git a/src/graphics/font/mod.rs b/src/graphics/font/mod.rs index a0a86a6..ef7fac8 100644 --- a/src/graphics/font/mod.rs +++ b/src/graphics/font/mod.rs @@ -147,6 +147,24 @@ impl<'a> Cache<'a> { self.cache.get(&c).unwrap() } + + fn test(&self) { + let mut data = vec![0; 1024 * 1024]; + unsafe { + self.gl + .bind_texture(glow::TEXTURE_2D, Some(self.tex.native())); + self.gl.get_tex_image( + glow::TEXTURE_2D, + 0, + glow::RED, + glow::UNSIGNED_BYTE, + glow::PixelPackData::Slice(&mut data), + ); + self.gl.bind_texture(glow::TEXTURE_2D, None); + } + let img = image::GrayImage::from_raw(1024, 1024, data).unwrap(); + img.save("test.png").unwrap(); + } } #[derive(Clone)] @@ -220,7 +238,7 @@ impl<'a> Text<'a> { let u_fill = self.program.get_uniform_location(&self.gl, "uFill"); unsafe { - self.gl.uniform_4_f32(conf.as_ref(), 5.0, 0.0, 0.0, 0.0); + self.gl.uniform_4_f32(conf.as_ref(), 5.0, 3.0, 0.0, 0.0); self.gl.uniform_1_i32(u_mode.as_ref(), -1); self.gl.uniform_4_f32(u_border.as_ref(), 0.0, 0.0, 0.0, 0.0); self.gl.uniform_4_f32(u_stroke.as_ref(), 1.0, 1.0, 1.0, 1.0); @@ -319,10 +337,10 @@ impl<'a> AttaWithBuffer for Text<'a> { let vbo = gl.create_buffer().unwrap(); gl.bind_buffer(glow::ARRAY_BUFFER, Some(vbo)); gl.enable_vertex_attrib_array(0); - gl.vertex_attrib_pointer_f32(0, 4, glow::FLOAT, false, 32, 0); + gl.vertex_attrib_pointer_f32(0, 4, glow::FLOAT, false, 48, 0); gl.enable_vertex_attrib_array(1); - gl.vertex_attrib_pointer_f32(1, 4, glow::FLOAT, false, 32, 16); + gl.vertex_attrib_pointer_f32(1, 4, glow::FLOAT, false, 48, 16); gl.bind_vertex_array(None); gl.bind_buffer(glow::ARRAY_BUFFER, None); diff --git a/src/graphics/mod.rs b/src/graphics/mod.rs index 848141d..9d3f337 100644 --- a/src/graphics/mod.rs +++ b/src/graphics/mod.rs @@ -3,6 +3,7 @@ pub mod colormap; mod colormesh; pub mod font; pub mod hello; +pub mod plane; pub mod ppi; pub mod threed; pub mod tools; @@ -14,6 +15,7 @@ use crate::{ components::Program, errors::*, graphics::font::FontConfig, + pg::layout_type::ViewPort, ui::{operation::Projection, typ::CameraOP}, }; @@ -125,6 +127,7 @@ pub trait AttachWithMouse { state: &Self::State, camera: &mut Camera, projection: &mut Projection, + viewport: &ViewPort, ) -> bool; fn reset(&mut self); diff --git a/src/graphics/plane.rs b/src/graphics/plane.rs new file mode 100644 index 0000000..27b08a8 --- /dev/null +++ b/src/graphics/plane.rs @@ -0,0 +1,7 @@ +pub struct Plane {} + +impl Plane { + pub fn new() -> Self { + Self {} + } +} diff --git a/src/graphics/threed.rs b/src/graphics/threed.rs index 4308786..8995769 100644 --- a/src/graphics/threed.rs +++ b/src/graphics/threed.rs @@ -5,6 +5,7 @@ use super::transforms::{position::Position, trackball::TrackballModel}; use super::{AttaWithProgram, AttachWithMouse}; use crate::camera::{self, Camera}; use crate::errors::*; +use crate::pg::layout_type::ViewPort; use crate::ui::operation::Projection; use glow::HasContext; use nalgebra_glm::{Mat4, Vec3}; @@ -46,6 +47,7 @@ impl AttachWithMouse for Trackball { state: &Self::State, camera: &mut Camera, projection: &mut Projection, + viewport: &ViewPort, ) -> bool { match state { &super::MouseState::Wheel(delta) => { diff --git a/src/graphics/transforms/mod.rs b/src/graphics/transforms/mod.rs index 3f61e1d..6749378 100644 --- a/src/graphics/transforms/mod.rs +++ b/src/graphics/transforms/mod.rs @@ -1,3 +1,4 @@ +pub mod plane; pub mod polar; pub mod position; pub mod trackball; diff --git a/src/graphics/transforms/plane.rs b/src/graphics/transforms/plane.rs new file mode 100644 index 0000000..91d3f2e --- /dev/null +++ b/src/graphics/transforms/plane.rs @@ -0,0 +1,88 @@ +use crate::components::{CodeType, Program, Snippet}; +use crate::errors::Result; +use crate::graphics::{AttaWithProgram, AttachWithMouse, MouseState}; +use crate::pg::layout_type::ViewPort; + +use glow::HasContext; +use nalgebra::{Matrix4, Quaternion, Translation3, Unit, UnitQuaternion, Vector3}; +use nalgebra_glm::vec3; + +#[derive(Debug, Clone)] +pub struct PlaneTrans {} + +impl AttachWithMouse for PlaneTrans { + type State = MouseState; + + fn attach_with_mouse( + &mut self, + state: &Self::State, + camera: &mut crate::camera::Camera, + projection: &mut crate::ui::operation::Projection, + viewport: &ViewPort, + ) -> bool { + let watch_vec = camera.front(); + let viewport_size = viewport.size(); + let if_vertical = true; + + match state { + MouseState::Drag { from, delta } => { + if if_vertical { + // Radian + let fov = projection.fov().to_radians(); + let aspect = projection.aspect(); + + // Z_near + let z_near = projection.z_near(); + + let h = 2.0 * z_near * (fov / 2.0).tan(); + let w = h * aspect; + + let move_width = (delta[0] * w) / viewport_size[0]; + let move_height = (delta[1] * h) / viewport_size[1]; + + let up = camera.get_upward(); + let right = watch_vec.cross(&up).normalize(); + let _move = move_width * right + move_height * up; + + camera.set_position(camera.get_position() + _move); + camera.set_center(camera.get_center() + _move); + } else { + } + } + MouseState::Wheel(delta) => { + projection.set_fov((projection.fov() - delta).clamp(15.0, 120.0)); + } + _ => {} + } + true + } + + fn init_camera(&self) -> crate::camera::Camera { + crate::camera::Camera::new( + vec3(0.0, 20.0, 0.0), + vec3(0.0, 0.0, 1.0), + vec3(0.0, 0.0, 0.0), + ) + } + + fn reset(&mut self) {} +} + +impl AttaWithProgram for PlaneTrans { + fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result<()> { + unsafe { + let loc = program.get_uniform_location(gl, "trackball_model"); + + let trackball = nalgebra_glm::rotate_x(&nalgebra_glm::identity(), 90.0f32.to_radians()); + + gl.uniform_matrix_4_f32_slice(loc.as_ref(), false, trackball.as_slice()); + } + Ok(()) + } +} + +impl Default for PlaneTrans { + fn default() -> Self { + Self {} + } +} diff --git a/src/graphics/transforms/trackball.rs b/src/graphics/transforms/trackball.rs index 5480d93..b3b1c29 100644 --- a/src/graphics/transforms/trackball.rs +++ b/src/graphics/transforms/trackball.rs @@ -25,7 +25,7 @@ impl TrackballModel { count: 0, model: Matrix4::identity(), renorm_count: 97, - trackball_size: 100.0, + trackball_size: 20.0, x: 0.0, y: 0.0, theta, diff --git a/src/pg/mod.rs b/src/pg/mod.rs index 177b334..ed96f14 100644 --- a/src/pg/mod.rs +++ b/src/pg/mod.rs @@ -11,6 +11,7 @@ use crate::graphics::collections::agg_fast_path::AggFastPath; use crate::graphics::font::Text; use crate::graphics::ppi::PPI; use crate::graphics::threed::Trackball; +use crate::graphics::transforms::plane::PlaneTrans; use crate::graphics::transforms::viewport; use crate::graphics::{AttaWithProgram, AttachWithMouse}; use crate::ui::operation::Operation; @@ -85,7 +86,7 @@ impl<'gl> Programs<'gl> { pub fn draw_modules( &mut self, modules: &mut ModulePackage<'gl>, - operation: &Operation, + operation: &Operation, viewport: &ViewPort, ) -> Result<()> { match &mut modules.modules { diff --git a/src/pg/modules/ppi.rs b/src/pg/modules/ppi.rs index 2b670ce..2522044 100644 --- a/src/pg/modules/ppi.rs +++ b/src/pg/modules/ppi.rs @@ -4,6 +4,7 @@ use font::{FontConfig, LineStyle, PositionText, TextLine}; use glow::HasContext; use std::rc::Rc; use tracker::track; +use transforms::plane::PlaneTrans; use transforms::viewport; use crate::font_manager::{FontSize, FontStyle}; @@ -65,21 +66,39 @@ impl<'b, 'a: 'b> PPIModule<'b, 'a> { config: &PPIModuleConfig, ) -> Result<()> { let config = config.to_line_config(); - // Create the path - let mut path = Path::new(true); - // Will be changed in the future let outskirt = 10.0; - for seg in 0..500 { - let angle = 2f32 * f32::consts::PI / 500.0 * seg as f32; - let x = (angle.cos() * outskirt) as f32; - let y = (angle.sin() * outskirt) as f32; - path.push([x, y, 0.0]); - } - path.finish(); + let mut paths = vec![]; - let (vbo, ebo, len) = self.line_program.bake(&vec![path], &config)?; + for range in 1..=6 { + let r = outskirt / 5.0 * range as f32; + // Create the path + let mut path = Path::new(true); + // Draw the circle + for seg in 0..200 { + let angle = 2f32 * f32::consts::PI / 200.0 * seg as f32; + let x = (angle.cos() * r) as f32; + let y = (angle.sin() * r) as f32; + path.push([x, y, 0.01]); + } + path.finish(); + paths.push(path); + } + + let a = 2.0 * f32::consts::PI / 6.0; + + for _a in 0..7 { + let mut path = Path::new(false); + let x = (a * _a as f32).cos() * outskirt; + let y = (a * _a as f32).sin() * outskirt; + path.push([0.0, 0.0, 0.01]); + path.push([x, y, 0.01]); + path.finish(); + paths.push(path); + } + + let (vbo, ebo, len) = self.line_program.bake(&paths, &config)?; attach.bind_data(&vbo, ebo.as_ref(), len); Ok(()) } @@ -89,12 +108,10 @@ impl<'b, 'a: 'b> PPIModule<'b, 'a> { match font_style { FontConfig::Textline(line_style, font_style) => { - let new_text = TextLine::new("ABC", Some(font_style), None); + let new_text = TextLine::new("Hello,World", Some(font_style), None); let position_text = PositionText::new(new_text, [0.0, 0.0, 0.0], font::Anchor::BottomCenter); - let text_pg_config = config.to_font_config(); - let (vbo, ebo, len) = self.text_program.bake(&position_text, &text_pg_config)?; attach.bind_data(&vbo, ebo.as_ref(), len); } @@ -107,7 +124,8 @@ impl<'b, 'a: 'b> PPIModule<'b, 'a> { impl<'b, 'a: 'b> Module for PPIModule<'b, 'a> { type Cursor = PPIPackage<'a>; type Data = Data; - type Operation = Trackball; + // type Operation = Trackball; + type Operation = PlaneTrans; fn render<'dt>( &mut self, @@ -223,7 +241,7 @@ impl<'b, 'a: 'b> Module for PPIModule<'b, 'a> { // Bind the data self.bind_ppi_pg(&mut ppi_attach, &data.borrow(), &config); self.bind_line_pg(&mut line_attach, &data.borrow(), &config); - self.bind_tick(&mut tick_attach, &data.borrow(), &config); + // self.bind_tick(&mut tick_attach, &data.borrow(), &config); Ok(PPIPackage::new( config, @@ -333,8 +351,8 @@ impl Default for PPIModuleConfig { Self { ticks: true, line_color: [1.0, 1.0, 1.0, 1.0], - line_width: 2.0, - line_antialias: 2.0, + line_width: 1.5, + line_antialias: 0.5, layer: 0, colors: vec![], color_range: [0.0, 0.0], diff --git a/src/shaders/font.rs b/src/shaders/font.rs index 5e128fb..230f048 100644 --- a/src/shaders/font.rs +++ b/src/shaders/font.rs @@ -18,7 +18,6 @@ impl FontVertex { // texcoord (left top, right bottom) layout(location = 0) in vec4 texcoord; - // Relative position (x, y, width, height) layout(location = 1) in vec4 relative_position; @@ -29,7 +28,6 @@ impl FontVertex { void main() { - gl_Position = vec4(0.0, 0.0, 0.0, 1.0); vs_out.texcoord = texcoord; vs_out.pos = relative_position; } @@ -43,6 +41,7 @@ impl FontGeometry { pub fn new() -> Self { let mut transform = Trackball::new().0; let raw = glsl! { + layout(points) in; layout(triangle_strip, max_vertices = 4) out; @@ -55,6 +54,7 @@ impl FontGeometry { uniform vec2 atlas_shape; out vec2 v_texCoord; + out vec2 UV_coord; in VS_OUT { vec4 texcoord; @@ -76,6 +76,10 @@ impl FontGeometry { vec2 tex_coord_lt = gs_in[0].texcoord.xy / atlas_shape; vec2 tex_coord_rb = gs_in[0].texcoord.zw / atlas_shape; + // uv_coord + vec2 uv_coord_lt = gs_in[0].texcoord.xy; + vec2 uv_coord_rb = gs_in[0].texcoord.zw; + // Char Size vec2 size = vec2(width, hgt); @@ -97,19 +101,23 @@ impl FontGeometry { // Emit vertices gl_Position = vec4(ndc_left_top.x, ndc_right_bottom.y, ndc_base_pos.z / ndc_base_pos.w, 1.0); - v_texCoord = vec2(tex_coord_lt.x, tex_coord_lt.y); + v_texCoord = vec2(tex_coord_lt.x, tex_coord_rb.y); + UV_coord = vec2(uv_coord_lt.x, uv_coord_rb.y); EmitVertex(); gl_Position = vec4(ndc_right_bottom.xy, ndc_base_pos.z / ndc_base_pos.w, 1.0); v_texCoord = tex_coord_rb; + UV_coord = uv_coord_rb; EmitVertex(); gl_Position = vec4(ndc_left_top.xy, ndc_base_pos.z / ndc_base_pos.w, 1.0); v_texCoord = tex_coord_lt; + UV_coord = uv_coord_lt; EmitVertex(); gl_Position = vec4(ndc_right_bottom.x, ndc_left_top.y, ndc_base_pos.z / ndc_base_pos.w, 1.0); v_texCoord = vec2(tex_coord_rb.x, tex_coord_lt.y); + UV_coord = vec2(uv_coord_rb.x, uv_coord_lt.y); EmitVertex(); EndPrimitive(); @@ -128,6 +136,7 @@ impl FontFragment { let raw = glsl! { uniform sampler2D atlas_data; in vec2 v_texCoord; + in vec2 UV_coord; uniform vec4 uClipUV; uniform vec4 uSdfConfig; @@ -161,20 +170,14 @@ impl FontFragment { vec4 fillColor = uFill; vec4 strokeColor = uStroke; - float scale = getUVScale(v_texCoord); + float scale = getUVScale(UV_coord); vec4 texture = getTexture(v_texCoord); float dis = texture.r; - if (dis<0.5) { - discard; - }else { - fragColor = vec4(1.0, 1.0, 1.0, 1.0); - } // float sdfRaw = 0.0; // float mark = 0.0; - // float sdf; // float sdfRadius = uSdfConfig.x; @@ -189,21 +192,15 @@ impl FontFragment { // fillColor = vec4(texture.rgb, fillColor.a); // } - // // if (gl_FragCoord.x < uClipUV.x || gl_FragCoord.y < uClipUV.y || gl_FragCoord.x > uClipUV.z || gl_FragCoord.y > uClipUV.w) { - // // discard; - // // } // // Compute mask based on SDF // float mask = clamp(sdf, 0.0, 1.0); - // // Final color blending logic here + // Final color blending logic here + + // fragColor = vec4(fillColor.rgb + mark, mask + mark); + + fragColor = vec4(dis,dis,dis,dis); - // if(mask < 0.5) { - // fragColor = vec4(0.0, 0.0, 0.0, 0.0); - // } else { - // fragColor = vec4(fillColor.rgb, 1.0); - // } - // fragColor = vec4(fillColor.rgb + mark, fillColor.a * mask + mark); - // fragColor = vec4(1.0, 1.0, 1.0, 1.0); } }; diff --git a/src/ui/operation.rs b/src/ui/operation.rs index 60d219b..3baa245 100644 --- a/src/ui/operation.rs +++ b/src/ui/operation.rs @@ -3,6 +3,7 @@ use crate::{ camera::Camera, components::Program, graphics::{AttaWithProgram, AttachWithMouse}, + pg::layout_type::ViewPort, }; pub struct Operation { @@ -23,11 +24,12 @@ impl Operation { } } - pub fn deal_io(&mut self, io: &super::io::IO) { + pub fn deal_io(&mut self, viewport: &ViewPort, io: &super::io::IO) { self.need_update = self.operation.attach_with_mouse( &T::State::from_context(io), &mut self.camera, &mut self.projection, + viewport, ); } @@ -56,10 +58,10 @@ impl Operation { self.operation.attach_with_program(gl, program); } - pub fn attach_with_mouse(&mut self, camera_op: &T::State) -> bool { - self.operation - .attach_with_mouse(camera_op, &mut self.camera, &mut self.projection) - } + // pub fn attach_with_mouse(&mut self, camera_op: &T::State) -> bool { + // self.operation + // .attach_with_mouse(camera_op, &mut self.camera, &mut self.projection) + // } pub fn is_need_update(&self) -> bool { self.need_update @@ -118,6 +120,18 @@ impl Projection { self.fov } + pub fn z_far(&self) -> f32 { + self.z_far + } + + pub fn z_near(&self) -> f32 { + self.z_near + } + + pub fn aspect(&self) -> f32 { + self.aspect + } + fn as_slice(&self) -> &[f32] { self.projection.as_slice() } diff --git a/src/ui/typ/main_load.rs b/src/ui/typ/main_load.rs index a7e007a..34a49ae 100644 --- a/src/ui/typ/main_load.rs +++ b/src/ui/typ/main_load.rs @@ -3,6 +3,7 @@ use std::thread::panicking; use super::{CameraOP, Layout, LayoutAttach, LayoutMod, Size}; use crate::camera::Camera; use crate::graphics::threed::Trackball; +use crate::graphics::transforms::plane::PlaneTrans; use crate::graphics::{AttaWithProgram, AttachWithMouse, MouseState}; use crate::pg::ModulePackage; use crate::pg::{_ModulePackage, layout_type::ViewPort}; @@ -136,7 +137,7 @@ impl LayoutMod for MainLoad { if ui.is_window_hovered() { let cio = IO::new(ui); - apptyp.operation.deal_io(&cio); + apptyp.operation.deal_io(&apptyp.main_viewport, &cio); } }); }); @@ -146,7 +147,7 @@ impl LayoutMod for MainLoad { let typ = MainLoadAttach { main_viewport: ViewPort::::new(gl, true), packages: Vec::new(), - operation: Operation::new(Trackball::default(), 16.0 / 9.0, 45.0, 0.1, 1000.0), + operation: Operation::new(PlaneTrans::default(), 16.0 / 9.0, 45.0, 0.1, 1000.0), }; typ } @@ -159,7 +160,7 @@ impl MainLoad { } pub struct MainLoadAttach<'gl> { - operation: Operation, + operation: Operation, main_viewport: ViewPort, packages: Vec>, } diff --git a/test.png b/test.png index f42ca9c..1612f62 100644 Binary files a/test.png and b/test.png differ