pusher
This commit is contained in:
parent
4204f444d6
commit
480888e8fc
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1182,6 +1182,7 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"chlorine",
|
||||
"mint",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@ -22,7 +22,7 @@ glow = "0.13.1"
|
||||
glutin = "0.31.3"
|
||||
glutin-winit = "0.4.2"
|
||||
image = "0.25.2"
|
||||
imgui = {version="0.12.0",features = ["tables-api"]}
|
||||
imgui = {version="0.12.0",features = ["tables-api", "freetype"]}
|
||||
imgui-glow-renderer = "0.12.0"
|
||||
imgui-winit-support = "0.12.0"
|
||||
include_dir = "0.7.4"
|
||||
|
||||
@ -8,77 +8,42 @@ use crate::errors::*;
|
||||
use crate::graphics::transforms::viewport::Viewport;
|
||||
use crate::graphics::ty::Ty;
|
||||
use crate::graphics::{AttaWithBuffer, Config, Graphics};
|
||||
use crate::shaders::agg_path::{AggPathFragment, AggPathVertex};
|
||||
|
||||
use super::Colletion;
|
||||
|
||||
pub struct AggFastPath {
|
||||
program: Program,
|
||||
buffer: Vec<Point>,
|
||||
indice: Vec<[u32; 3]>,
|
||||
}
|
||||
|
||||
vao: Option<NativeVertexArray>,
|
||||
vbo: Option<NativeBuffer>,
|
||||
ebo: Option<NativeBuffer>,
|
||||
pub struct AggFastPathConfig {
|
||||
pub color: [f32; 4],
|
||||
pub linewidth: f32,
|
||||
pub antialias: f32,
|
||||
}
|
||||
|
||||
impl AggFastPath {
|
||||
pub fn new() -> Result<Self> {
|
||||
let vertex = Shader::new(
|
||||
glow::VERTEX_SHADER,
|
||||
CodeType::from_path("agg-fast-path.vert"),
|
||||
CodeType::from_piece(AggPathVertex::new()),
|
||||
)?;
|
||||
|
||||
let fragment = Shader::new(
|
||||
glow::FRAGMENT_SHADER,
|
||||
CodeType::from_path("agg-fast-path.frag"),
|
||||
CodeType::from_piece(AggPathFragment::new()),
|
||||
)?;
|
||||
|
||||
let input_snippet = Snippet::new(
|
||||
"input",
|
||||
CodeType::from_code(
|
||||
"
|
||||
layout(location = 0) in vec3 prev;
|
||||
layout(location = 1) in vec3 curr;
|
||||
layout(location = 2) in vec3 next;
|
||||
layout(location = 3) in float id;
|
||||
|
||||
uniform float linewidth;
|
||||
|
||||
uniform float antialias;
|
||||
|
||||
uniform vec4 color;
|
||||
|
||||
",
|
||||
),
|
||||
false,
|
||||
None,
|
||||
)?;
|
||||
|
||||
let vertex = vertex.add_snippet_before(input_snippet);
|
||||
|
||||
let program = Program::new(vertex, fragment, None, "330 core");
|
||||
|
||||
// program.set_transform(transform);
|
||||
// program.set_viewport(viewport);
|
||||
|
||||
Ok(Self {
|
||||
program,
|
||||
buffer: Vec::with_capacity(128),
|
||||
indice: Vec::with_capacity(128 * 2),
|
||||
ebo: None,
|
||||
vao: None,
|
||||
vbo: None,
|
||||
})
|
||||
Ok(Self { program })
|
||||
}
|
||||
|
||||
#[cfg(feature = "inparser")]
|
||||
pub fn set_transform<T: Transform>(&mut self, transform: &T) {
|
||||
self.program.set_transform(transform);
|
||||
}
|
||||
|
||||
#[cfg(feature = "inparser")]
|
||||
pub fn set_viewport(&mut self, viewport: &Viewport) {
|
||||
self.program.set_viewport(viewport);
|
||||
pub fn set_viewport(&mut self, gl: &glow::Context, viewport: [f32; 2]) {
|
||||
let loc = self.program.get_uniform_location(gl, "viewport");
|
||||
unsafe {
|
||||
gl.uniform_2_f32(loc.as_ref(), viewport[0], viewport[1]);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_linecolor(&mut self, gl: &glow::Context, color: [f32; 4]) {
|
||||
@ -89,7 +54,7 @@ impl AggFastPath {
|
||||
}
|
||||
|
||||
pub fn set_linewidth(&mut self, gl: &glow::Context, linewidth: f32) {
|
||||
let loc = self.program.get_uniform_location(gl, "linewidth");
|
||||
let loc = self.program.get_uniform_location(gl, "thickness");
|
||||
unsafe {
|
||||
gl.uniform_1_f32(loc.as_ref(), linewidth);
|
||||
}
|
||||
@ -102,6 +67,12 @@ impl AggFastPath {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_config(&mut self, gl: &glow::Context, config: &AggFastPathConfig) {
|
||||
self.set_linecolor(gl, config.color);
|
||||
self.set_linewidth(gl, config.linewidth);
|
||||
self.set_anatialias(gl, config.antialias);
|
||||
}
|
||||
|
||||
pub fn program(&mut self) -> &mut Program {
|
||||
&mut self.program
|
||||
}
|
||||
@ -109,102 +80,24 @@ impl AggFastPath {
|
||||
pub fn program_ref(&self) -> &Program {
|
||||
&self.program
|
||||
}
|
||||
|
||||
fn init(&mut self, gl: &glow::Context) {
|
||||
self.set_anatialias(gl, 0.005);
|
||||
self.set_linecolor(gl, [1.0, 1.0, 1.0, 1.0]);
|
||||
self.set_linewidth(gl, 0.02);
|
||||
}
|
||||
}
|
||||
|
||||
impl Colletion for AggFastPath {
|
||||
type Item = Path;
|
||||
|
||||
fn append(&mut self, item: Self::Item) {
|
||||
self.buffer.extend(item.points);
|
||||
self.indice.extend(item.ebo);
|
||||
}
|
||||
}
|
||||
|
||||
impl Graphics for AggFastPath {
|
||||
const id: &'static str = "AggPath";
|
||||
type Config = ();
|
||||
type Config = AggFastPathConfig;
|
||||
fn compile(&mut self, gl: &glow::Context) -> Result<()> {
|
||||
use bytemuck::cast_slice;
|
||||
self.program.compile(gl)?;
|
||||
|
||||
unsafe {
|
||||
let vao = gl.create_vertex_array().unwrap();
|
||||
|
||||
gl.bind_vertex_array(Some(vao));
|
||||
for p in self.buffer.iter() {
|
||||
println!("{}", p);
|
||||
}
|
||||
println!("{:?}", self.indice);
|
||||
|
||||
let vbo = gl.create_buffer().unwrap();
|
||||
gl.bind_buffer(glow::ARRAY_BUFFER, Some(vbo));
|
||||
gl.buffer_data_u8_slice(
|
||||
glow::ARRAY_BUFFER,
|
||||
cast_slice(&self.buffer),
|
||||
glow::STATIC_DRAW,
|
||||
);
|
||||
|
||||
gl.enable_vertex_attrib_array(0);
|
||||
gl.vertex_attrib_pointer_f32(0, 3, glow::FLOAT, false, 40, 0);
|
||||
|
||||
gl.enable_vertex_attrib_array(1);
|
||||
gl.vertex_attrib_pointer_f32(1, 3, glow::FLOAT, false, 40, 12);
|
||||
|
||||
gl.enable_vertex_attrib_array(2);
|
||||
gl.vertex_attrib_pointer_f32(2, 3, glow::FLOAT, false, 40, 24);
|
||||
|
||||
gl.enable_vertex_attrib_array(3);
|
||||
gl.vertex_attrib_pointer_f32(3, 1, glow::FLOAT, false, 40, 36);
|
||||
|
||||
let ebo = gl.create_buffer().unwrap();
|
||||
gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(ebo));
|
||||
|
||||
gl.buffer_data_u8_slice(
|
||||
glow::ELEMENT_ARRAY_BUFFER,
|
||||
cast_slice(&self.indice),
|
||||
glow::STATIC_DRAW,
|
||||
);
|
||||
|
||||
self.vao = Some(vao);
|
||||
self.vbo = Some(vbo);
|
||||
self.ebo = Some(ebo);
|
||||
|
||||
gl.bind_vertex_array(None);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
self.program.compile(gl)
|
||||
}
|
||||
|
||||
fn draw(&self, gl: &glow::Context, count: i32) -> Result<()> {
|
||||
unsafe {
|
||||
gl.bind_vertex_array(Some(self.vao.unwrap()));
|
||||
gl.draw_elements(
|
||||
glow::TRIANGLES,
|
||||
(self.indice.len() * 3) as i32,
|
||||
glow::UNSIGNED_INT,
|
||||
0,
|
||||
);
|
||||
gl.bind_vertex_array(None);
|
||||
gl.draw_elements(glow::TRIANGLES, count, glow::UNSIGNED_INT, 0);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn destroy(&mut self, gl: &glow::Context) -> Result<()> {
|
||||
self.program.destroy(gl);
|
||||
|
||||
unsafe {
|
||||
self.ebo.map(|ebo| gl.delete_buffer(ebo));
|
||||
self.vao.map(|vao| gl.delete_vertex_array(vao));
|
||||
self.vbo.map(|vbo| gl.delete_buffer(vbo));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -223,7 +116,6 @@ impl Graphics for AggFastPath {
|
||||
fn mount(&mut self, gl: &glow::Context) -> Result<()> {
|
||||
unsafe {
|
||||
gl.use_program(self.program.native_program);
|
||||
self.init(gl);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -237,18 +129,57 @@ impl Graphics for AggFastPath {
|
||||
}
|
||||
|
||||
impl AttaWithBuffer for AggFastPath {
|
||||
type Data = ();
|
||||
type Data = Vec<Path>;
|
||||
|
||||
fn bake(
|
||||
&self,
|
||||
data: &Self::Data,
|
||||
config: &<Self as Graphics>::Config,
|
||||
) -> Result<(Vec<f32>, Option<Vec<u32>>, i32)> {
|
||||
Ok((vec![], None, 0))
|
||||
let points = data.iter().map(|v| &v.points).flatten().collect::<Vec<_>>();
|
||||
let mut vbo = Vec::with_capacity(points.len() * 10);
|
||||
for p in points {
|
||||
vbo.extend_from_slice(&[
|
||||
p.prev[0], p.prev[1], p.prev[2], p.curr[0], p.curr[1], p.curr[2], p.next[0],
|
||||
p.next[1], p.next[2], p.id,
|
||||
]);
|
||||
}
|
||||
let mut ebo = vec![];
|
||||
for e in data.iter().map(|v| &v.ebo).flatten() {
|
||||
ebo.extend_from_slice(e);
|
||||
}
|
||||
|
||||
let len = ebo.len() as i32;
|
||||
|
||||
Ok((vbo, Some(ebo), len))
|
||||
}
|
||||
|
||||
fn init(&self, gl: &glow::Context) -> (NativeVertexArray, NativeBuffer, Option<NativeBuffer>) {
|
||||
(self.vao.unwrap(), self.vbo.unwrap(), self.ebo)
|
||||
unsafe {
|
||||
let vao = gl.create_vertex_array().unwrap();
|
||||
gl.bind_vertex_array(Some(vao));
|
||||
|
||||
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, 3, glow::FLOAT, false, 40, 0);
|
||||
|
||||
gl.enable_vertex_attrib_array(1);
|
||||
gl.vertex_attrib_pointer_f32(1, 3, glow::FLOAT, false, 40, 12);
|
||||
|
||||
gl.enable_vertex_attrib_array(2);
|
||||
gl.vertex_attrib_pointer_f32(2, 3, glow::FLOAT, false, 40, 24);
|
||||
|
||||
gl.enable_vertex_attrib_array(3);
|
||||
gl.vertex_attrib_pointer_f32(3, 1, glow::FLOAT, false, 40, 36);
|
||||
let ebo = gl.create_buffer().unwrap();
|
||||
gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(ebo));
|
||||
gl.bind_vertex_array(None);
|
||||
|
||||
gl.bind_buffer(glow::ARRAY_BUFFER, None);
|
||||
(vao, vbo, Some(ebo))
|
||||
}
|
||||
}
|
||||
}
|
||||
#[repr(C)]
|
||||
@ -269,6 +200,11 @@ impl std::fmt::Display for Point {
|
||||
)
|
||||
}
|
||||
}
|
||||
impl Point {
|
||||
fn f32_slice(&self) -> &[f32] {
|
||||
unsafe { std::slice::from_raw_parts(self as *const Self as *const f32, 13) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Ty for Point {}
|
||||
|
||||
|
||||
@ -2,14 +2,15 @@ mod esdt;
|
||||
use esdt::{Image2d, Unorm8};
|
||||
use glow::{HasContext, TEXTURE_2D};
|
||||
use std::{cell::RefCell, collections::HashMap};
|
||||
use text_items::{LineStyle, Text as TextTrait};
|
||||
use text_items::Text as TextTrait;
|
||||
mod text_items;
|
||||
pub use text_items::{Anchor, PositionText, TextLine};
|
||||
pub use text_items::{Anchor, LineStyle, PositionText, TextLine};
|
||||
|
||||
use crate::{
|
||||
components::{CodeType, Program, Shader},
|
||||
errors::*,
|
||||
font_manager::{FontManager, FontStyle},
|
||||
shaders::font::{FontFragment, FontGeometry, FontVertex},
|
||||
utils::resources::RcGlTexture,
|
||||
};
|
||||
|
||||
@ -18,14 +19,12 @@ pub struct Text<'a> {
|
||||
gl: &'a glow::Context,
|
||||
font_manager: RefCell<FontManager>,
|
||||
cache: RefCell<HashMap<String, Cache<'a>>>,
|
||||
items: Vec<PositionText>,
|
||||
program: Program,
|
||||
}
|
||||
|
||||
pub struct Cache<'a> {
|
||||
gl: &'a glow::Context,
|
||||
cache: HashMap<char, TextVType>,
|
||||
// cache_tex: Vec<u8>,
|
||||
width: usize,
|
||||
height: usize,
|
||||
last_pos: [usize; 2],
|
||||
@ -115,14 +114,20 @@ impl<'a> Cache<'a> {
|
||||
self.cache.insert(
|
||||
c,
|
||||
TextVType {
|
||||
// tex_coords: [
|
||||
// x as f32,
|
||||
// (y + height - 1) as f32,
|
||||
// (x + width - 1) as f32,
|
||||
// (y + height - 1) as f32,
|
||||
// (x + width - 1) as f32,
|
||||
// y as f32,
|
||||
// x as f32,
|
||||
// y as f32,
|
||||
// ],
|
||||
tex_coords: [
|
||||
x as f32,
|
||||
(y + height - 1) as f32,
|
||||
(x + width - 1) as f32,
|
||||
(y + height - 1) as f32,
|
||||
(x + width - 1) as f32,
|
||||
y as f32,
|
||||
x as f32,
|
||||
y as f32,
|
||||
],
|
||||
// tex_coords: [0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0],
|
||||
@ -146,34 +151,65 @@ impl<'a> Cache<'a> {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TextVType {
|
||||
tex_coords: [f32; 8],
|
||||
tex_coords: [f32; 4],
|
||||
}
|
||||
|
||||
impl TextVType {
|
||||
fn left_top(&self) -> [f32; 2] {
|
||||
[self.tex_coords[0], self.tex_coords[1]]
|
||||
}
|
||||
|
||||
fn right_bottom(&self) -> [f32; 2] {
|
||||
[self.tex_coords[2], self.tex_coords[3]]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Text<'a> {
|
||||
pub fn new(gl: &'a glow::Context, font_manager: FontManager) -> Result<Self> {
|
||||
let vertex = Shader::new(
|
||||
glow::VERTEX_SHADER,
|
||||
crate::components::CodeType::from_path("font.vert"),
|
||||
crate::components::CodeType::from_piece(FontVertex::new()),
|
||||
)?;
|
||||
|
||||
let fragment = Shader::new(glow::FRAGMENT_SHADER, CodeType::from_path("font.frag"))?;
|
||||
let geom = Shader::new(
|
||||
glow::GEOMETRY_SHADER,
|
||||
crate::components::CodeType::from_piece(FontGeometry::new()),
|
||||
)?;
|
||||
|
||||
let mut program = Program::new(vertex, fragment, None, "330 core");
|
||||
#[cfg(feature = "inparser")]
|
||||
program.set_transform(&transform);
|
||||
let fragment = Shader::new(
|
||||
glow::FRAGMENT_SHADER,
|
||||
CodeType::from_piece(FontFragment::new()),
|
||||
)?;
|
||||
|
||||
let mut program = Program::new(vertex, fragment, Some(geom), "330 core");
|
||||
|
||||
Ok(Self {
|
||||
gl,
|
||||
font_manager: RefCell::new(font_manager),
|
||||
cache: RefCell::new(HashMap::new()),
|
||||
items: Vec::new(),
|
||||
program,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "inparser")]
|
||||
pub fn set_viewport(&mut self, viewport: &Viewport) {
|
||||
self.program.set_viewport(viewport);
|
||||
pub fn set_viewport(&self, viewport: [f32; 2]) {
|
||||
let loc = self.program.get_uniform_location(&self.gl, "viewport");
|
||||
unsafe {
|
||||
self.gl
|
||||
.uniform_2_f32(loc.as_ref(), viewport[0], viewport[1]);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_config(&self, config: FontConfig) {
|
||||
match config {
|
||||
FontConfig::Textline(style, font) => {
|
||||
let loc = self.program.get_uniform_location(&self.gl, "location");
|
||||
let anchor = self.program.get_uniform_location(&self.gl, "anchor");
|
||||
unsafe {
|
||||
self.gl.uniform_3_f32(loc.as_ref(), 0.0, 0.0, 1.0);
|
||||
self.gl.uniform_3_f32(anchor.as_ref(), 0.0, 0.0, 0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn set_uniforms(&self) {
|
||||
@ -207,9 +243,6 @@ impl<'a> Graphics for Text<'a> {
|
||||
|
||||
fn draw(&self, gl: &glow::Context, count: i32) -> Result<()> {
|
||||
unsafe {
|
||||
gl.clear(glow::COLOR_BUFFER_BIT);
|
||||
// gl.polygon_mode(glow::FRONT_AND_BACK, glow::LINE);
|
||||
|
||||
let loc = self.program.get_uniform_location(gl, "atlas_data");
|
||||
gl.uniform_1_i32(loc.as_ref(), 0);
|
||||
|
||||
@ -227,7 +260,7 @@ impl<'a> Graphics for Text<'a> {
|
||||
|
||||
self.set_uniforms();
|
||||
|
||||
gl.draw_elements(glow::TRIANGLES, count / 2 * 3, glow::UNSIGNED_INT, 0);
|
||||
gl.draw_arrays(glow::POINTS, 0, count);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -241,6 +274,16 @@ impl<'a> Graphics for Text<'a> {
|
||||
}
|
||||
|
||||
fn set_config(&mut self, gl: &glow::Context, config: &Self::Config) -> Result<()> {
|
||||
unsafe {
|
||||
match config {
|
||||
FontConfig::Textline(style, font) => {
|
||||
let loc = self.program.get_uniform_location(gl, "location");
|
||||
let anchor = self.program.get_uniform_location(gl, "anchor");
|
||||
gl.uniform_3_f32(loc.as_ref(), 0.0, 0.0, 2.0);
|
||||
gl.uniform_3_f32(anchor.as_ref(), 0.0, 0.0, 0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -259,19 +302,7 @@ impl<'a> AttaWithBuffer for Text<'a> {
|
||||
&mut *self.cache.borrow_mut(),
|
||||
)?;
|
||||
|
||||
let mut ebos = Vec::with_capacity(v.len() / 2 * 3);
|
||||
|
||||
for i in 0..v.len() / 4 {
|
||||
let i = i as u32;
|
||||
ebos.push(i * 4);
|
||||
ebos.push(i * 4 + 1);
|
||||
ebos.push(i * 4 + 3);
|
||||
|
||||
ebos.push(i * 4 + 1);
|
||||
ebos.push(i * 4 + 2);
|
||||
ebos.push(i * 4 + 3);
|
||||
}
|
||||
Ok((v.vertex(), Some(ebos), v.len() as i32))
|
||||
Ok((v.vertex(), None, v.len() as i32))
|
||||
}
|
||||
|
||||
fn init(
|
||||
@ -288,17 +319,15 @@ 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, 3, glow::FLOAT, false, 20, 0);
|
||||
gl.vertex_attrib_pointer_f32(0, 4, glow::FLOAT, false, 32, 0);
|
||||
|
||||
gl.enable_vertex_attrib_array(1);
|
||||
gl.vertex_attrib_pointer_f32(1, 2, glow::FLOAT, false, 20, 12);
|
||||
|
||||
let ebo = gl.create_buffer().unwrap();
|
||||
gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(ebo));
|
||||
gl.vertex_attrib_pointer_f32(1, 4, glow::FLOAT, false, 32, 16);
|
||||
|
||||
gl.bind_vertex_array(None);
|
||||
gl.bind_buffer(glow::ARRAY_BUFFER, None);
|
||||
|
||||
(vao, vbo, Some(ebo))
|
||||
(vao, vbo, None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,8 +100,8 @@ impl Default for TextAlign {
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Zeroable, Pod)]
|
||||
pub struct TextVertexItem {
|
||||
position: [f32; 3],
|
||||
tex_coords: [f32; 2],
|
||||
tex_coords: [f32; 4],
|
||||
position: [f32; 4],
|
||||
}
|
||||
|
||||
pub struct TextVertexArray {
|
||||
@ -123,22 +123,25 @@ impl TextVertexArray {
|
||||
self.points.push(item);
|
||||
}
|
||||
|
||||
pub fn insert_text(&mut self, tex_coords: TextVType, positions: [[f32; 3]; 4]) {
|
||||
for i in 0..4 {
|
||||
self.push(TextVertexItem {
|
||||
position: positions[i],
|
||||
tex_coords: [
|
||||
tex_coords.tex_coords[i * 2],
|
||||
tex_coords.tex_coords[i * 2 + 1],
|
||||
],
|
||||
});
|
||||
}
|
||||
pub fn insert_text(&mut self, tex_coords: TextVType, position: [f32; 2], size: [f32; 2]) {
|
||||
let tex_left_top = tex_coords.left_top();
|
||||
let tex_right_bottom = tex_coords.right_bottom();
|
||||
|
||||
self.push(TextVertexItem {
|
||||
position: [position[0], position[1], size[0], size[1]],
|
||||
tex_coords: [
|
||||
tex_left_top[0],
|
||||
tex_left_top[1],
|
||||
tex_right_bottom[0],
|
||||
tex_right_bottom[1],
|
||||
],
|
||||
});
|
||||
}
|
||||
pub fn vertex(&self) -> Vec<f32> {
|
||||
let mut result = Vec::with_capacity(self.len() * 6);
|
||||
let mut result = Vec::with_capacity(self.len() * 8);
|
||||
self.points.iter().for_each(|v| {
|
||||
result.extend_from_slice(&v.position);
|
||||
result.extend_from_slice(&v.tex_coords);
|
||||
result.extend_from_slice(&v.position);
|
||||
});
|
||||
result
|
||||
}
|
||||
@ -205,24 +208,25 @@ impl Text for TextLine {
|
||||
});
|
||||
|
||||
let metrics = font.get_metrics(char);
|
||||
let bear_x = metrics.horiBearingX;
|
||||
let bear_y = metrics.horiBearingY;
|
||||
let width = (metrics.width >> 6) as f32;
|
||||
let height = (metrics.height >> 6) as f32;
|
||||
|
||||
let bear_x = (metrics.horiBearingX >> 6) as f32;
|
||||
let bear_y = (metrics.horiBearingY >> 6) as f32;
|
||||
|
||||
let x0 = pen[0] + bear_x as f32 + x_kerning;
|
||||
let y0 = pen[1] - bear_y as f32;
|
||||
let x1 = pen[0] + metrics.width as f32 + x_kerning;
|
||||
let y1 = pen[1] + metrics.height as f32;
|
||||
|
||||
let position = [[x0, y0, 0.0], [x1, y0, 0.0], [x1, y1, 0.0], [x1, y0, 0.0]];
|
||||
|
||||
if let Some(cache) = cache.get(char) {
|
||||
baked.insert_text(cache.to_owned(), position);
|
||||
baked.insert_text(cache.to_owned(), [x0, y0], [width, height]);
|
||||
} else {
|
||||
let char_glyph = font.get_char(char, 64)?;
|
||||
let mut img = char_glyph.into();
|
||||
let (result, _) = glyph_to_sdf(&mut img, SDF_PARAM, None);
|
||||
let b = cache.insert_glyph(result, char);
|
||||
baked.insert_text(b.to_owned(), position);
|
||||
baked.insert_text(b.to_owned(), [x0, y0], [width, height]);
|
||||
}
|
||||
|
||||
pen[0] += x_advanced;
|
||||
|
||||
@ -203,7 +203,7 @@ impl AttaWithBuffer for PPI {
|
||||
vertices.extend([r, *azi, *ele, *dt]);
|
||||
}
|
||||
}
|
||||
let len = vertices.len() as i32 / 3;
|
||||
let len = vertices.len() as i32 / 4;
|
||||
return Ok((vertices, None, len));
|
||||
} else {
|
||||
return Err(Error::InvalidDataType);
|
||||
@ -219,6 +219,7 @@ impl AttaWithBuffer for PPI {
|
||||
gl.enable_vertex_attrib_array(0);
|
||||
gl.vertex_attrib_pointer_f32(0, 4, glow::FLOAT, false, 16, 0);
|
||||
gl.bind_vertex_array(None);
|
||||
gl.bind_buffer(glow::ARRAY_BUFFER, None);
|
||||
|
||||
(vao, vbo, None)
|
||||
}
|
||||
|
||||
@ -86,6 +86,10 @@ impl<T: Resource> ViewPort<T> {
|
||||
pub fn fbo(&self) -> &RcGlRcFramebuffer {
|
||||
&self.main_fbo
|
||||
}
|
||||
|
||||
pub fn size(&self) -> [f32; 2] {
|
||||
self.renderer_size
|
||||
}
|
||||
}
|
||||
|
||||
impl ViewPort<NativeTexture> {
|
||||
|
||||
@ -2,13 +2,16 @@ mod app;
|
||||
use femtovg::renderer::OpenGl;
|
||||
use femtovg::Canvas;
|
||||
use glow::HasContext;
|
||||
use layout_type::ViewPort;
|
||||
pub mod layout_type;
|
||||
mod modules;
|
||||
|
||||
use crate::font_manager::FontManager;
|
||||
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::viewport;
|
||||
use crate::graphics::{AttaWithProgram, AttachWithMouse};
|
||||
use crate::ui::operation::Operation;
|
||||
use crate::ui::typ::LayoutAttach;
|
||||
@ -25,6 +28,7 @@ pub(super) struct Programs<'gl> {
|
||||
gl: &'gl GL,
|
||||
_ppi: PPI,
|
||||
_text: Text<'gl>,
|
||||
_line: AggFastPath,
|
||||
}
|
||||
|
||||
impl<'gl> Programs<'gl> {
|
||||
@ -35,21 +39,25 @@ impl<'gl> Programs<'gl> {
|
||||
gl,
|
||||
_ppi: PPI::new()?,
|
||||
_text: Text::new(gl, font_manager)?,
|
||||
_line: AggFastPath::new()?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn prepare(&mut self) -> Result<()> {
|
||||
self._ppi.program().compile(&self.gl)?;
|
||||
self._line.program().compile(&self.gl)?;
|
||||
self._text.program_mut().compile(&self.gl)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn ppi<'b>(&'b mut self) -> modules::PPIModule<'b, 'gl> {
|
||||
modules::PPIModule::new(&self.gl, &mut self._ppi, &mut self._text).unwrap()
|
||||
modules::PPIModule::new(&self.gl, &mut self._ppi, &mut self._text, &mut self._line).unwrap()
|
||||
}
|
||||
|
||||
pub fn destroy(&mut self) -> Result<()> {
|
||||
self._ppi.destroy(&self.gl)?;
|
||||
self._text.destroy(&self.gl)?;
|
||||
self._line.destroy(&self.gl)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -78,12 +86,11 @@ impl<'gl> Programs<'gl> {
|
||||
&mut self,
|
||||
modules: &mut ModulePackage<'gl>,
|
||||
operation: &Operation<Trackball>,
|
||||
viewport: &ViewPort,
|
||||
) -> Result<()> {
|
||||
match &mut modules.modules {
|
||||
_ModulePackage::PPI(ppi) => {
|
||||
self.ppi().start();
|
||||
self.ppi().render(ppi, operation)?;
|
||||
self.ppi().end();
|
||||
self.ppi().render(ppi, operation, viewport)?;
|
||||
}
|
||||
}
|
||||
modules.need_update = false;
|
||||
|
||||
@ -15,7 +15,7 @@ mod ppi;
|
||||
use crate::errors::*;
|
||||
pub use ppi::{PPIModule, PPIPackage};
|
||||
|
||||
use super::Data;
|
||||
use super::{layout_type::ViewPort, Data};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct Attach<'a> {
|
||||
@ -43,23 +43,43 @@ impl<'a> Attach<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn bind_self(&self) {
|
||||
self.vao.bind(glow::VERTEX_ARRAY);
|
||||
self.vbo.bind(glow::ARRAY_BUFFER);
|
||||
if let Some(ebo) = self.ebo.as_ref() {
|
||||
ebo.bind(glow::ELEMENT_ARRAY_BUFFER);
|
||||
}
|
||||
}
|
||||
|
||||
fn unbind_self(&self) {
|
||||
self.vao.unbind(glow::VERTEX_ARRAY);
|
||||
self.vbo.unbind(glow::ARRAY_BUFFER);
|
||||
if let Some(ebo) = self.ebo.as_ref() {
|
||||
ebo.unbind(glow::ELEMENT_ARRAY_BUFFER);
|
||||
}
|
||||
}
|
||||
|
||||
fn bind_data(&mut self, vbo: &Vec<f32>, ebo: Option<&Vec<u32>>, len: i32) {
|
||||
use bytemuck::cast_slice;
|
||||
self.vao.bind(glow::VERTEX_ARRAY);
|
||||
self.vbo.bind(glow::ARRAY_BUFFER);
|
||||
unsafe {
|
||||
self.gl
|
||||
.buffer_data_u8_slice(glow::ARRAY_BUFFER, cast_slice(&vbo), glow::STATIC_DRAW);
|
||||
if let Some(ebo) = ebo {
|
||||
self.ebo.as_ref().unwrap().bind(glow::ELEMENT_ARRAY_BUFFER);
|
||||
self.gl.bind_buffer(
|
||||
glow::ELEMENT_ARRAY_BUFFER,
|
||||
Some(self.ebo.as_ref().unwrap().native()),
|
||||
);
|
||||
self.gl.buffer_data_u8_slice(
|
||||
glow::ELEMENT_ARRAY_BUFFER,
|
||||
cast_slice(&ebo),
|
||||
glow::STATIC_DRAW,
|
||||
);
|
||||
|
||||
self.gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, None);
|
||||
}
|
||||
}
|
||||
|
||||
self.vao.unbind(glow::VERTEX_ARRAY);
|
||||
self.vbo.unbind(glow::ARRAY_BUFFER);
|
||||
self.len = len;
|
||||
}
|
||||
|
||||
@ -77,13 +97,9 @@ pub trait Module: Sized {
|
||||
&mut self,
|
||||
cursor: &mut Self::Cursor,
|
||||
operation: &Operation<Self::Operation>,
|
||||
viewport: &ViewPort,
|
||||
) -> Result<()>;
|
||||
fn resize(&self, size: [f32; 2]);
|
||||
fn destroy(&self);
|
||||
|
||||
fn start(&mut self);
|
||||
// fn init(&mut self, info: &Operation<Self::Operation>) -> Result<()>;
|
||||
fn end(&mut self);
|
||||
fn load_data<'dt>(&self, data: &CachedData<Self::Data>) -> Result<Self::Cursor>;
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,14 @@
|
||||
use collections::agg_fast_path::{AggFastPath, AggFastPathConfig, Path};
|
||||
use core::f32;
|
||||
use font::{FontConfig, LineStyle, PositionText, TextLine};
|
||||
use glow::HasContext;
|
||||
use std::rc::Rc;
|
||||
use tracker::track;
|
||||
use transforms::viewport;
|
||||
|
||||
use crate::font_manager::{FontSize, FontStyle};
|
||||
use crate::graphics::{font::Text, *};
|
||||
use crate::pg::layout_type::ViewPort;
|
||||
use crate::ui::helper_components::colorbar::colorbar;
|
||||
use crate::ui::operation::{self, Operation};
|
||||
use crate::SETTING;
|
||||
@ -20,35 +27,81 @@ use super::{Attach, Module, ModuleCursor};
|
||||
pub struct PPIModule<'b, 'a: 'b> {
|
||||
gl: &'a glow::Context,
|
||||
ppi_program: &'b mut PPI,
|
||||
line_program: &'b mut AggFastPath,
|
||||
text_program: &'b mut Text<'a>,
|
||||
}
|
||||
|
||||
impl<'b, 'a: 'b> PPIModule<'b, 'a> {
|
||||
pub fn new(gl: &'a glow::Context, ppi: &'b mut PPI, text: &'b mut Text<'a>) -> Result<Self> {
|
||||
pub fn new(
|
||||
gl: &'a glow::Context,
|
||||
ppi: &'b mut PPI,
|
||||
text: &'b mut Text<'a>,
|
||||
line: &'b mut AggFastPath,
|
||||
) -> Result<Self> {
|
||||
let config = PPIConfig::default();
|
||||
Ok(Self {
|
||||
gl,
|
||||
ppi_program: ppi,
|
||||
text_program: text,
|
||||
line_program: line,
|
||||
})
|
||||
}
|
||||
|
||||
fn rebind(&self, attach: &mut Attach, data: &Data, config: &PPIModuleConfig) -> Result<()> {
|
||||
let (vbo, ebo, len) = self.ppi_program.bake(
|
||||
data,
|
||||
&PPIConfig {
|
||||
unvalid_value: config.unvalid_value,
|
||||
color_range: config.color_range,
|
||||
colors: config.colors.clone(),
|
||||
layer: config.layer,
|
||||
rdpi: config.rdpi,
|
||||
adpi: config.adpi,
|
||||
three_d: config.is_three_d,
|
||||
},
|
||||
)?;
|
||||
fn bind_ppi_pg(
|
||||
&self,
|
||||
attach: &mut Attach,
|
||||
data: &Data,
|
||||
config: &PPIModuleConfig,
|
||||
) -> Result<()> {
|
||||
let (vbo, ebo, len) = self.ppi_program.bake(data, &config.to_ppi_config())?;
|
||||
attach.bind_data(&vbo, ebo.as_ref(), len);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn bind_line_pg(
|
||||
&self,
|
||||
attach: &mut Attach,
|
||||
data: &Data,
|
||||
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 (vbo, ebo, len) = self.line_program.bake(&vec![path], &config)?;
|
||||
attach.bind_data(&vbo, ebo.as_ref(), len);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn bind_tick(&self, attach: &mut Attach, data: &Data, config: &PPIModuleConfig) -> Result<()> {
|
||||
let font_style = config.to_font_config();
|
||||
|
||||
match font_style {
|
||||
FontConfig::Textline(line_style, font_style) => {
|
||||
let new_text = TextLine::new("ABC", 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);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'b, 'a: 'b> Module for PPIModule<'b, 'a> {
|
||||
@ -56,116 +109,155 @@ impl<'b, 'a: 'b> Module for PPIModule<'b, 'a> {
|
||||
type Data = Data;
|
||||
type Operation = Trackball;
|
||||
|
||||
fn start(&mut self) {
|
||||
self.ppi_program.mount(&self.gl).unwrap();
|
||||
}
|
||||
|
||||
fn end(&mut self) {
|
||||
self.ppi_program.unmount(&self.gl).unwrap();
|
||||
}
|
||||
|
||||
fn render<'dt>(
|
||||
&mut self,
|
||||
cursor: &mut Self::Cursor,
|
||||
operation: &Operation<Self::Operation>,
|
||||
viewport: &ViewPort,
|
||||
) -> Result<()> {
|
||||
// Mount PPI Program
|
||||
self.ppi_program.mount(&self.gl)?;
|
||||
// Deal with the operation
|
||||
operation.attach_with_program(&self.gl, self.ppi_program.program());
|
||||
let attach = &mut cursor.ppi_attach;
|
||||
// PPI Program
|
||||
let ppi_attach = &mut cursor.ppi_attach;
|
||||
let data = &cursor.ppi_data.borrow();
|
||||
let config = &mut cursor.ppi_config;
|
||||
|
||||
self.ppi_program.set_config(
|
||||
&self.gl,
|
||||
&PPIConfig {
|
||||
unvalid_value: config.unvalid_value,
|
||||
color_range: config.color_range,
|
||||
colors: config.colors.clone(),
|
||||
layer: config.layer,
|
||||
rdpi: config.rdpi,
|
||||
adpi: config.adpi,
|
||||
three_d: config.is_three_d,
|
||||
},
|
||||
)?;
|
||||
// Update the config
|
||||
self.ppi_program
|
||||
.set_config(&self.gl, &config.to_ppi_config())?;
|
||||
|
||||
// if the layer is changed, we need to rebind the data
|
||||
if config.changed_layer() {
|
||||
self.rebind(attach, data, config);
|
||||
config.reset();
|
||||
self.bind_ppi_pg(ppi_attach, data, config);
|
||||
}
|
||||
attach.vao.bind(glow::VERTEX_ARRAY);
|
||||
self.ppi_program.draw(&self.gl, attach.len())?;
|
||||
attach.vao.unbind(glow::VERTEX_ARRAY);
|
||||
|
||||
// PPI Draw
|
||||
ppi_attach.bind_self();
|
||||
self.ppi_program.draw(&self.gl, ppi_attach.len())?;
|
||||
ppi_attach.unbind_self();
|
||||
|
||||
// Unmount PPI Program
|
||||
self.ppi_program.unmount(&self.gl)?;
|
||||
|
||||
// Mount Line Program
|
||||
self.line_program.mount(&self.gl)?;
|
||||
|
||||
// Deal with the operation
|
||||
operation.attach_with_program(&self.gl, self.line_program.program());
|
||||
|
||||
// Set the viewport, this is important
|
||||
self.line_program.set_viewport(&self.gl, viewport.size());
|
||||
|
||||
// Update the config
|
||||
self.line_program
|
||||
.set_config(&self.gl, &config.to_line_config());
|
||||
|
||||
// PPI Tick Draw
|
||||
let attach = &mut cursor.line_attach;
|
||||
attach.bind_self();
|
||||
self.line_program.draw(&self.gl, attach.len())?;
|
||||
attach.unbind_self();
|
||||
|
||||
self.line_program.unmount(&self.gl)?;
|
||||
|
||||
self.text_program.mount(&self.gl);
|
||||
|
||||
let tick_attach = &mut cursor.tick_attach;
|
||||
// Deal with the operation
|
||||
operation.attach_with_program(&self.gl, self.text_program.program_mut());
|
||||
self.text_program.set_viewport(viewport.size());
|
||||
self.text_program
|
||||
.set_config(&self.gl, &config.to_font_config());
|
||||
|
||||
tick_attach.bind_self();
|
||||
self.text_program.draw(&self.gl, tick_attach.len())?;
|
||||
tick_attach.unbind_self();
|
||||
|
||||
config.reset();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn resize(&self, size: [f32; 2]) {}
|
||||
|
||||
fn destroy(&self) {}
|
||||
|
||||
fn load_data<'dt>(&self, data: &CachedData<Self::Data>) -> Result<Self::Cursor> {
|
||||
let _data = data.borrow();
|
||||
|
||||
// Check if the data is valid
|
||||
if _data.blocks.len() == 0 {
|
||||
return Err(Error::InvalidDataType);
|
||||
}
|
||||
|
||||
// Init the memory
|
||||
let (vao, vbo, ebo) = self.ppi_program.init(&self.gl);
|
||||
let mut attach = Attach::new(&self.gl, vao, vbo, ebo, None);
|
||||
let mut ppi_attach = Attach::new(&self.gl, vao, vbo, ebo, None);
|
||||
|
||||
// Get the data info
|
||||
let (r, a, t, max_layer, unvalid) = self.ppi_program.data_info(&_data)?;
|
||||
|
||||
// Find the color map
|
||||
let cmap = SETTING.find(&t);
|
||||
|
||||
// Check if the color map is valid
|
||||
if cmap.is_none() {
|
||||
return Err(Error::InvalidDataType);
|
||||
}
|
||||
|
||||
let cmap = cmap.unwrap();
|
||||
|
||||
let config = PPIModuleConfig {
|
||||
color_range: cmap.value_range(),
|
||||
colors: cmap.color()?,
|
||||
layer: 0,
|
||||
rdpi: r,
|
||||
adpi: a,
|
||||
max_layer,
|
||||
unvalid_value: unvalid,
|
||||
is_three_d: true,
|
||||
tracker: 0,
|
||||
};
|
||||
// Init the memory for the line program
|
||||
let (vao, vbo, ebo) = self.line_program.init(&self.gl);
|
||||
let mut line_attach = Attach::new(&self.gl, vao, vbo, ebo, None);
|
||||
|
||||
self.rebind(&mut attach, &data.borrow(), &config);
|
||||
// Tick Label
|
||||
let (vao, vbo, ebo) = self.text_program.init(&self.gl);
|
||||
let mut tick_attach = Attach::new(&self.gl, vao, vbo, ebo, None);
|
||||
|
||||
Ok(PPIPackage::new(config, attach, data))
|
||||
let mut config = PPIModuleConfig::default();
|
||||
config.rdpi = r;
|
||||
config.adpi = a;
|
||||
config.max_layer = max_layer;
|
||||
config.unvalid_value = unvalid;
|
||||
config.colors = cmap.color()?;
|
||||
config.color_range = cmap.value_range();
|
||||
|
||||
// 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);
|
||||
|
||||
Ok(PPIPackage::new(
|
||||
config,
|
||||
ppi_attach,
|
||||
line_attach,
|
||||
tick_attach,
|
||||
data,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[track]
|
||||
#[derive(PartialEq)]
|
||||
pub struct PPIModuleConfig {
|
||||
pub layer: usize,
|
||||
pub colors: Vec<[u8; 4]>,
|
||||
pub color_range: [f32; 2],
|
||||
pub is_three_d: bool,
|
||||
#[do_not_track]
|
||||
pub unvalid_value: f32,
|
||||
#[do_not_track]
|
||||
pub max_layer: usize,
|
||||
#[do_not_track]
|
||||
pub rdpi: f32,
|
||||
#[do_not_track]
|
||||
pub adpi: f32,
|
||||
}
|
||||
|
||||
pub struct PPIPackage<'gl> {
|
||||
draw_helper: bool,
|
||||
ppi_config: PPIModuleConfig,
|
||||
ppi_attach: Attach<'gl>,
|
||||
line_attach: Attach<'gl>,
|
||||
tick_attach: Attach<'gl>,
|
||||
ppi_data: CachedData<Data>,
|
||||
}
|
||||
|
||||
impl<'gl> PPIPackage<'gl> {
|
||||
fn new(ppi_config: PPIModuleConfig, ppi_attach: Attach<'gl>, data: &CachedData<Data>) -> Self {
|
||||
fn new(
|
||||
ppi_config: PPIModuleConfig,
|
||||
ppi_attach: Attach<'gl>,
|
||||
line_attach: Attach<'gl>,
|
||||
tick_attach: Attach<'gl>,
|
||||
data: &CachedData<Data>,
|
||||
) -> Self {
|
||||
Self {
|
||||
draw_helper: true,
|
||||
ppi_config,
|
||||
ppi_attach,
|
||||
line_attach,
|
||||
tick_attach,
|
||||
ppi_data: Rc::clone(data),
|
||||
}
|
||||
}
|
||||
@ -192,8 +284,17 @@ impl<'gl> ModuleCursor for PPIPackage<'gl> {
|
||||
ui.checkbox("three d?", &mut is_three_d);
|
||||
ui.separator();
|
||||
|
||||
let mut line_width = self.ppi_config.line_width;
|
||||
let mut line_antialias = self.ppi_config.line_antialias;
|
||||
|
||||
ui.text("PPI Line Config");
|
||||
ui.slider("line width", 0.1, 10.0, &mut line_width);
|
||||
ui.slider("line ana", 0.1, 10.0, &mut line_antialias);
|
||||
|
||||
self.ppi_config.set_layer(layer);
|
||||
self.ppi_config.set_is_three_d(is_three_d);
|
||||
self.ppi_config.set_line_width(line_width);
|
||||
self.ppi_config.set_line_antialias(line_antialias);
|
||||
self.ppi_config.changed_any()
|
||||
}
|
||||
|
||||
@ -202,3 +303,79 @@ impl<'gl> ModuleCursor for PPIPackage<'gl> {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[track]
|
||||
#[derive(PartialEq)]
|
||||
pub struct PPIModuleConfig {
|
||||
pub ticks: bool,
|
||||
pub line_color: [f32; 4],
|
||||
pub line_width: f32,
|
||||
pub line_antialias: f32,
|
||||
pub layer: usize,
|
||||
pub colors: Vec<[u8; 4]>,
|
||||
pub color_range: [f32; 2],
|
||||
pub is_three_d: bool,
|
||||
|
||||
pub tick_label_color: [f32; 4],
|
||||
pub tick_label_size: f32,
|
||||
#[do_not_track]
|
||||
pub unvalid_value: f32,
|
||||
#[do_not_track]
|
||||
pub max_layer: usize,
|
||||
#[do_not_track]
|
||||
pub rdpi: f32,
|
||||
#[do_not_track]
|
||||
pub adpi: f32,
|
||||
}
|
||||
|
||||
impl Default for PPIModuleConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
ticks: true,
|
||||
line_color: [1.0, 1.0, 1.0, 1.0],
|
||||
line_width: 2.0,
|
||||
line_antialias: 2.0,
|
||||
layer: 0,
|
||||
colors: vec![],
|
||||
color_range: [0.0, 0.0],
|
||||
is_three_d: true,
|
||||
unvalid_value: 0.0,
|
||||
tick_label_color: [1.0, 1.0, 1.0, 1.0],
|
||||
tick_label_size: 24.0,
|
||||
max_layer: 0,
|
||||
rdpi: 0.0,
|
||||
adpi: 0.0,
|
||||
tracker: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PPIModuleConfig {
|
||||
fn to_ppi_config(&self) -> PPIConfig {
|
||||
PPIConfig {
|
||||
unvalid_value: self.unvalid_value,
|
||||
color_range: self.color_range,
|
||||
colors: self.colors.clone(),
|
||||
layer: self.layer,
|
||||
rdpi: self.rdpi,
|
||||
adpi: self.adpi,
|
||||
three_d: self.is_three_d,
|
||||
}
|
||||
}
|
||||
|
||||
fn to_line_config(&self) -> AggFastPathConfig {
|
||||
AggFastPathConfig {
|
||||
color: self.line_color,
|
||||
linewidth: self.line_width,
|
||||
antialias: self.line_antialias,
|
||||
}
|
||||
}
|
||||
|
||||
fn to_font_config(&self) -> FontConfig {
|
||||
let line_style = LineStyle::default();
|
||||
let mut font_style = FontStyle::default();
|
||||
font_style.size = FontSize::Absolute(self.tick_label_size);
|
||||
font_style.color = self.tick_label_color;
|
||||
FontConfig::Textline(line_style, font_style)
|
||||
}
|
||||
}
|
||||
|
||||
126
src/shaders/agg_path.rs
Normal file
126
src/shaders/agg_path.rs
Normal file
@ -0,0 +1,126 @@
|
||||
use glsl::syntax::ShaderStage;
|
||||
use glsl::syntax::TranslationUnit;
|
||||
use glsl::transpiler::glsl::show_translation_unit;
|
||||
use glsl_quasiquote::glsl;
|
||||
|
||||
use crate::impl_code_piece;
|
||||
|
||||
use super::{trackball::Trackball, CodePiece};
|
||||
|
||||
pub struct AggPathVertex(ShaderStage);
|
||||
|
||||
pub struct AggPathFragment(ShaderStage);
|
||||
|
||||
impl AggPathVertex {
|
||||
pub fn new() -> Self {
|
||||
let mut transform = Trackball::new().0;
|
||||
let raw = glsl! {
|
||||
|
||||
layout(location = 0) in vec3 prev;
|
||||
layout(location = 1) in vec3 curr;
|
||||
layout(location = 2) in vec3 next;
|
||||
layout(location = 3) in float id;
|
||||
|
||||
uniform float antialias;
|
||||
uniform float thickness;
|
||||
uniform vec2 viewport;
|
||||
uniform vec4 color;
|
||||
|
||||
out float v_distance;
|
||||
out vec4 v_color;
|
||||
|
||||
void main() {
|
||||
vec4 ndc_prev = transform(position(prev));
|
||||
vec4 ndc_curr = transform(position(curr));
|
||||
vec4 ndc_next = transform(position(next));
|
||||
|
||||
// screen space
|
||||
vec2 screen_prev = viewport * ((ndc_prev.xy/ndc_prev.w) + 1.0)/2.0;
|
||||
vec2 screen_curr = viewport * ((ndc_curr.xy/ndc_curr.w) + 1.0)/2.0;
|
||||
vec2 screen_next = viewport * ((ndc_next.xy/ndc_next.w) + 1.0)/2.0;
|
||||
|
||||
|
||||
vec2 P;
|
||||
float w = thickness/2.0 + antialias;
|
||||
|
||||
if (prev.xy == curr.xy) {
|
||||
vec2 v = normalize(screen_next.xy - screen_curr.xy);
|
||||
vec2 normal = normalize(vec2(-v.y, v.x));
|
||||
P = screen_curr.xy + w*normal*id;
|
||||
} else if (curr.xy == next.xy) {
|
||||
vec2 v = normalize(screen_curr.xy - screen_prev.xy);
|
||||
vec2 normal = normalize(vec2(-v.y, v.x));
|
||||
P = screen_curr.xy + w*normal*id;
|
||||
} else {
|
||||
|
||||
vec2 v0 = normalize(screen_curr.xy - screen_prev.xy);
|
||||
vec2 v1 = normalize(screen_next.xy - screen_curr.xy);
|
||||
vec2 normal = normalize(vec2(-v0.y, v0.x));
|
||||
vec2 tangent = normalize(v0 + v1);
|
||||
|
||||
vec2 miter = vec2(-tangent.y, tangent.x);
|
||||
|
||||
float l = abs(w/dot(miter,normal));
|
||||
P = screen_curr.xy + l*miter*sign(id);
|
||||
}
|
||||
|
||||
v_color = color;
|
||||
|
||||
if (abs(id) > 1.5) v_color.a = 0.0;
|
||||
v_distance = w * id;
|
||||
|
||||
// Back to NDC coordinates
|
||||
gl_Position = vec4(2.0*P/viewport-1.0, ndc_curr.z / ndc_curr.w, 1.0);
|
||||
}
|
||||
};
|
||||
|
||||
transform.extend(raw);
|
||||
|
||||
Self(transform)
|
||||
}
|
||||
}
|
||||
|
||||
impl AggPathFragment {
|
||||
pub fn new() -> Self {
|
||||
let raw = glsl! {
|
||||
uniform float antialias;
|
||||
uniform float thickness;
|
||||
|
||||
in float v_distance;
|
||||
in vec4 v_color;
|
||||
out vec4 fragColor;
|
||||
|
||||
|
||||
vec4 stroke(float distance, float linewidth, float antialias, vec4 fg_color)
|
||||
{
|
||||
vec4 frag_color;
|
||||
float t = linewidth/2.0 - antialias;
|
||||
float signed_distance = distance;
|
||||
float border_distance = abs(signed_distance) - t;
|
||||
float alpha = border_distance/antialias;
|
||||
alpha = exp(-alpha*alpha);
|
||||
|
||||
if( border_distance < 0.0 )
|
||||
frag_color = fg_color;
|
||||
else
|
||||
frag_color = vec4(fg_color.rgb, fg_color.a * alpha);
|
||||
|
||||
return frag_color;
|
||||
}
|
||||
|
||||
vec4 stroke(float distance, float linewidth, float antialias, vec4 fg_color, vec4 bg_color)
|
||||
{
|
||||
return stroke(distance, linewidth, antialias, fg_color);
|
||||
}
|
||||
|
||||
void main() {
|
||||
if (v_color.a == 0) {discard;}
|
||||
fragColor = stroke(v_distance, thickness, antialias, v_color);
|
||||
}
|
||||
};
|
||||
Self(raw)
|
||||
}
|
||||
}
|
||||
|
||||
impl_code_piece!(AggPathVertex, 0);
|
||||
impl_code_piece!(AggPathFragment, 0);
|
||||
216
src/shaders/font.rs
Normal file
216
src/shaders/font.rs
Normal file
@ -0,0 +1,216 @@
|
||||
use super::trackball::Trackball;
|
||||
use super::CodePiece;
|
||||
use crate::impl_code_piece;
|
||||
use glsl::syntax::ShaderStage;
|
||||
use glsl::syntax::TranslationUnit;
|
||||
use glsl::transpiler::glsl::show_translation_unit;
|
||||
use glsl_quasiquote::glsl;
|
||||
|
||||
pub struct FontVertex(pub ShaderStage);
|
||||
|
||||
pub struct FontFragment(pub ShaderStage);
|
||||
|
||||
pub struct FontGeometry(pub ShaderStage);
|
||||
|
||||
impl FontVertex {
|
||||
pub fn new() -> Self {
|
||||
let raw = glsl! {
|
||||
|
||||
// texcoord (left top, right bottom)
|
||||
layout(location = 0) in vec4 texcoord;
|
||||
|
||||
// Relative position (x, y, width, height)
|
||||
layout(location = 1) in vec4 relative_position;
|
||||
|
||||
out VS_OUT {
|
||||
vec4 texcoord;
|
||||
vec4 pos;
|
||||
} vs_out;
|
||||
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
vs_out.texcoord = texcoord;
|
||||
vs_out.pos = relative_position;
|
||||
}
|
||||
};
|
||||
|
||||
Self(raw)
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// Uniforms
|
||||
uniform vec3 location;
|
||||
uniform vec3 anchor;
|
||||
uniform vec2 viewport;
|
||||
|
||||
// Texture Shape
|
||||
uniform vec2 atlas_shape;
|
||||
|
||||
out vec2 v_texCoord;
|
||||
|
||||
in VS_OUT {
|
||||
vec4 texcoord;
|
||||
vec4 pos;
|
||||
} gs_in[];
|
||||
|
||||
void main() {
|
||||
|
||||
vec4 pos = gs_in[0].pos;
|
||||
float x, y, width, hgt;
|
||||
|
||||
// Char position and size
|
||||
x = pos.x;
|
||||
y = pos.y;
|
||||
width = pos.z;
|
||||
hgt = pos.w;
|
||||
|
||||
// texcoord
|
||||
vec2 tex_coord_lt = gs_in[0].texcoord.xy / atlas_shape;
|
||||
vec2 tex_coord_rb = gs_in[0].texcoord.zw / atlas_shape;
|
||||
|
||||
// Char Size
|
||||
vec2 size = vec2(width, hgt);
|
||||
|
||||
// Base Text Location
|
||||
vec3 base_pos = location + anchor;
|
||||
|
||||
// base_pos in NDC
|
||||
vec4 ndc_base_pos = transform(position(base_pos));
|
||||
|
||||
// Screen Space
|
||||
vec2 screen_base_pos = viewport * ((ndc_base_pos.xy / ndc_base_pos.w) + 1.0) / 2.0;
|
||||
|
||||
// Billboard Type
|
||||
vec2 left_top = screen_base_pos + vec2(x, y);
|
||||
vec2 right_bottom = left_top + size;
|
||||
|
||||
vec2 ndc_left_top = (2.0 * left_top / viewport - 1.0);
|
||||
vec2 ndc_right_bottom = (2.0 * right_bottom / viewport - 1.0);
|
||||
|
||||
// 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);
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = vec4(ndc_right_bottom.xy, ndc_base_pos.z / ndc_base_pos.w, 1.0);
|
||||
v_texCoord = tex_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;
|
||||
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);
|
||||
EmitVertex();
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
transform.extend(raw);
|
||||
|
||||
Self(transform)
|
||||
}
|
||||
}
|
||||
|
||||
impl FontFragment {
|
||||
pub fn new() -> Self {
|
||||
let raw = glsl! {
|
||||
uniform sampler2D atlas_data;
|
||||
in vec2 v_texCoord;
|
||||
|
||||
uniform vec4 uClipUV;
|
||||
uniform vec4 uSdfConfig;
|
||||
uniform int uMode;
|
||||
uniform vec4 uBorder;
|
||||
uniform vec4 uStroke;
|
||||
uniform vec4 uFill;
|
||||
|
||||
float getUVScale(vec2 sdfUV) {
|
||||
float dx = dFdx(sdfUV.x);
|
||||
float dy = dFdy(sdfUV.y);
|
||||
return (sqrt(dx * dx + dy * dy) + sqrt(dy * dy + dx * dx)) * 0.5;
|
||||
}
|
||||
|
||||
struct SDF {
|
||||
float outer;
|
||||
float inner;
|
||||
};
|
||||
|
||||
vec4 getTexture(vec2 uv) {
|
||||
return texture(atlas_data, uv);
|
||||
}
|
||||
|
||||
vec4 getMask(vec4 color, vec2 uv, vec2 st) {
|
||||
return color; // 默认不修改颜色
|
||||
}
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
vec4 fillColor = uFill;
|
||||
vec4 strokeColor = uStroke;
|
||||
|
||||
float scale = getUVScale(v_texCoord);
|
||||
|
||||
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;
|
||||
// float expand = uBorder.x;
|
||||
// float bleed = uBorder.y;
|
||||
|
||||
// float d = (texture.r - 0.75) * sdfRadius;
|
||||
// float s = (d + expand / uSdfConfig.y) / scale + 0.5 + bleed;
|
||||
// sdf = s; // Assuming SDF returns a single float, adjust as necessary
|
||||
|
||||
// if (uMode == -2) {
|
||||
// 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
|
||||
|
||||
// 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);
|
||||
}
|
||||
};
|
||||
|
||||
Self(raw)
|
||||
}
|
||||
}
|
||||
|
||||
impl_code_piece!(FontVertex, 0);
|
||||
impl_code_piece!(FontGeometry, 0);
|
||||
impl_code_piece!(FontFragment, 0);
|
||||
@ -1,4 +1,6 @@
|
||||
pub mod agg_path;
|
||||
pub mod colormap;
|
||||
pub mod font;
|
||||
pub mod math;
|
||||
pub mod polar;
|
||||
pub mod ppi;
|
||||
|
||||
@ -21,6 +21,46 @@ impl Trackball {
|
||||
* trackball_model
|
||||
* position;
|
||||
}
|
||||
|
||||
vec4 position(float x)
|
||||
{
|
||||
return vec4(x, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
vec4 position(float x, float y)
|
||||
{
|
||||
return vec4(x, y, 0.0, 1.0);
|
||||
}
|
||||
|
||||
vec4 position(vec2 xy)
|
||||
{
|
||||
return vec4(xy, 0.0, 1.0);
|
||||
}
|
||||
|
||||
vec4 position(float x, float y, float z)
|
||||
{
|
||||
return vec4(x, y, z, 1.0);
|
||||
}
|
||||
|
||||
vec4 position(vec3 xyz)
|
||||
{
|
||||
return vec4(xyz, 1.0);
|
||||
}
|
||||
|
||||
vec4 position(vec4 xyzw)
|
||||
{
|
||||
return xyzw;
|
||||
}
|
||||
|
||||
vec4 position(vec2 xy, float z)
|
||||
{
|
||||
return vec4(xy, z, 1.0);
|
||||
}
|
||||
|
||||
vec4 position(float x, vec2 yz)
|
||||
{
|
||||
return vec4(x, yz, 1.0);
|
||||
}
|
||||
};
|
||||
|
||||
Self(raw)
|
||||
|
||||
@ -81,11 +81,12 @@ impl LayoutMod for MainLoad {
|
||||
let dsp_size = ui.io().display_size;
|
||||
|
||||
let content_size = ui.content_region_avail();
|
||||
|
||||
// Change the size of the viewport
|
||||
apptyp.main_viewport.set_size(content_size);
|
||||
// context.helper.set_size(content_size, scale[0]);
|
||||
|
||||
let draws = ui.get_window_draw_list();
|
||||
|
||||
draws.channels_split(2, |channels| {
|
||||
channels.set_current(0);
|
||||
let fbo = apptyp.main_viewport.fbo();
|
||||
@ -191,7 +192,7 @@ impl<'gl> LayoutAttach<'gl> for MainLoadAttach<'gl> {
|
||||
programs: &mut crate::pg::Programs<'gl>,
|
||||
helper: &mut Helper,
|
||||
) -> crate::errors::Result<()> {
|
||||
helper.draw_modules(gl, &self.packages);
|
||||
// helper.draw_modules(gl, &self.packages);
|
||||
if self.packages.iter().any(|v| v.need_update) || self.operation.is_need_update() {
|
||||
// Helper task
|
||||
self.main_viewport.bind(gl);
|
||||
@ -201,7 +202,7 @@ impl<'gl> LayoutAttach<'gl> for MainLoadAttach<'gl> {
|
||||
}
|
||||
|
||||
for package in self.packages.iter_mut() {
|
||||
programs.draw_modules(package, &self.operation)?;
|
||||
programs.draw_modules(package, &self.operation, &self.main_viewport)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user