sync
This commit is contained in:
parent
36e355335f
commit
1641585177
22
Cargo.lock
generated
22
Cargo.lock
generated
@ -182,6 +182,17 @@ dependencies = [
|
|||||||
"libloading 0.8.5",
|
"libloading 0.8.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-trait"
|
||||||
|
version = "0.1.83"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.87",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
@ -653,6 +664,13 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "element_bridge"
|
name = "element_bridge"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"flume",
|
||||||
|
"makepad-widgets",
|
||||||
|
"mp_elements",
|
||||||
|
"tokio",
|
||||||
|
"wgpu",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encase"
|
name = "encase"
|
||||||
@ -1693,6 +1711,9 @@ dependencies = [
|
|||||||
name = "mp"
|
name = "mp"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"element_bridge",
|
||||||
|
"futures",
|
||||||
"glam",
|
"glam",
|
||||||
"log",
|
"log",
|
||||||
"makepad-widgets",
|
"makepad-widgets",
|
||||||
@ -1735,6 +1756,7 @@ dependencies = [
|
|||||||
"flume",
|
"flume",
|
||||||
"glam",
|
"glam",
|
||||||
"image",
|
"image",
|
||||||
|
"log",
|
||||||
"mp_core",
|
"mp_core",
|
||||||
"pollster",
|
"pollster",
|
||||||
"quick_cache",
|
"quick_cache",
|
||||||
|
|||||||
24
backup.txt
Normal file
24
backup.txt
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
let data = DATAPOOL
|
||||||
|
.get_or_load(
|
||||||
|
"/Users/tsuki/Desktop/Z_RADR_I_X5775_20230726180000_O_DOR-XPD-CAP-FMT.BIN.zip",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let first_block = data.get(0).unwrap();
|
||||||
|
let first_block: &Data = &(*first_block);
|
||||||
|
|
||||||
|
if let Ok(d) = first_block.try_into() {
|
||||||
|
let attachment = {
|
||||||
|
// Ctx
|
||||||
|
let mut pipelines = GIAPP.pipelines();
|
||||||
|
let ppi = pipelines.ppi();
|
||||||
|
|
||||||
|
GIAPP.load_data(
|
||||||
|
ppi,
|
||||||
|
d,
|
||||||
|
&PPIConfig {
|
||||||
|
colormap: vec![[1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0]],
|
||||||
|
color_range: [0.0, 1.0],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -4,3 +4,8 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
mp_elements = { path = "../mp_elements", version = "*" }
|
||||||
|
makepad-widgets = { git = "https://github.com/makepad/makepad", branch = "rik", version = "0.6.0" }
|
||||||
|
flume = "0.11.1"
|
||||||
|
wgpu = "23.0.0"
|
||||||
|
tokio = { version = "1.41.1", features = ["sync"] }
|
||||||
|
|||||||
@ -1,14 +1,70 @@
|
|||||||
pub fn add(left: u64, right: u64) -> u64 {
|
use makepad_widgets::{makepad_shader_compiler::builtin, Cx, Texture};
|
||||||
left + right
|
use mp_elements::{
|
||||||
|
app::{Ctx, DrawList, RenderWindow},
|
||||||
|
App,
|
||||||
|
};
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
pub use mp_elements::app::Window;
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct TextureBridge {
|
||||||
|
dirty: bool,
|
||||||
|
_buffer: Arc<tokio::sync::Mutex<Vec<u8>>>,
|
||||||
|
window: Arc<RenderWindow>,
|
||||||
|
_texture: Texture,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
impl TextureBridge {
|
||||||
mod tests {
|
pub fn new(texture: Texture, app: &App, window: Window) -> Self {
|
||||||
use super::*;
|
let window = app.create_window(window);
|
||||||
|
Self {
|
||||||
|
dirty: true,
|
||||||
|
_buffer: Arc::new(tokio::sync::Mutex::new(vec![0u8; 256 * 256 * 4])),
|
||||||
|
window: Arc::new(window),
|
||||||
|
_texture: texture,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
pub fn texture(&self) -> &Texture {
|
||||||
fn it_works() {
|
&self._texture
|
||||||
let result = add(2, 2);
|
}
|
||||||
assert_eq!(result, 4);
|
|
||||||
|
pub fn window(&self) -> &RenderWindow {
|
||||||
|
&self.window
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_window(&self) -> Arc<RenderWindow> {
|
||||||
|
self.window.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn draw(&mut self, app: &App, draw_list: DrawList) {
|
||||||
|
app.draw(&self.window, draw_list).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn load_data(buffer: Arc<Mutex<Vec<u8>>>, ctx: &Ctx, render_window: &RenderWindow) {
|
||||||
|
let output = &render_window.output().output_buffer;
|
||||||
|
|
||||||
|
let (sender, receiver) = flume::bounded(1);
|
||||||
|
let slice = output.slice(..);
|
||||||
|
slice.map_async(wgpu::MapMode::Read, move |r| sender.send(r).unwrap());
|
||||||
|
|
||||||
|
let device = &ctx.device;
|
||||||
|
device.poll(wgpu::Maintain::wait()).panic_on_timeout();
|
||||||
|
receiver.recv_async().await.unwrap().unwrap();
|
||||||
|
|
||||||
|
{
|
||||||
|
let view = slice.get_mapped_range();
|
||||||
|
let mut buffer = buffer.lock().unwrap();
|
||||||
|
buffer.copy_from_slice(&view[..]);
|
||||||
|
}
|
||||||
|
output.unmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_texture(&self, cx: &mut Cx, buffer: Vec<u8>) {
|
||||||
|
self._texture.put_back_vec_u8(cx, buffer, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn buffer(&self) -> Arc<tokio::sync::Mutex<Vec<u8>>> {
|
||||||
|
self._buffer.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,3 +15,7 @@ tracing = "0.1.40"
|
|||||||
tracing-subscriber = "0.3.18"
|
tracing-subscriber = "0.3.18"
|
||||||
mp_elements = { path = "../mp_elements", version = "*" }
|
mp_elements = { path = "../mp_elements", version = "*" }
|
||||||
tokio = { version = "1.41.1", features = ["full"] }
|
tokio = { version = "1.41.1", features = ["full"] }
|
||||||
|
|
||||||
|
element_bridge = { path = "../element_bridge", version = "*" }
|
||||||
|
futures = "0.3.31"
|
||||||
|
async-trait = "0.1.83"
|
||||||
|
|||||||
107
mp/src/app.rs
107
mp/src/app.rs
@ -1,8 +1,17 @@
|
|||||||
|
use crate::widgets::area::TAreaWidgetRefExt;
|
||||||
|
use crate::windows_manager::WindowsManager;
|
||||||
|
use crate::{render_task::RenderTasks, PLUGIN_MANAGER, RUNTIME};
|
||||||
|
use crate::{DATAPOOL, GIAPP};
|
||||||
|
use ::log::info;
|
||||||
use makepad_widgets::makepad_micro_serde::*;
|
use makepad_widgets::makepad_micro_serde::*;
|
||||||
use makepad_widgets::*;
|
use makepad_widgets::*;
|
||||||
use mp_elements::elements::Element;
|
use mp_core::Data;
|
||||||
|
use mp_elements::elements::ppi::PPIConfig;
|
||||||
|
use mp_elements::elements::PPI;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use window_menu::WindowMenuWidgetRefExt;
|
||||||
|
|
||||||
use crate::{DATAPOOL, GIAPP, PLUGIN_MANAGER};
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
live_design! {
|
live_design! {
|
||||||
import makepad_widgets::base::*;
|
import makepad_widgets::base::*;
|
||||||
@ -48,6 +57,29 @@ live_design! {
|
|||||||
|
|
||||||
<MainView>{}
|
<MainView>{}
|
||||||
}
|
}
|
||||||
|
window_menu = {
|
||||||
|
main = Main {items: [app, file, window, help]}
|
||||||
|
|
||||||
|
app = Sub {name: "MP", items: [about, line, settings, line, quit]}
|
||||||
|
about = Item {name: "About Makepad Studio", enabled: false}
|
||||||
|
settings = Item {name: "Settings", enabled: false}
|
||||||
|
quit = Item {name: "Quit Makepad Studio", key: KeyQ}
|
||||||
|
|
||||||
|
file = Sub {name: "File", items: [open_file, open_window]}
|
||||||
|
open_file = Item {name: "Open File", enabled: true, shift: true, key: KeyO}
|
||||||
|
open_window = Item {name: "Open Folder", enabled: false, shift: true, key: KeyN}
|
||||||
|
|
||||||
|
|
||||||
|
window = Sub {name: "Window", items: [minimize, zoom, line, all_to_front]}
|
||||||
|
minimize = Item {name: "Minimize", enabled: false}
|
||||||
|
zoom = Item {name: "Zoom", enabled: false}
|
||||||
|
all_to_front = Item {name: "Bring All to Front", enabled: false}
|
||||||
|
|
||||||
|
help = Sub {name: "Help", items: [about]}
|
||||||
|
|
||||||
|
line = Line,
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -58,6 +90,10 @@ live_design! {
|
|||||||
pub struct App {
|
pub struct App {
|
||||||
#[live]
|
#[live]
|
||||||
ui: WidgetRef,
|
ui: WidgetRef,
|
||||||
|
#[rust]
|
||||||
|
render_tasks: Arc<Mutex<RenderTasks>>,
|
||||||
|
#[rust]
|
||||||
|
windows_manager: WindowsManager,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LiveRegister for App {
|
impl LiveRegister for App {
|
||||||
@ -65,6 +101,7 @@ impl LiveRegister for App {
|
|||||||
crate::makepad_widgets::live_design(_cx);
|
crate::makepad_widgets::live_design(_cx);
|
||||||
crate::app_ui::live_design(_cx);
|
crate::app_ui::live_design(_cx);
|
||||||
crate::widgets::area::live_design(_cx);
|
crate::widgets::area::live_design(_cx);
|
||||||
|
crate::widgets::renderer::live_design(_cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,31 +111,61 @@ struct AppStateRon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MatchEvent for App {
|
impl MatchEvent for App {
|
||||||
fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions) {
|
// Start UP
|
||||||
use native_dialog::FileDialog;
|
fn handle_startup(&mut self, _cx: &mut Cx) {}
|
||||||
let ui = self.ui.clone();
|
|
||||||
if ui.button(id!(open_modal)).clicked(&actions) {
|
|
||||||
let supported_extensions = PLUGIN_MANAGER.supported_extensions();
|
|
||||||
|
|
||||||
// let file = FileDialog::new()
|
fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions) {}
|
||||||
// .add_filter("Supported files", &supported_extensions)
|
|
||||||
// .show_open_single_file()
|
|
||||||
// .unwrap();
|
|
||||||
|
|
||||||
// if let Some(file) = file {
|
|
||||||
// if let Ok(d) = DATAPOOL.get_or_load(file) {}
|
|
||||||
// }
|
|
||||||
|
|
||||||
ui.modal(id!(modal)).open(cx);
|
|
||||||
// ui.popup_notification(id!(test_noti)).open(cx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppMain for App {
|
impl AppMain for App {
|
||||||
fn handle_event(&mut self, cx: &mut Cx, event: &Event) {
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event) {
|
||||||
self.match_event(cx, event);
|
self.match_event(cx, event);
|
||||||
self.ui.handle_event(cx, event, &mut Scope::empty());
|
self.ui.handle_event(cx, event, &mut Scope::empty());
|
||||||
|
spawn_background(self, event);
|
||||||
|
handle_menu(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn spawn_background(app: &mut App, event: &Event) {
|
||||||
|
match event {
|
||||||
|
Event::Draw(_) => {
|
||||||
|
// Render Task
|
||||||
|
|
||||||
|
info!("Starting background task......");
|
||||||
|
let tasks = app.render_tasks.clone();
|
||||||
|
RUNTIME.spawn(async move {
|
||||||
|
let tasks = tasks.lock().await;
|
||||||
|
tasks.render().await;
|
||||||
|
});
|
||||||
|
let tasks = app.render_tasks.clone();
|
||||||
|
let all_buffers = app.windows_manager.buffer();
|
||||||
|
RUNTIME.spawn(async move {
|
||||||
|
let mut tasks = tasks.lock().await;
|
||||||
|
tasks.listen(all_buffers).await;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_menu(event: &Event) {
|
||||||
|
match event {
|
||||||
|
Event::MacosMenuCommand(command) => {
|
||||||
|
if command == &LiveId::from_str("open_file") {
|
||||||
|
use native_dialog::FileDialog;
|
||||||
|
info!("Open File Dialog");
|
||||||
|
let supported_extensions = PLUGIN_MANAGER.supported_extensions();
|
||||||
|
let file = FileDialog::new()
|
||||||
|
.add_filter("Supported files", &supported_extensions)
|
||||||
|
.show_open_single_file()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
if let Some(file) = file {
|
||||||
|
info!("File: {:?}", file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@ live_design! {
|
|||||||
import makepad_widgets::base::*;
|
import makepad_widgets::base::*;
|
||||||
import makepad_widgets::theme_desktop_dark::*;
|
import makepad_widgets::theme_desktop_dark::*;
|
||||||
import crate::widgets::area::Area;
|
import crate::widgets::area::Area;
|
||||||
|
import crate::widgets::renderer::IRenderer;
|
||||||
|
|
||||||
import makepad_draw::shader::std::*;
|
import makepad_draw::shader::std::*;
|
||||||
|
|
||||||
@ -59,28 +60,28 @@ live_design! {
|
|||||||
y: 0.5
|
y: 0.5
|
||||||
},
|
},
|
||||||
quad = <Area> {
|
quad = <Area> {
|
||||||
draw: {
|
// draw: {
|
||||||
// this example shader is ported from kishimisu's tutorial
|
// // this example shader is ported from kishimisu's tutorial
|
||||||
fn pixel(self) -> vec4 {
|
// fn pixel(self) -> vec4 {
|
||||||
// let uv = self.pos - 0.5;
|
// // let uv = self.pos - 0.5;
|
||||||
// let uv0 = uv;
|
// // let uv0 = uv;
|
||||||
// let finalColor = vec3(0.0);
|
// // let finalColor = vec3(0.0);
|
||||||
|
|
||||||
// let i = 0;
|
// // let i = 0;
|
||||||
// for _i in 0..4 { // you cannot refer to _i inside the for loop; use i instead
|
// // for _i in 0..4 { // you cannot refer to _i inside the for loop; use i instead
|
||||||
// uv = fract(uv * -1.5) - 0.5;
|
// // uv = fract(uv * -1.5) - 0.5;
|
||||||
// let d = length(uv) * exp(-length(uv0));
|
// // let d = length(uv) * exp(-length(uv0));
|
||||||
// let col = Pal::iq2(length(uv0) + float(i) * .4 + self.time * .4);
|
// // let col = Pal::iq2(length(uv0) + float(i) * .4 + self.time * .4);
|
||||||
// d = sin(d*8. + self.time) / 8.;
|
// // d = sin(d*8. + self.time) / 8.;
|
||||||
// d = abs(d);
|
// // d = abs(d);
|
||||||
// d = pow(0.01 / d, 1.2);
|
// // d = pow(0.01 / d, 1.2);
|
||||||
// finalColor += col * d;
|
// // finalColor += col * d;
|
||||||
// i = i+1;
|
// // i = i+1;
|
||||||
|
// // }
|
||||||
|
|
||||||
|
// // return vec4(finalColor ,1);
|
||||||
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// return vec4(finalColor ,1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
44
mp/src/handle_events.rs
Normal file
44
mp/src/handle_events.rs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
use log::*;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
use crate::{app::App, render_task::RenderTasks, windows_manager::WindowsManager, GIAPP, RUNTIME};
|
||||||
|
|
||||||
|
pub async fn register_task(tasks: Arc<Mutex<RenderTasks>>, windows_manager: &mut WindowsManager) {
|
||||||
|
let render_window = {
|
||||||
|
let bridge = windows_manager.get_bridge(0).unwrap();
|
||||||
|
let b = bridge.lock().unwrap();
|
||||||
|
b.render_window().clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Ok(data) = DATAPOOL.get_or_load_async(file).await {
|
||||||
|
// First Block
|
||||||
|
let first_block = data.get(0).unwrap();
|
||||||
|
let first_block: &Data = &*first_block;
|
||||||
|
let pipelines = GIAPP.pipelines();
|
||||||
|
let ppi = pipelines.ppi();
|
||||||
|
let first_block = first_block.try_into().unwrap();
|
||||||
|
|
||||||
|
let attachment = {
|
||||||
|
let ppi: &PPI = &*ppi;
|
||||||
|
let attachment = GIAPP.load_data(
|
||||||
|
ppi,
|
||||||
|
first_block,
|
||||||
|
&PPIConfig {
|
||||||
|
colormap: vec![[1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0]],
|
||||||
|
color_range: [0.0, 1.0],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
attachment
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut tasks = tasks.lock().await;
|
||||||
|
let mut draw_list = mp_elements::app::DrawList::new();
|
||||||
|
let attachment = Arc::new(attachment);
|
||||||
|
draw_list.push(ppi.clone(), attachment);
|
||||||
|
tasks.register_task(0, render_window, draw_list);
|
||||||
|
|
||||||
|
info!("task registered, all {}", tasks.tasks.len());
|
||||||
|
info!("Data loaded");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,12 +1,12 @@
|
|||||||
use mp_elements;
|
use mp_elements;
|
||||||
use tokio::runtime::Runtime;
|
use tokio::runtime::Runtime;
|
||||||
pub mod app;
|
pub mod app;
|
||||||
|
pub mod windows_manager;
|
||||||
pub use makepad_widgets;
|
pub use makepad_widgets;
|
||||||
pub use makepad_widgets::makepad_draw;
|
pub use makepad_widgets::makepad_draw;
|
||||||
pub use makepad_widgets::makepad_platform;
|
pub use makepad_widgets::makepad_platform;
|
||||||
pub mod app_ui;
|
pub mod app_ui;
|
||||||
pub mod render;
|
pub mod render_task;
|
||||||
pub mod shaders;
|
|
||||||
pub mod widgets;
|
pub mod widgets;
|
||||||
|
|
||||||
use mp_core::{config::Setting, datapool::DataPool, plugin_system::PluginManager};
|
use mp_core::{config::Setting, datapool::DataPool, plugin_system::PluginManager};
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
pub struct Camera {}
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
use makepad_widgets::{Cx, Texture, TextureFormat};
|
|
||||||
use mp_core::data::RadarGridData;
|
|
||||||
|
|
||||||
pub enum Data {
|
|
||||||
GridData(GridData),
|
|
||||||
}
|
|
||||||
pub struct GridData {
|
|
||||||
texture: Texture,
|
|
||||||
clear_buffer: bool,
|
|
||||||
shape: Option<Vec<u32>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GridData {
|
|
||||||
pub fn new(cx: &mut Cx) -> Self {
|
|
||||||
let mut texture = Texture::new_with_format(cx, TextureFormat::Unknown);
|
|
||||||
|
|
||||||
texture.texture_id();
|
|
||||||
|
|
||||||
GridData {
|
|
||||||
texture,
|
|
||||||
clear_buffer: true,
|
|
||||||
shape: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update(&mut self, cx: &mut Cx, data: &RadarGridData) {
|
|
||||||
let data = data.data.cast_to::<f32>();
|
|
||||||
self.clear_buffer = false;
|
|
||||||
// self.shape = Some(data.dim().into());
|
|
||||||
// self.texture.put_back_vec_f32(cx, data.into(), None);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear(&mut self) {
|
|
||||||
self.clear_buffer = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn texture(&self) -> &Texture {
|
|
||||||
&self.texture
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<GridData> for Data {
|
|
||||||
fn from(data: GridData) -> Self {
|
|
||||||
Data::GridData(data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
pub mod camera;
|
|
||||||
pub mod data;
|
|
||||||
123
mp/src/render_task.rs
Normal file
123
mp/src/render_task.rs
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
use crate::{
|
||||||
|
widgets::renderer,
|
||||||
|
windows_manager::{AllBuffers, WindowsManager},
|
||||||
|
GIAPP, RUNTIME,
|
||||||
|
};
|
||||||
|
use element_bridge::TextureBridge;
|
||||||
|
use futures::future::BoxFuture;
|
||||||
|
use log::info;
|
||||||
|
use makepad_widgets::{Cx, Texture};
|
||||||
|
use mp_elements::{
|
||||||
|
app::{DrawList, RenderWindow},
|
||||||
|
App,
|
||||||
|
};
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct RenderTasks {
|
||||||
|
pub(crate) tasks: Vec<(tokio::sync::mpsc::Receiver<Vec<u8>>, RenderTask)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RenderTasks {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self { tasks: Vec::new() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_task(&mut self, task: (tokio::sync::mpsc::Receiver<Vec<u8>>, RenderTask)) {
|
||||||
|
self.tasks.push(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn register_task(
|
||||||
|
&mut self,
|
||||||
|
bridge_id: usize,
|
||||||
|
bridge: Arc<RenderWindow>,
|
||||||
|
draw_list: DrawList,
|
||||||
|
) {
|
||||||
|
let (task, receiver) = RenderTask::new(bridge_id, bridge, draw_list);
|
||||||
|
self.push_task((receiver, task));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear(&mut self) {
|
||||||
|
self.tasks.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn render(&self) {
|
||||||
|
// Draw all tasks
|
||||||
|
let futures: Vec<_> = self
|
||||||
|
.tasks
|
||||||
|
.iter()
|
||||||
|
.map(|(_, task)| async {
|
||||||
|
info!("Drawing task");
|
||||||
|
task.draw().await;
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
info!("all tasks: {:?}", futures.len());
|
||||||
|
futures::future::join_all(futures).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn listen(&mut self, manager: AllBuffers) {
|
||||||
|
let mut futures = Vec::new();
|
||||||
|
|
||||||
|
for (receiver, _) in self.tasks.iter_mut() {
|
||||||
|
let manager = manager.lock().unwrap();
|
||||||
|
let buffer = manager.get(&0).unwrap().clone();
|
||||||
|
let future = async move {
|
||||||
|
while let Some(data) = receiver.recv().await {
|
||||||
|
let mut buffer = buffer.lock().await;
|
||||||
|
info!("Received data");
|
||||||
|
buffer.copy_from_slice(&data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
futures.push(Box::pin(future));
|
||||||
|
}
|
||||||
|
|
||||||
|
futures::future::join_all(futures).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RenderTask {
|
||||||
|
// bridge: element_bridge::TextureBridge,
|
||||||
|
bridge_id: usize,
|
||||||
|
sender: tokio::sync::mpsc::Sender<Vec<u8>>,
|
||||||
|
buffer: Arc<Mutex<Vec<u8>>>,
|
||||||
|
render_window: Arc<RenderWindow>,
|
||||||
|
draw_list: DrawList,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RenderTask {
|
||||||
|
pub fn new(
|
||||||
|
bridge_id: usize,
|
||||||
|
bridge_render_window: Arc<RenderWindow>,
|
||||||
|
draw_list: DrawList,
|
||||||
|
) -> (Self, tokio::sync::mpsc::Receiver<Vec<u8>>) {
|
||||||
|
let (sender, receiver) = tokio::sync::mpsc::channel(1);
|
||||||
|
(
|
||||||
|
Self {
|
||||||
|
bridge_id,
|
||||||
|
sender,
|
||||||
|
buffer: Arc::new(Mutex::new(vec![0u8; 256 * 256 * 4])),
|
||||||
|
render_window: bridge_render_window,
|
||||||
|
draw_list,
|
||||||
|
},
|
||||||
|
receiver,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn draw(&self) {
|
||||||
|
GIAPP
|
||||||
|
.draw(&self.render_window, self.draw_list.clone())
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let ctx = GIAPP.ctx();
|
||||||
|
|
||||||
|
TextureBridge::load_data(self.buffer.clone(), ctx, &self.render_window).await;
|
||||||
|
|
||||||
|
let bf = {
|
||||||
|
let buffer = self.buffer.clone();
|
||||||
|
let buffer = buffer.lock().unwrap();
|
||||||
|
buffer.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
self.sender.send(bf).await.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,63 +0,0 @@
|
|||||||
use crate::render::data::GridData;
|
|
||||||
use makepad_widgets::*;
|
|
||||||
|
|
||||||
live_design! {
|
|
||||||
ColorMap = {{ColorMap}} {
|
|
||||||
|
|
||||||
// Cameras
|
|
||||||
uniform view: mat4
|
|
||||||
uniform projection: mat4
|
|
||||||
uniform model: mat4
|
|
||||||
|
|
||||||
uniform conf: vec4
|
|
||||||
|
|
||||||
varing value: float
|
|
||||||
varing range: vec4
|
|
||||||
|
|
||||||
// Data
|
|
||||||
texture data: texture3d
|
|
||||||
// ColorMAPPER
|
|
||||||
textrue color_map: texture1d
|
|
||||||
|
|
||||||
fn get_value_at(self, pos: vec3) -> float {
|
|
||||||
return sampler3d_rt(self.data, pos).r;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn vertex(self) -> vec4 {
|
|
||||||
let v = sampler2d_rt(self.data, )
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pixel(self) -> vec4 {
|
|
||||||
return vec4(1., 0., 0., 1.);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Live, LiveRegister)]
|
|
||||||
pub struct ColorMap {
|
|
||||||
#[deref]
|
|
||||||
draw_vars: DrawVars,
|
|
||||||
#[live]
|
|
||||||
geometry: GeometryQuad2D,
|
|
||||||
#[calc]
|
|
||||||
pub position: Vec3,
|
|
||||||
#[calc]
|
|
||||||
pub value: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LiveHook for ColorMap {
|
|
||||||
fn before_apply(&mut self, cx: &mut Cx, apply: &mut Apply, index: usize, nodes: &[LiveNode]) {
|
|
||||||
self.draw_vars
|
|
||||||
.before_apply_init_shader(cx, apply, index, nodes, &self.geometry);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn after_apply(&mut self, cx: &mut Cx, apply: &mut Apply, index: usize, nodes: &[LiveNode]) {
|
|
||||||
self.draw_vars
|
|
||||||
.after_apply_update_self(cx, apply, index, nodes, &self.geometry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ColorMap {}
|
|
||||||
@ -1,69 +0,0 @@
|
|||||||
use crate::render::camera::Camera;
|
|
||||||
use crate::render::data::GridData;
|
|
||||||
use makepad_widgets::*;
|
|
||||||
|
|
||||||
live_design! {
|
|
||||||
PPI = {{PPI}} {
|
|
||||||
|
|
||||||
// Cameras
|
|
||||||
uniform view: mat4
|
|
||||||
uniform projection: mat4
|
|
||||||
uniform model: mat4
|
|
||||||
|
|
||||||
uniform conf: vec4
|
|
||||||
|
|
||||||
varing value: float
|
|
||||||
varing range: vec4
|
|
||||||
|
|
||||||
// Data
|
|
||||||
texture data: texture2d
|
|
||||||
|
|
||||||
// ColorMAPPER
|
|
||||||
textrue color_map: texture2d
|
|
||||||
|
|
||||||
fn get_value_at(self, pos: vec3) -> float {
|
|
||||||
return sampler3d(self.data, pos).r;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn vertex(self) -> vec4 {
|
|
||||||
let v = sampler2d_rt(self.data, )
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pixel(self) -> vec4 {
|
|
||||||
return vec4(1., 0., 0., 1.);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Live, LiveRegister)]
|
|
||||||
pub struct PPI {
|
|
||||||
#[deref]
|
|
||||||
pub draw_vars: DrawVars,
|
|
||||||
#[live]
|
|
||||||
geometry: GeometryQuad2D,
|
|
||||||
#[calc]
|
|
||||||
pub position: Vec3,
|
|
||||||
#[calc]
|
|
||||||
pub value: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LiveHook for PPI {
|
|
||||||
fn before_apply(&mut self, cx: &mut Cx, apply: &mut Apply, index: usize, nodes: &[LiveNode]) {
|
|
||||||
self.draw_vars
|
|
||||||
.before_apply_init_shader(cx, apply, index, nodes, &self.geometry);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn after_apply(&mut self, cx: &mut Cx, apply: &mut Apply, index: usize, nodes: &[LiveNode]) {
|
|
||||||
self.draw_vars
|
|
||||||
.after_apply_update_self(cx, apply, index, nodes, &self.geometry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PPI {
|
|
||||||
pub fn update_draw_call_vars(&mut self, camera: &Camera, data: &GridData) {
|
|
||||||
self.draw_vars.texture_slots[0] = Some(data.texture().clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,6 +1,16 @@
|
|||||||
|
use std::cell::RefCell;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
use crate::windows_manager::WindowId;
|
||||||
|
use crate::windows_manager::WindowsManager;
|
||||||
|
use crate::GIAPP;
|
||||||
|
use element_bridge::{TextureBridge, Window};
|
||||||
use makepad_widgets::makepad_derive_widget::*;
|
use makepad_widgets::makepad_derive_widget::*;
|
||||||
use makepad_widgets::makepad_draw::*;
|
use makepad_widgets::makepad_draw::*;
|
||||||
use makepad_widgets::widget::*;
|
use makepad_widgets::widget::*;
|
||||||
|
use mp_elements::renderer::camera::Camera;
|
||||||
|
use mp_elements::renderer::projection::Projection;
|
||||||
|
|
||||||
live_design! {
|
live_design! {
|
||||||
Area = {{TArea}} {}
|
Area = {{TArea}} {}
|
||||||
@ -17,32 +27,81 @@ pub struct TArea {
|
|||||||
layout: Layout,
|
layout: Layout,
|
||||||
#[live]
|
#[live]
|
||||||
time: f32,
|
time: f32,
|
||||||
// #[rust]
|
|
||||||
// next_frame: NextFrame,
|
#[rust]
|
||||||
|
bridge: Option<Arc<Mutex<TextureBridge>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LiveHook for TArea {
|
#[derive(Debug, Clone)]
|
||||||
fn after_new_from_doc(&mut self, cx: &mut Cx) {
|
pub enum Status<T> {
|
||||||
// starts the animation cycle on startup
|
Share(std::rc::Rc<RefCell<T>>),
|
||||||
// self.next_frame = cx.new_next_frame();
|
Own(T),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct TAreaState {
|
||||||
|
pub time: f32,
|
||||||
|
pub camera: Status<Camera>,
|
||||||
|
pub bridge: Option<TextureBridge>,
|
||||||
|
pub projection: Projection,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TAreaState {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
time: 0.0,
|
||||||
|
camera: Status::Own(Camera::default()),
|
||||||
|
bridge: None,
|
||||||
|
projection: Projection::default(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TAreaState {
|
||||||
|
pub fn set_camera<F: FnOnce(&mut Camera)>(&mut self, f: F) {
|
||||||
|
match self.camera {
|
||||||
|
Status::Share(ref camera) => {
|
||||||
|
f(&mut camera.borrow_mut());
|
||||||
|
}
|
||||||
|
Status::Own(ref mut camera) => {
|
||||||
|
f(camera);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resize(&mut self, width: f32, height: f32) {
|
||||||
|
self.projection.resize(width as u32, height as u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_bridge(&mut self, bridge: TextureBridge) {
|
||||||
|
self.bridge = Some(bridge);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_bridge(&mut self, cx: &mut Cx, window: Window) {
|
||||||
|
let texture = Texture::new_with_format(
|
||||||
|
cx,
|
||||||
|
TextureFormat::VecRGBAf32 {
|
||||||
|
width: window.width as usize,
|
||||||
|
height: window.height as usize,
|
||||||
|
data: None,
|
||||||
|
updated: TextureUpdated::Full,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
let bridge = TextureBridge::new(texture, &GIAPP, window);
|
||||||
|
self.bridge = Some(bridge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LiveHook for TArea {}
|
||||||
|
|
||||||
#[derive(Clone, DefaultNone)]
|
#[derive(Clone, DefaultNone)]
|
||||||
pub enum MyWidgetAction {
|
pub enum MyWidgetAction {
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for TArea {
|
impl Widget for TArea {
|
||||||
fn handle_event(&mut self, cx: &mut Cx, event: &Event, _scope: &mut Scope) {
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event, _scope: &mut Scope) {}
|
||||||
// if let Some(ne) = self.next_frame.is_event(event) {
|
|
||||||
// // update time to use for animation
|
|
||||||
// self.time = (ne.time * 0.001).fract() as f32;
|
|
||||||
// // force updates, so that we can animate in the absence of user-generated events
|
|
||||||
// self.redraw(cx);
|
|
||||||
// self.next_frame = cx.new_next_frame();
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn draw_walk(&mut self, cx: &mut Cx2d, _scope: &mut Scope, walk: Walk) -> DrawStep {
|
fn draw_walk(&mut self, cx: &mut Cx2d, _scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
self.draw.begin(cx, walk, self.layout);
|
self.draw.begin(cx, walk, self.layout);
|
||||||
@ -50,3 +109,49 @@ impl Widget for TArea {
|
|||||||
DrawStep::done()
|
DrawStep::done()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TArea {
|
||||||
|
fn set_bridge(&mut self, bridge: Arc<Mutex<TextureBridge>>) {
|
||||||
|
self.bridge = Some(bridge);
|
||||||
|
self.draw
|
||||||
|
.draw_vars
|
||||||
|
.set_texture(0, self.bridge.as_ref().unwrap().lock().unwrap().texture());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_bridge(&mut self, cx: &mut Cx, manager: &mut WindowsManager) {
|
||||||
|
let window_id = WindowId::new("Primary");
|
||||||
|
|
||||||
|
// let height = self.walk.height.
|
||||||
|
// let width = self.walk.width.fixed_or_zero();
|
||||||
|
let height = 256;
|
||||||
|
let width = 256;
|
||||||
|
|
||||||
|
let window = Window {
|
||||||
|
height: height as u32,
|
||||||
|
width: width as u32,
|
||||||
|
};
|
||||||
|
|
||||||
|
let texture = Texture::new_with_format(
|
||||||
|
cx,
|
||||||
|
TextureFormat::VecRGBAf32 {
|
||||||
|
width: window.width as usize,
|
||||||
|
height: window.height as usize,
|
||||||
|
data: None,
|
||||||
|
updated: TextureUpdated::Full,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
let bridge = TextureBridge::new(texture, &GIAPP, window);
|
||||||
|
let (_, bridge) = manager.add_window(window_id, bridge);
|
||||||
|
|
||||||
|
self.set_bridge(bridge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TAreaRef {
|
||||||
|
pub fn init_bridge(&self, cx: &mut Cx, manager: &mut WindowsManager) {
|
||||||
|
if let Some(mut bridge) = self.borrow_mut() {
|
||||||
|
bridge.init_bridge(cx, manager);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1 +1,2 @@
|
|||||||
pub mod area;
|
pub mod area;
|
||||||
|
pub mod renderer;
|
||||||
|
|||||||
110
mp/src/widgets/renderer.rs
Normal file
110
mp/src/widgets/renderer.rs
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
|
use crate::GIAPP;
|
||||||
|
use element_bridge::{TextureBridge, Window};
|
||||||
|
use makepad_widgets::makepad_derive_widget::*;
|
||||||
|
use makepad_widgets::makepad_draw::*;
|
||||||
|
use makepad_widgets::widget::*;
|
||||||
|
use mp_elements::renderer::camera::Camera;
|
||||||
|
use mp_elements::renderer::projection::Projection;
|
||||||
|
|
||||||
|
live_design! {
|
||||||
|
IRenderer = {{Renderer}} {
|
||||||
|
|
||||||
|
import crate::widgets::area::Area;
|
||||||
|
<Area> {
|
||||||
|
draw: {
|
||||||
|
fn pixel(self) -> vec4 {
|
||||||
|
return mix(#7,#4,self.pos.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Live, Widget)]
|
||||||
|
pub struct Renderer {
|
||||||
|
#[redraw]
|
||||||
|
#[live]
|
||||||
|
draw: DrawQuad,
|
||||||
|
#[walk]
|
||||||
|
walk: Walk,
|
||||||
|
#[layout]
|
||||||
|
layout: Layout,
|
||||||
|
#[rust]
|
||||||
|
state: RenderState,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Status<T> {
|
||||||
|
Share(std::rc::Rc<RefCell<T>>),
|
||||||
|
Own(T),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct RenderState {
|
||||||
|
pub time: f32,
|
||||||
|
pub camera: Status<Camera>,
|
||||||
|
pub bridge: Option<TextureBridge>,
|
||||||
|
pub projection: Projection,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for RenderState {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
time: 0.0,
|
||||||
|
camera: Status::Own(Camera::default()),
|
||||||
|
bridge: None,
|
||||||
|
projection: Projection::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RenderState {
|
||||||
|
pub fn set_camera<F: FnOnce(&mut Camera)>(&mut self, f: F) {
|
||||||
|
match self.camera {
|
||||||
|
Status::Share(ref camera) => {
|
||||||
|
f(&mut camera.borrow_mut());
|
||||||
|
}
|
||||||
|
Status::Own(ref mut camera) => {
|
||||||
|
f(camera);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resize(&mut self, width: f32, height: f32) {
|
||||||
|
self.projection.resize(width as u32, height as u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_bridge(&mut self, bridge: TextureBridge) {
|
||||||
|
self.bridge = Some(bridge);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_bridge(&mut self, cx: &mut Cx, window: Window) {
|
||||||
|
let texture = Texture::new_with_format(
|
||||||
|
cx,
|
||||||
|
TextureFormat::VecRGBAf32 {
|
||||||
|
width: window.width as usize,
|
||||||
|
height: window.height as usize,
|
||||||
|
data: None,
|
||||||
|
updated: TextureUpdated::Full,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
let bridge = TextureBridge::new(texture, &GIAPP, window);
|
||||||
|
self.bridge = Some(bridge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LiveHook for Renderer {}
|
||||||
|
|
||||||
|
impl Widget for Renderer {
|
||||||
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event, _scope: &mut Scope) {}
|
||||||
|
|
||||||
|
fn draw_walk(&mut self, cx: &mut Cx2d, _scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
self.draw.begin(cx, walk, self.layout);
|
||||||
|
self.draw.end(cx);
|
||||||
|
DrawStep::done()
|
||||||
|
}
|
||||||
|
}
|
||||||
73
mp/src/windows_manager.rs
Normal file
73
mp/src/windows_manager.rs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
};
|
||||||
|
|
||||||
|
use element_bridge::TextureBridge;
|
||||||
|
|
||||||
|
pub type AllBuffers = Arc<Mutex<HashMap<usize, Arc<tokio::sync::Mutex<Vec<u8>>>>>>;
|
||||||
|
|
||||||
|
#[derive(Eq, Hash, PartialEq)]
|
||||||
|
pub struct WindowId {
|
||||||
|
id: u64,
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct WindowsManager {
|
||||||
|
inner: HashMap<WindowId, Arc<Mutex<TextureBridge>>>,
|
||||||
|
|
||||||
|
all_bridges: Vec<(usize, Arc<Mutex<TextureBridge>>)>,
|
||||||
|
|
||||||
|
all_revelant_buffers: Arc<Mutex<HashMap<usize, Arc<tokio::sync::Mutex<Vec<u8>>>>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WindowsManager {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
inner: HashMap::new(),
|
||||||
|
all_bridges: Vec::new(),
|
||||||
|
all_revelant_buffers: Arc::new(Mutex::new(HashMap::new())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_window(
|
||||||
|
&mut self,
|
||||||
|
id: WindowId,
|
||||||
|
bridge: TextureBridge,
|
||||||
|
) -> (usize, Arc<Mutex<TextureBridge>>) {
|
||||||
|
let bridge = Arc::new(Mutex::new(bridge));
|
||||||
|
self.inner.insert(id, bridge.clone());
|
||||||
|
|
||||||
|
let new_id = self.all_bridges.len();
|
||||||
|
self.all_bridges.push((new_id, bridge.clone()));
|
||||||
|
|
||||||
|
let buffer = {
|
||||||
|
let bridge = bridge.lock().unwrap();
|
||||||
|
bridge.buffer()
|
||||||
|
};
|
||||||
|
|
||||||
|
// self.all_revelant_buffers.push((new_id, buffer));
|
||||||
|
self.all_revelant_buffers
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.insert(new_id, buffer);
|
||||||
|
(new_id, bridge)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_bridge(&self, id: usize) -> Option<Arc<Mutex<TextureBridge>>> {
|
||||||
|
self.all_bridges.get(id).map(|(_, bridge)| bridge.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn buffer(&self) -> AllBuffers {
|
||||||
|
self.all_revelant_buffers.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WindowId {
|
||||||
|
pub fn new<S: Into<String>>(name: S) -> Self {
|
||||||
|
Self {
|
||||||
|
id: 0,
|
||||||
|
name: name.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,15 +6,17 @@ edition = "2021"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
bytemuck = { version = "1.19.0", features = ["derive"] }
|
bytemuck = { version = "1.19.0", features = ["derive"] }
|
||||||
glam = { version = "0.29.2", features = ["bytemuck"] }
|
glam = { version = "0.29.2", features = ["bytemuck"] }
|
||||||
regex = "1.11.1"
|
|
||||||
wgpu = "23.0.0"
|
wgpu = "23.0.0"
|
||||||
mp_core = { path = "../mp_core", version = "*" }
|
mp_core = { path = "../mp_core", version = "*" }
|
||||||
flume = "0.11.1"
|
|
||||||
pollster = "0.4.0"
|
|
||||||
quick_cache = "0.6.9"
|
quick_cache = "0.6.9"
|
||||||
encase = { version = "0.10.0", features = ["glam"] }
|
encase = { version = "0.10.0", features = ["glam"] }
|
||||||
image = "0.25.5"
|
image = "0.25.5"
|
||||||
rust-embed = "8.5.0"
|
rust-embed = "8.5.0"
|
||||||
|
flume = "0.11.1"
|
||||||
|
log = "0.4.22"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
regex = "1.11.1"
|
regex = "1.11.1"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
pollster = "0.4.0"
|
||||||
|
|||||||
@ -22,6 +22,11 @@ fn main() {
|
|||||||
println!("cargo:rerun-if-changed={}", path.display());
|
println!("cargo:rerun-if-changed={}", path.display());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let path_name = path.file_stem().unwrap().to_str().unwrap();
|
||||||
|
if path_name.contains("merged") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let merged_shader = merge_shader(&path.display().to_string(), &shader_path_base);
|
let merged_shader = merge_shader(&path.display().to_string(), &shader_path_base);
|
||||||
|
|
||||||
let out_path = Path::new(&crate_path)
|
let out_path = Path::new(&crate_path)
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 53 KiB |
@ -1,20 +1,20 @@
|
|||||||
@group(1) @binding(0) var color_map_texture: texture_2d<f32>;
|
@group(1) @binding(0) var color_map_texture: texture_1d<f32>;
|
||||||
@group(1) @binding(1) var color_map_sampler: sampler;
|
@group(1) @binding(1) var color_map_sampler: sampler;
|
||||||
@group(1) @binding(2) var<uniform> color_map_params: ColorMapParams;
|
@group(1) @binding(2) var<uniform> color_map_params: ColorMapParams;
|
||||||
|
|
||||||
struct ColorMapParams {
|
struct ColorMapParams {
|
||||||
color_count: u32,
|
color_count: u32,
|
||||||
value_min: f32,
|
value_min: f32,
|
||||||
value_max: f32
|
value_max: f32,
|
||||||
invalid_value: f32
|
invalid_value: f32
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_idx(ratio: f32) -> f32 {
|
fn find_idx(ratio: f32) -> f32 {
|
||||||
var sum = 0.0;
|
var sum = 0.0;
|
||||||
var i = 0.0;
|
var i = 0.0;
|
||||||
var count = (color_map_params.color_count - 1) as f32;
|
let count = f32(color_map_params.color_count - 1);
|
||||||
while (ratio > sum) {
|
while (ratio > sum) {
|
||||||
sum += textureSample(color_map_texture, color_map_sampler, vec2<f32>(i / count, 0.0)).r;
|
sum += textureSample(color_map_texture, color_map_sampler, i / count).r;
|
||||||
i += 1.0;
|
i += 1.0;
|
||||||
}
|
}
|
||||||
return i / count;
|
return i / count;
|
||||||
@ -22,8 +22,8 @@ fn find_idx(ratio: f32) -> f32 {
|
|||||||
|
|
||||||
|
|
||||||
fn linear_colormap(value: f32) -> vec4f {
|
fn linear_colormap(value: f32) -> vec4f {
|
||||||
var v = clamp((value - color_map_params.value_min) / (color_map_params.value_max - color_map_params.value_min), 0.0, 1.0);
|
let v = clamp((value - color_map_params.value_min) / (color_map_params.value_max - color_map_params.value_min), 0.0, 1.0);
|
||||||
float idx = find_idx(v);
|
let idx = find_idx(v);
|
||||||
let c0: vec3f = textureSample(color_map_texture, color_map_sampler, vec2<f32>(idx, 0.0)).rgb;
|
let c0 = textureSample(color_map_texture, color_map_sampler, idx).rgb;
|
||||||
return vec4f(c0, 1.0);
|
return vec4f(c0, 1.0);
|
||||||
}
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
#include "constants.wgsl";
|
#include "constants.wgsl";
|
||||||
|
#include "colormap.wgsl";
|
||||||
// Common Uniforms
|
// Common Uniforms
|
||||||
// common_tools
|
// common_tools
|
||||||
// model_matrix: mat4,
|
// model_matrix: mat4,
|
||||||
@ -12,9 +13,9 @@
|
|||||||
// light_intensity: float,
|
// light_intensity: float,
|
||||||
|
|
||||||
// Uniforms
|
// Uniforms
|
||||||
@group(1) @binding(0) var<uniform> params: UniformParams;
|
@group(2) @binding(0) var<uniform> params: UniformParams;
|
||||||
// Data Buffer
|
// Data Buffer
|
||||||
@group(1) @binding(1) var<storage> data: array<f32>;
|
@group(2) @binding(1) var<storage> data: array<f32>;
|
||||||
|
|
||||||
struct UniformParams {
|
struct UniformParams {
|
||||||
origin: vec4f
|
origin: vec4f
|
||||||
@ -36,8 +37,7 @@ fn vertex(
|
|||||||
var out: VertexOutput;
|
var out: VertexOutput;
|
||||||
|
|
||||||
// Transform position
|
// Transform position
|
||||||
out.position = common_tools.proj_matrix * common_tools.view_matrix * common_tools.model_matrix * vec4f(position, 1.0);
|
out.position = vec4(position.xyz, 1.0);
|
||||||
// out.position = vec4(position.xyz, 1.0);
|
|
||||||
out.r_range = r_range;
|
out.r_range = r_range;
|
||||||
let idx = u32(position.w);
|
let idx = u32(position.w);
|
||||||
out.idx = idx;
|
out.idx = idx;
|
||||||
@ -57,8 +57,8 @@ fn fragment(input: VertexOutput) -> @location(0) vec4f {
|
|||||||
// Sample data texture
|
// Sample data texture
|
||||||
let value = data[input.idx];
|
let value = data[input.idx];
|
||||||
let ear = polar_forward(input.position.xyz);
|
let ear = polar_forward(input.position.xyz);
|
||||||
// var color = linear_colormap(value);
|
|
||||||
|
|
||||||
|
// let color = linear_colormap(value);
|
||||||
var color = clamp(value / 75.0, 0.0, 1.0);
|
var color = clamp(value / 75.0, 0.0, 1.0);
|
||||||
|
|
||||||
// let r = ear.x;
|
// let r = ear.x;
|
||||||
|
|||||||
@ -26,6 +26,35 @@ const HALF_PI:f32 = 1.57079632679489661923132169163975144;
|
|||||||
const LOG2:f32 = 0.693147180559945309417232121458176568;
|
const LOG2:f32 = 0.693147180559945309417232121458176568;
|
||||||
const LOG10:f32 = 2.30258509299404568401799145468436421;
|
const LOG10:f32 = 2.30258509299404568401799145468436421;
|
||||||
|
|
||||||
|
@group(1) @binding(0) var color_map_texture: texture_1d<f32>;
|
||||||
|
@group(1) @binding(1) var color_map_sampler: sampler;
|
||||||
|
@group(1) @binding(2) var<uniform> color_map_params: ColorMapParams;
|
||||||
|
|
||||||
|
struct ColorMapParams {
|
||||||
|
color_count: u32,
|
||||||
|
value_min: f32,
|
||||||
|
value_max: f32,
|
||||||
|
invalid_value: f32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_idx(ratio: f32) -> f32 {
|
||||||
|
var sum = 0.0;
|
||||||
|
var i = 0.0;
|
||||||
|
let count = f32(color_map_params.color_count - 1);
|
||||||
|
while (ratio > sum) {
|
||||||
|
sum += textureSample(color_map_texture, color_map_sampler, i / count).r;
|
||||||
|
i += 1.0;
|
||||||
|
}
|
||||||
|
return i / count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn linear_colormap(value: f32) -> vec4f {
|
||||||
|
let v = clamp((value - color_map_params.value_min) / (color_map_params.value_max - color_map_params.value_min), 0.0, 1.0);
|
||||||
|
let idx = find_idx(v);
|
||||||
|
let c0 = textureSample(color_map_texture, color_map_sampler, idx).rgb;
|
||||||
|
return vec4f(c0, 1.0);
|
||||||
|
}
|
||||||
// Common Uniforms
|
// Common Uniforms
|
||||||
// common_tools
|
// common_tools
|
||||||
// model_matrix: mat4,
|
// model_matrix: mat4,
|
||||||
@ -39,9 +68,9 @@ const LOG10:f32 = 2.30258509299404568401799145468436421;
|
|||||||
// light_intensity: float,
|
// light_intensity: float,
|
||||||
|
|
||||||
// Uniforms
|
// Uniforms
|
||||||
@group(1) @binding(0) var<uniform> params: UniformParams;
|
@group(2) @binding(0) var<uniform> params: UniformParams;
|
||||||
// Data Buffer
|
// Data Buffer
|
||||||
@group(1) @binding(1) var<storage> data: array<f32>;
|
@group(2) @binding(1) var<storage> data: array<f32>;
|
||||||
|
|
||||||
struct UniformParams {
|
struct UniformParams {
|
||||||
origin: vec4f
|
origin: vec4f
|
||||||
@ -63,8 +92,7 @@ fn vertex(
|
|||||||
var out: VertexOutput;
|
var out: VertexOutput;
|
||||||
|
|
||||||
// Transform position
|
// Transform position
|
||||||
out.position = common_tools.proj_matrix * common_tools.view_matrix * common_tools.model_matrix * vec4f(position, 1.0);
|
out.position = vec4(position.xyz, 1.0);
|
||||||
// out.position = vec4(position.xyz, 1.0);
|
|
||||||
out.r_range = r_range;
|
out.r_range = r_range;
|
||||||
let idx = u32(position.w);
|
let idx = u32(position.w);
|
||||||
out.idx = idx;
|
out.idx = idx;
|
||||||
@ -84,8 +112,8 @@ fn fragment(input: VertexOutput) -> @location(0) vec4f {
|
|||||||
// Sample data texture
|
// Sample data texture
|
||||||
let value = data[input.idx];
|
let value = data[input.idx];
|
||||||
let ear = polar_forward(input.position.xyz);
|
let ear = polar_forward(input.position.xyz);
|
||||||
// var color = linear_colormap(value);
|
|
||||||
|
|
||||||
|
// let color = linear_colormap(value);
|
||||||
var color = clamp(value / 75.0, 0.0, 1.0);
|
var color = clamp(value / 75.0, 0.0, 1.0);
|
||||||
|
|
||||||
// let r = ear.x;
|
// let r = ear.x;
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
|
use std::cell::RefCell;
|
||||||
|
use std::sync::{Arc, Mutex, MutexGuard};
|
||||||
|
|
||||||
|
use crate::elements::{Element, ElementAttach, Elements, ElementsRef};
|
||||||
|
use crate::elementvec::ElementVec;
|
||||||
|
use encase;
|
||||||
use quick_cache::sync::Cache;
|
use quick_cache::sync::Cache;
|
||||||
use wgpu::util::DeviceExt;
|
use wgpu::util::DeviceExt;
|
||||||
|
|
||||||
use crate::elements::{Element, ElementAttach, ElementsRef};
|
|
||||||
use crate::elementvec::ElementVec;
|
|
||||||
use wgpu::{Backends, Instance};
|
use wgpu::{Backends, Instance};
|
||||||
|
|
||||||
use encase;
|
|
||||||
|
|
||||||
type DB = std::sync::Arc<wgpu::Buffer>;
|
type DB = std::sync::Arc<wgpu::Buffer>;
|
||||||
|
|
||||||
const BACKENDS_DEFAULT: u32 = Backends::DX12.bits()
|
const BACKENDS_DEFAULT: u32 = Backends::DX12.bits()
|
||||||
@ -15,13 +15,8 @@ const BACKENDS_DEFAULT: u32 = Backends::DX12.bits()
|
|||||||
| Backends::BROWSER_WEBGPU.bits();
|
| Backends::BROWSER_WEBGPU.bits();
|
||||||
|
|
||||||
pub struct App {
|
pub struct App {
|
||||||
_texture: wgpu::Texture,
|
pub(crate) pipelines: Option<ElementVec>,
|
||||||
_texture_size: wgpu::Extent3d,
|
ctx: Ctx,
|
||||||
texture_view: wgpu::TextureView,
|
|
||||||
output: Output,
|
|
||||||
pub pipelines: Option<ElementVec>,
|
|
||||||
pub ctx: Ctx,
|
|
||||||
|
|
||||||
buffer_pool: DataBufferPool,
|
buffer_pool: DataBufferPool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,44 +54,22 @@ impl App {
|
|||||||
// Create a new instance of the common utils struct. This struct contains the bind group layout, bind group, and uniform buffer.
|
// Create a new instance of the common utils struct. This struct contains the bind group layout, bind group, and uniform buffer.
|
||||||
let common_utils = CommonUtils::new(&device);
|
let common_utils = CommonUtils::new(&device);
|
||||||
|
|
||||||
// Create a new texture. This texture will be used as the output texture for the render pass.
|
|
||||||
let texture_size = wgpu::Extent3d {
|
|
||||||
width: 256,
|
|
||||||
height: 256,
|
|
||||||
depth_or_array_layers: 1,
|
|
||||||
};
|
|
||||||
let texture = device.create_texture(&wgpu::TextureDescriptor {
|
|
||||||
label: Some("output texture"),
|
|
||||||
size: texture_size,
|
|
||||||
mip_level_count: 1,
|
|
||||||
sample_count: 1,
|
|
||||||
dimension: wgpu::TextureDimension::D2,
|
|
||||||
format: wgpu::TextureFormat::Rgba8UnormSrgb,
|
|
||||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_SRC,
|
|
||||||
view_formats: &[],
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create a texture view from the texture. This texture view will be used as the output texture for the render pass.
|
|
||||||
let texture_view = texture.create_view(&wgpu::TextureViewDescriptor::default());
|
|
||||||
|
|
||||||
// Buffer pool
|
// Buffer pool
|
||||||
let buffer_pool = DataBufferPool::new();
|
let buffer_pool = DataBufferPool::new();
|
||||||
|
|
||||||
let ctx = Ctx::new(device, queue, common_utils);
|
let ctx = Ctx::new(device, queue, common_utils);
|
||||||
|
|
||||||
let output = Output::new(&ctx.device);
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
pipelines: None,
|
pipelines: None,
|
||||||
_texture: texture,
|
|
||||||
_texture_size: texture_size,
|
|
||||||
texture_view,
|
|
||||||
buffer_pool,
|
buffer_pool,
|
||||||
output,
|
|
||||||
ctx,
|
ctx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn buffer_pool(&mut self) -> &mut DataBufferPool {
|
||||||
|
&mut self.buffer_pool
|
||||||
|
}
|
||||||
|
|
||||||
// Create a new context struct. This struct contains references to the device, queue, bind group layout, and bind group.
|
// Create a new context struct. This struct contains references to the device, queue, bind group layout, and bind group.
|
||||||
pub fn ctx(&self) -> &Ctx {
|
pub fn ctx(&self) -> &Ctx {
|
||||||
&self.ctx
|
&self.ctx
|
||||||
@ -117,7 +90,7 @@ impl App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Draw the elements in the draw list.
|
// Draw the elements in the draw list.
|
||||||
pub async fn draw(&self, draw_list: DrawList<'_, '_>) {
|
pub async fn draw(&self, window: &RenderWindow, draw_list: DrawList) {
|
||||||
let mut encoder = self
|
let mut encoder = self
|
||||||
.ctx
|
.ctx
|
||||||
.device
|
.device
|
||||||
@ -129,7 +102,7 @@ impl App {
|
|||||||
let render_pass_desc = wgpu::RenderPassDescriptor {
|
let render_pass_desc = wgpu::RenderPassDescriptor {
|
||||||
label: Some("Some Render Pass"),
|
label: Some("Some Render Pass"),
|
||||||
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||||
view: &self.texture_view,
|
view: &window.texture_view,
|
||||||
resolve_target: None,
|
resolve_target: None,
|
||||||
ops: wgpu::Operations {
|
ops: wgpu::Operations {
|
||||||
load: wgpu::LoadOp::Clear(wgpu::Color::BLACK),
|
load: wgpu::LoadOp::Clear(wgpu::Color::BLACK),
|
||||||
@ -161,24 +134,105 @@ impl App {
|
|||||||
attach.bind(&mut render_pass);
|
attach.bind(&mut render_pass);
|
||||||
|
|
||||||
// Draw the element.
|
// Draw the element.
|
||||||
element.draw(attach, &mut render_pass);
|
element.draw(&attach, &mut render_pass);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// output
|
// Output
|
||||||
self.output
|
window.finish(&mut encoder);
|
||||||
.output(&mut encoder, &self._texture, self._texture_size, &self.ctx);
|
|
||||||
self.ctx.queue.submit(Some(encoder.finish()));
|
self.ctx.queue.submit(Some(encoder.finish()));
|
||||||
|
|
||||||
self.output.get_data(&self.ctx).await;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_data<'a, T>(&mut self, element: &T, data: &T::Data) -> ElementAttach
|
pub fn drop_all_buffers(&mut self) {
|
||||||
|
self.buffer_pool.buffers.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_data<'a, T>(&self, element: &T, data: &T::Data, config: &T::Config) -> ElementAttach
|
||||||
where
|
where
|
||||||
T: Element,
|
T: Element,
|
||||||
{
|
{
|
||||||
let buffer_pool = &mut self.buffer_pool;
|
let buffer_pool = &self.buffer_pool;
|
||||||
let ctx = &self.ctx;
|
let ctx = &self.ctx;
|
||||||
element.load_data(&ctx, data, buffer_pool)
|
element.load_data(&ctx, data, buffer_pool, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_window(&self, window: Window) -> RenderWindow {
|
||||||
|
RenderWindow::new(window, &self.ctx.device)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Window {
|
||||||
|
pub width: u32,
|
||||||
|
pub height: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RenderWindow {
|
||||||
|
_texture: wgpu::Texture,
|
||||||
|
_texture_size: wgpu::Extent3d,
|
||||||
|
texture_view: wgpu::TextureView,
|
||||||
|
output: Output,
|
||||||
|
window: Window,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RenderWindow {
|
||||||
|
pub fn new(window: Window, device: &wgpu::Device) -> Self {
|
||||||
|
// Create a new texture. This texture will be used as the output texture for the render pass.
|
||||||
|
let texture_size = wgpu::Extent3d {
|
||||||
|
width: window.width,
|
||||||
|
height: window.height,
|
||||||
|
depth_or_array_layers: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
let texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||||
|
label: Some("output texture"),
|
||||||
|
size: texture_size,
|
||||||
|
mip_level_count: 1,
|
||||||
|
sample_count: 1,
|
||||||
|
dimension: wgpu::TextureDimension::D2,
|
||||||
|
format: wgpu::TextureFormat::Rgba8UnormSrgb,
|
||||||
|
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_SRC,
|
||||||
|
view_formats: &[],
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create a texture view from the texture. This texture view will be used as the output texture for the render pass.
|
||||||
|
let texture_view = texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||||
|
|
||||||
|
let output = Output::new(device);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
_texture: texture,
|
||||||
|
_texture_size: texture_size,
|
||||||
|
texture_view,
|
||||||
|
output,
|
||||||
|
window,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn output(&self) -> &Output {
|
||||||
|
&self.output
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn finish(&self, encoder: &mut wgpu::CommandEncoder) {
|
||||||
|
encoder.copy_texture_to_buffer(
|
||||||
|
wgpu::ImageCopyTexture {
|
||||||
|
texture: &self._texture,
|
||||||
|
mip_level: 0,
|
||||||
|
origin: wgpu::Origin3d::ZERO,
|
||||||
|
aspect: wgpu::TextureAspect::All,
|
||||||
|
},
|
||||||
|
wgpu::ImageCopyBuffer {
|
||||||
|
buffer: &self.output.output_buffer,
|
||||||
|
layout: wgpu::ImageDataLayout {
|
||||||
|
offset: 0,
|
||||||
|
bytes_per_row: Some(256 * 4),
|
||||||
|
rows_per_image: Some(256),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wgpu::Extent3d {
|
||||||
|
width: self.window.width,
|
||||||
|
height: self.window.height,
|
||||||
|
depth_or_array_layers: 1,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,16 +256,21 @@ impl Ctx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DrawList<'b, 'a: 'b> {
|
#[derive(Clone)]
|
||||||
pub elements: Vec<(&'b ElementAttach, ElementsRef<'a>)>, // 修复字段访问权限
|
pub struct DrawList {
|
||||||
|
pub elements: Vec<(std::sync::Arc<ElementAttach>, Elements)>, // 修复字段访问权限
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b, 'a: 'b> DrawList<'b, 'a> {
|
impl DrawList {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self { elements: vec![] }
|
Self { elements: vec![] }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push<Ele: Into<ElementsRef<'a>>>(&mut self, element: Ele, attach: &'a ElementAttach) {
|
pub fn push<Ele: Into<Elements>>(
|
||||||
|
&mut self,
|
||||||
|
element: Ele,
|
||||||
|
attach: std::sync::Arc<ElementAttach>,
|
||||||
|
) {
|
||||||
self.elements.push((attach, element.into()));
|
self.elements.push((attach, element.into()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -298,7 +357,7 @@ impl DataBufferPool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_or_create_buffer<F>(&mut self, key: BufferKey, f: F) -> DB
|
pub fn get_or_create_buffer<F>(&self, key: BufferKey, f: F) -> DB
|
||||||
where
|
where
|
||||||
F: FnOnce() -> wgpu::Buffer,
|
F: FnOnce() -> wgpu::Buffer,
|
||||||
{
|
{
|
||||||
@ -325,7 +384,7 @@ impl BufferKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Output {
|
pub struct Output {
|
||||||
output_buffer: wgpu::Buffer,
|
pub output_buffer: wgpu::Buffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Output {
|
impl Output {
|
||||||
@ -346,34 +405,6 @@ impl Output {
|
|||||||
Self { output_buffer }
|
Self { output_buffer }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn output(
|
|
||||||
&self,
|
|
||||||
encoder: &mut wgpu::CommandEncoder,
|
|
||||||
texture: &wgpu::Texture,
|
|
||||||
texture_size: wgpu::Extent3d,
|
|
||||||
ctx: &Ctx,
|
|
||||||
) {
|
|
||||||
let u32_size = std::mem::size_of::<u32>() as u32;
|
|
||||||
|
|
||||||
encoder.copy_texture_to_buffer(
|
|
||||||
wgpu::ImageCopyTexture {
|
|
||||||
aspect: wgpu::TextureAspect::All,
|
|
||||||
texture: &texture,
|
|
||||||
mip_level: 0,
|
|
||||||
origin: wgpu::Origin3d::ZERO,
|
|
||||||
},
|
|
||||||
wgpu::ImageCopyBuffer {
|
|
||||||
buffer: &self.output_buffer,
|
|
||||||
layout: wgpu::ImageDataLayout {
|
|
||||||
offset: 0,
|
|
||||||
bytes_per_row: Some(u32_size * 256),
|
|
||||||
rows_per_image: Some(256),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
texture_size,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_data(&self, ctx: &Ctx) {
|
pub async fn get_data(&self, ctx: &Ctx) {
|
||||||
let device = &ctx.device;
|
let device = &ctx.device;
|
||||||
// 需要对映射变量设置范围,以便我们能够解除缓冲区的映射
|
// 需要对映射变量设置范围,以便我们能够解除缓冲区的映射
|
||||||
@ -404,29 +435,27 @@ impl Output {
|
|||||||
|
|
||||||
mod test {
|
mod test {
|
||||||
use mp_core::{PluginManager, RadarGridData};
|
use mp_core::{PluginManager, RadarGridData};
|
||||||
|
use wgpu::core::pipeline;
|
||||||
|
|
||||||
use crate::elements::{Element, PPI};
|
use crate::elements::{ppi::PPIConfig, Element, PPI};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
#[test]
|
#[test]
|
||||||
fn test_app() {
|
fn test_app() {
|
||||||
let plugin_manager = PluginManager::new(
|
let plugin_manager = PluginManager::new(
|
||||||
// r#"/Users/tsuki/projects/mp/loaders"#
|
r#"/Users/tsuki/projects/mp/loaders"#, // r#"C:\Users\qwin7\projects\radarmp\loaders"#,
|
||||||
r#"C:\Users\qwin7\projects\radarmp\loaders"#,
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let data = plugin_manager.try_load_data(
|
let data = plugin_manager.try_load_data(
|
||||||
// "/Users/tsuki/Desktop/Z_RADR_I_X5775_20230726180000_O_DOR-XPD-CAP-FMT.BIN.zip",
|
"/Users/tsuki/Desktop/Z_RADR_I_X5775_20230726180000_O_DOR-XPD-CAP-FMT.BIN.zip",
|
||||||
r#"C:\Users\qwin7\Downloads\ZJSXAA_20230113070200_R.dat.gz"#,
|
// r#"C:\Users\qwin7\Downloads\ZJSXAA_20230113070200_R.dat.gz"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
pollster::block_on(async {
|
pollster::block_on(async {
|
||||||
let mut app = App::instant().await;
|
let mut app = App::instant().await;
|
||||||
app.init().await;
|
app.init().await;
|
||||||
|
|
||||||
let pipelines = app.pipelines.as_ref().unwrap();
|
|
||||||
let ppi = pipelines.ppi();
|
|
||||||
let ctx = &app.ctx;
|
let ctx = &app.ctx;
|
||||||
let buffer_pool = &mut app.buffer_pool;
|
let buffer_pool = &mut app.buffer_pool;
|
||||||
|
|
||||||
@ -434,17 +463,33 @@ mod test {
|
|||||||
let first_block = data.first().unwrap();
|
let first_block = data.first().unwrap();
|
||||||
|
|
||||||
// Convert the first block into a PPI struct.
|
// Convert the first block into a PPI struct.
|
||||||
if let Ok(data) = first_block.try_into() {
|
// if let Ok(data) = first_block.try_into() {
|
||||||
let attachment = ppi.load_data(&ctx, data, buffer_pool);
|
// // let attachment = {
|
||||||
|
// // let pipelines = app.pipelines.as_mut().unwrap();
|
||||||
|
// // let ppi = pipelines.ppi();
|
||||||
|
|
||||||
// Create a new draw list and push the attachment into it.
|
// // // let attachment = ppi.load_data(
|
||||||
|
// // // &ctx,
|
||||||
|
// // // data,
|
||||||
|
// // // buffer_pool,
|
||||||
|
// // // &PPIConfig {
|
||||||
|
// // // colormap: vec![[1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0]],
|
||||||
|
// // // color_range: [0.0, 1.0],
|
||||||
|
// // // },
|
||||||
|
// // // );
|
||||||
|
// // attachment
|
||||||
|
// // };
|
||||||
|
|
||||||
let mut draw_list = DrawList::new();
|
// let pipeline = app.pipelines();
|
||||||
draw_list.push(ppi, &attachment);
|
// let ppi = pipeline.ppi();
|
||||||
|
|
||||||
// Draw the elements in the draw list.
|
// // Create a new draw list and push the attachment into it.
|
||||||
app.draw(draw_list).await;
|
// let mut draw_list = DrawList::new();
|
||||||
}
|
// // draw_list.push(ppi, &attachment);
|
||||||
|
|
||||||
|
// // Draw the elements in the draw list.
|
||||||
|
// // app.draw(draw_list).await;
|
||||||
|
// }
|
||||||
} else {
|
} else {
|
||||||
panic!("Failed to load data");
|
panic!("Failed to load data");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,22 +1,33 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
pub mod ppi;
|
pub mod ppi;
|
||||||
use crate::app::{BufferKey, Ctx, DataBufferPool};
|
use crate::{
|
||||||
|
app::{BufferKey, Ctx, DataBufferPool},
|
||||||
|
App,
|
||||||
|
};
|
||||||
|
use mp_core::config;
|
||||||
pub use ppi::PPI;
|
pub use ppi::PPI;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use wgpu::util::DeviceExt;
|
use wgpu::util::DeviceExt;
|
||||||
|
|
||||||
macro_rules! elements {
|
macro_rules! elements {
|
||||||
($(($element_name:ident,$element: ty),)+) => {
|
($(($element_name:ident,$element: ty),)+) => {
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum Elements {
|
pub enum Elements {
|
||||||
$($element_name($element),)+
|
$($element_name(Arc<$element>),)+
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
pub enum ElementsRef<'a> {
|
pub enum ElementsRef<'a> {
|
||||||
$($element_name(&'a $element),)+
|
$($element_name(&'a $element),)+
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum ElementsMut<'a> {
|
||||||
|
$($element_name(&'a mut $element),)+
|
||||||
|
}
|
||||||
|
|
||||||
$(
|
$(
|
||||||
impl From<$element> for Elements {
|
impl From<Arc<$element>> for Elements {
|
||||||
fn from(element: $element) -> Self {
|
fn from(element: Arc<$element>) -> Self {
|
||||||
Elements::$element_name(element)
|
Elements::$element_name(element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -26,6 +37,21 @@ macro_rules! elements {
|
|||||||
ElementsRef::$element_name(element)
|
ElementsRef::$element_name(element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a mut $element> for ElementsMut<'a> {
|
||||||
|
fn from(element: &'a mut $element) -> Self {
|
||||||
|
ElementsMut::$element_name(element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a mut $element> for ElementsRef<'a> {
|
||||||
|
fn from(element: &'a mut $element) -> Self {
|
||||||
|
ElementsRef::$element_name(element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
)+
|
)+
|
||||||
|
|
||||||
impl Elements {
|
impl Elements {
|
||||||
@ -57,6 +83,20 @@ macro_rules! elements {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> ElementsMut<'a> {
|
||||||
|
pub fn pipeline(&'a self) -> &wgpu::RenderPipeline {
|
||||||
|
match self {
|
||||||
|
$(ElementsMut::$element_name(element) => element.pipeline(),)+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw(&'a self, attach: &ElementAttach, render_pass: &mut wgpu::RenderPass) {
|
||||||
|
match self {
|
||||||
|
$(ElementsMut::$element_name(element) => element.draw(attach, render_pass),)+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,6 +105,8 @@ pub trait Element {
|
|||||||
type Uniform;
|
type Uniform;
|
||||||
type Data;
|
type Data;
|
||||||
|
|
||||||
|
type Config;
|
||||||
|
|
||||||
fn new(ctx: &Ctx) -> Self;
|
fn new(ctx: &Ctx) -> Self;
|
||||||
|
|
||||||
// fn new_attachment<'a>(&self, ctx: &Ctx) -> ElementAttach;
|
// fn new_attachment<'a>(&self, ctx: &Ctx) -> ElementAttach;
|
||||||
@ -84,7 +126,8 @@ pub trait Element {
|
|||||||
&self,
|
&self,
|
||||||
ctx: &Ctx,
|
ctx: &Ctx,
|
||||||
data: &Self::Data,
|
data: &Self::Data,
|
||||||
buffer_pool: &mut DataBufferPool,
|
buffer_pool: &DataBufferPool,
|
||||||
|
config: &Self::Config,
|
||||||
) -> ElementAttach;
|
) -> ElementAttach;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::Shaders;
|
use crate::tools::colormap::{ColorMap, ColormapParams};
|
||||||
use rust_embed::RustEmbed;
|
use log::*;
|
||||||
use std::{ops::Sub, result, vec};
|
use std::{ops::Sub, vec};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
app::{BufferKey, Ctx, DataBufferPool},
|
app::{BufferKey, Ctx, DataBufferPool},
|
||||||
@ -20,6 +20,12 @@ const RMAXNUM: u64 = 50;
|
|||||||
pub struct PPI {
|
pub struct PPI {
|
||||||
bind_group_layout: wgpu::BindGroupLayout,
|
bind_group_layout: wgpu::BindGroupLayout,
|
||||||
pipeline: wgpu::RenderPipeline,
|
pipeline: wgpu::RenderPipeline,
|
||||||
|
colormap: Option<ColorMap>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PPIConfig {
|
||||||
|
pub colormap: Vec<[f32; 4]>,
|
||||||
|
pub color_range: [f32; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -67,8 +73,14 @@ impl Element for PPI {
|
|||||||
type Uniform = PPIUniform;
|
type Uniform = PPIUniform;
|
||||||
type Data = RadarGridData;
|
type Data = RadarGridData;
|
||||||
|
|
||||||
|
type Config = PPIConfig;
|
||||||
|
|
||||||
fn new(ctx: &Ctx) -> Self {
|
fn new(ctx: &Ctx) -> Self {
|
||||||
let device = &ctx.device;
|
let device = &ctx.device;
|
||||||
|
|
||||||
|
// Tools
|
||||||
|
let colormap_layout = ColorMap::layout(device);
|
||||||
|
|
||||||
// Group Layout
|
// Group Layout
|
||||||
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
label: Some("PPI Bind Group Layout"),
|
label: Some("PPI Bind Group Layout"),
|
||||||
@ -106,6 +118,8 @@ impl Element for PPI {
|
|||||||
bind_group_layouts: &[
|
bind_group_layouts: &[
|
||||||
// common_tools
|
// common_tools
|
||||||
&ctx.common_tools.bind_group_layout,
|
&ctx.common_tools.bind_group_layout,
|
||||||
|
// colormap
|
||||||
|
&colormap_layout,
|
||||||
// ppi
|
// ppi
|
||||||
&bind_group_layout,
|
&bind_group_layout,
|
||||||
],
|
],
|
||||||
@ -155,6 +169,7 @@ impl Element for PPI {
|
|||||||
PPI {
|
PPI {
|
||||||
bind_group_layout: bind_group_layout,
|
bind_group_layout: bind_group_layout,
|
||||||
pipeline: render_pipeline,
|
pipeline: render_pipeline,
|
||||||
|
colormap: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,12 +203,13 @@ impl Element for PPI {
|
|||||||
&self,
|
&self,
|
||||||
ctx: &Ctx,
|
ctx: &Ctx,
|
||||||
data: &Self::Data,
|
data: &Self::Data,
|
||||||
buffer_pool: &mut DataBufferPool,
|
buffer_pool: &DataBufferPool,
|
||||||
|
config: &Self::Config,
|
||||||
) -> ElementAttach {
|
) -> ElementAttach {
|
||||||
|
info!("Loading PPI data");
|
||||||
let (vertex, index) = self.bake(data);
|
let (vertex, index) = self.bake(data);
|
||||||
println!("index: {:?}", &(index.as_ref()).unwrap()[0..24]);
|
|
||||||
println!("vertex: {:?}", &vertex[0..4]);
|
|
||||||
let device = &ctx.device;
|
let device = &ctx.device;
|
||||||
|
let queue = &ctx.queue;
|
||||||
|
|
||||||
let uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
let uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
label: Some("PPI Uniform Buffer"),
|
label: Some("PPI Uniform Buffer"),
|
||||||
@ -247,12 +263,22 @@ impl Element for PPI {
|
|||||||
label: Some("PPI Bind Group"),
|
label: Some("PPI Bind Group"),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ColorMap Bind Group
|
||||||
|
let color_map = ColorMap::new(
|
||||||
|
device,
|
||||||
|
queue,
|
||||||
|
ColormapParams::new(config.colormap.clone(), config.color_range),
|
||||||
|
);
|
||||||
|
let color_map_group = color_map.bind_group(device);
|
||||||
|
// self.colormap = Some(color_map);
|
||||||
|
|
||||||
ElementAttach {
|
ElementAttach {
|
||||||
vertex_buffer: vertex_buffer,
|
vertex_buffer: vertex_buffer,
|
||||||
index_buffer: Some(index_buffer),
|
index_buffer: Some(index_buffer),
|
||||||
num_indices,
|
num_indices,
|
||||||
uniform_buffer: Some(uniform_buffer),
|
uniform_buffer: Some(uniform_buffer),
|
||||||
bind_group: vec![(1, bind_group)],
|
// bind group 0 is always common tools
|
||||||
|
bind_group: vec![(1, color_map_group), (2, bind_group)],
|
||||||
data_buffer_key: Some(key),
|
data_buffer_key: Some(key),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -262,7 +288,7 @@ impl PPI {
|
|||||||
fn init_shader(device: &wgpu::Device) -> wgpu::ShaderModule {
|
fn init_shader(device: &wgpu::Device) -> wgpu::ShaderModule {
|
||||||
// let shader_str = merge_shader(r#"/Users/tsuki/projects/mp/mp_elements/shaders/ppi.wgsl"#);
|
// let shader_str = merge_shader(r#"/Users/tsuki/projects/mp/mp_elements/shaders/ppi.wgsl"#);
|
||||||
|
|
||||||
let shader_str = get_shader("ppi_merged.wgsl").as_ref();
|
let shader_str = get_shader("elements/ppi_merged.wgsl");
|
||||||
|
|
||||||
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||||
label: Some("PPI Shader Module"),
|
label: Some("PPI Shader Module"),
|
||||||
|
|||||||
@ -1,27 +1,29 @@
|
|||||||
use crate::app::Ctx;
|
use crate::app::Ctx;
|
||||||
use crate::elements::*;
|
use crate::elements::*;
|
||||||
|
use std::sync::Arc;
|
||||||
macro_rules! elementvec {
|
macro_rules! elementvec {
|
||||||
($({$element: ident, $element_ty: ty})+) => {
|
($({$element: ident, $element_ty: ty, $element_mut: ident})+) => {
|
||||||
pub struct ElementVec {
|
pub struct ElementVec {
|
||||||
$($element: $element_ty,)+
|
$($element: Arc<$element_ty> ,)+
|
||||||
}
|
}
|
||||||
impl ElementVec {
|
impl ElementVec {
|
||||||
pub fn init(ctx: &Ctx) -> Self {
|
pub fn init(ctx: &Ctx) -> Self {
|
||||||
// Compile the shaders, create the pipelines, etc.
|
// Compile the shaders, create the pipelines, etc.
|
||||||
Self {
|
Self {
|
||||||
$($element: <$element_ty>::new(ctx),)+
|
$($element: Arc::new((<$element_ty>::new(ctx))) ,)+
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$(pub fn $element(&self) -> &$element_ty {
|
$(pub fn $element(&self) -> &Arc< $element_ty> {
|
||||||
&self.$element
|
&self.$element
|
||||||
})+
|
})+
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
() => {};
|
() => {};
|
||||||
}
|
}
|
||||||
|
|
||||||
elementvec!({
|
elementvec!({
|
||||||
ppi, PPI
|
ppi, PPI, ppi_mut
|
||||||
});
|
});
|
||||||
|
|||||||
@ -2,6 +2,7 @@ pub mod app;
|
|||||||
pub mod elements;
|
pub mod elements;
|
||||||
pub mod elementvec;
|
pub mod elementvec;
|
||||||
pub mod renderer;
|
pub mod renderer;
|
||||||
|
pub mod tools;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
pub use app::App;
|
pub use app::App;
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
use glam::*;
|
use glam::*;
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub struct Camera {
|
pub struct Camera {
|
||||||
pub position: Vec3,
|
pub position: Vec3,
|
||||||
pub center: Vec3,
|
pub center: Vec3,
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
use glam::*;
|
use glam::*;
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
pub struct Projection {
|
pub struct Projection {
|
||||||
aspect: f32,
|
aspect: f32,
|
||||||
fovy: f32,
|
fovy: f32,
|
||||||
@ -24,3 +25,14 @@ impl Projection {
|
|||||||
Mat4::perspective_rh(self.fovy, self.aspect, self.znear, self.zfar)
|
Mat4::perspective_rh(self.fovy, self.aspect, self.znear, self.zfar)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Projection {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
aspect: 1.0,
|
||||||
|
fovy: 45.0,
|
||||||
|
znear: 0.1,
|
||||||
|
zfar: 100.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
212
mp_elements/src/tools/colormap.rs
Normal file
212
mp_elements/src/tools/colormap.rs
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
use wgpu::util::DeviceExt;
|
||||||
|
|
||||||
|
pub struct ColorMap {
|
||||||
|
uniform: ColorMapUniform,
|
||||||
|
uniform_buffer: wgpu::Buffer,
|
||||||
|
unifrom_bind_group_layout: wgpu::BindGroupLayout,
|
||||||
|
|
||||||
|
texture: wgpu::Texture,
|
||||||
|
texture_view: wgpu::TextureView,
|
||||||
|
sampler: wgpu::Sampler,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ColormapParams {
|
||||||
|
pub colors: Vec<[f32; 4]>,
|
||||||
|
pub color_range: [f32; 2],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ColormapParams {
|
||||||
|
pub fn from_u8(colors: Vec<[u8; 4]>, color_range: [f32; 2]) -> Self {
|
||||||
|
let colors = colors
|
||||||
|
.iter()
|
||||||
|
.map(|c| {
|
||||||
|
let c = [c[0] as f32, c[1] as f32, c[2] as f32, c[3] as f32];
|
||||||
|
let c = [c[0] / 255.0, c[1] / 255.0, c[2] / 255.0, c[3] / 255.0];
|
||||||
|
c
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
ColormapParams {
|
||||||
|
colors,
|
||||||
|
color_range,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn new(colors: Vec<[f32; 4]>, color_range: [f32; 2]) -> Self {
|
||||||
|
ColormapParams {
|
||||||
|
colors,
|
||||||
|
color_range,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn as_texture_data(&self) -> Vec<u8> {
|
||||||
|
self.colors
|
||||||
|
.iter()
|
||||||
|
.flat_map(|color| bytemuck::bytes_of(color))
|
||||||
|
.copied()
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, encase::ShaderType)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct ColorMapUniform {
|
||||||
|
color_count: u32,
|
||||||
|
value_min: f32,
|
||||||
|
value_max: f32,
|
||||||
|
invalid_value: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ColorMapUniform {
|
||||||
|
fn as_slice(&self) -> encase::internal::Result<Vec<u8>> {
|
||||||
|
let mut buffer = encase::UniformBuffer::new(Vec::new());
|
||||||
|
buffer.write(self)?;
|
||||||
|
Ok(buffer.into_inner())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ColorMap {
|
||||||
|
pub fn new(device: &wgpu::Device, queue: &wgpu::Queue, params: ColormapParams) -> Self {
|
||||||
|
let uniform = ColorMapUniform {
|
||||||
|
color_count: params.colors.len() as u32,
|
||||||
|
value_min: params.color_range[0],
|
||||||
|
value_max: params.color_range[1],
|
||||||
|
invalid_value: 0.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
|
label: Some("ColorMap Uniform Buffer"),
|
||||||
|
contents: uniform.as_slice().unwrap().as_slice(),
|
||||||
|
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||||
|
});
|
||||||
|
|
||||||
|
let texture = Self::create_color_texture(device, queue, ¶ms);
|
||||||
|
let texture_view = texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||||
|
let sampler = Self::create_sampler(device);
|
||||||
|
|
||||||
|
let bind_group_layout = Self::layout(device);
|
||||||
|
|
||||||
|
ColorMap {
|
||||||
|
uniform,
|
||||||
|
uniform_buffer: buffer,
|
||||||
|
unifrom_bind_group_layout: bind_group_layout,
|
||||||
|
sampler,
|
||||||
|
texture,
|
||||||
|
texture_view,
|
||||||
|
// uniform_bind_group: bind_group,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout {
|
||||||
|
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
|
label: Some("ColorMap Bind Group Layout"),
|
||||||
|
entries: &[
|
||||||
|
wgpu::BindGroupLayoutEntry {
|
||||||
|
binding: 0,
|
||||||
|
visibility: wgpu::ShaderStages::all(),
|
||||||
|
ty: wgpu::BindingType::Texture {
|
||||||
|
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||||
|
view_dimension: wgpu::TextureViewDimension::D1,
|
||||||
|
multisampled: false,
|
||||||
|
},
|
||||||
|
count: None,
|
||||||
|
},
|
||||||
|
wgpu::BindGroupLayoutEntry {
|
||||||
|
binding: 1,
|
||||||
|
visibility: wgpu::ShaderStages::all(),
|
||||||
|
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
|
||||||
|
count: None,
|
||||||
|
},
|
||||||
|
wgpu::BindGroupLayoutEntry {
|
||||||
|
binding: 2,
|
||||||
|
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||||
|
ty: wgpu::BindingType::Buffer {
|
||||||
|
ty: wgpu::BufferBindingType::Uniform,
|
||||||
|
has_dynamic_offset: false,
|
||||||
|
min_binding_size: None,
|
||||||
|
},
|
||||||
|
count: None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bind_group(&self, device: &wgpu::Device) -> wgpu::BindGroup {
|
||||||
|
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||||
|
label: Some("ColorMap Bind Group"),
|
||||||
|
layout: &self.unifrom_bind_group_layout,
|
||||||
|
entries: &[
|
||||||
|
wgpu::BindGroupEntry {
|
||||||
|
binding: 0,
|
||||||
|
resource: wgpu::BindingResource::TextureView(&self.texture_view),
|
||||||
|
},
|
||||||
|
wgpu::BindGroupEntry {
|
||||||
|
binding: 1,
|
||||||
|
resource: wgpu::BindingResource::Sampler(&self.sampler),
|
||||||
|
},
|
||||||
|
wgpu::BindGroupEntry {
|
||||||
|
binding: 2,
|
||||||
|
resource: self.uniform_buffer.as_entire_binding(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
bind_group
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bind_group_layout(&self) -> &wgpu::BindGroupLayout {
|
||||||
|
&self.unifrom_bind_group_layout
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_uniform<F>(&mut self, f: F)
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut ColorMapUniform),
|
||||||
|
{
|
||||||
|
f(&mut self.uniform);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(&mut self, queue: &wgpu::Queue) {
|
||||||
|
queue.write_buffer(
|
||||||
|
&self.uniform_buffer,
|
||||||
|
0,
|
||||||
|
self.uniform.as_slice().unwrap().as_slice(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_color_texture(
|
||||||
|
device: &wgpu::Device,
|
||||||
|
queue: &wgpu::Queue,
|
||||||
|
params: &ColormapParams,
|
||||||
|
) -> wgpu::Texture {
|
||||||
|
device.create_texture_with_data(
|
||||||
|
queue,
|
||||||
|
&wgpu::TextureDescriptor {
|
||||||
|
label: Some("ColorMap Texture"),
|
||||||
|
size: wgpu::Extent3d {
|
||||||
|
width: params.colors.len() as u32,
|
||||||
|
height: 1,
|
||||||
|
depth_or_array_layers: 1,
|
||||||
|
},
|
||||||
|
mip_level_count: 1,
|
||||||
|
sample_count: 1,
|
||||||
|
dimension: wgpu::TextureDimension::D1,
|
||||||
|
format: wgpu::TextureFormat::Rgba8Unorm,
|
||||||
|
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
|
||||||
|
view_formats: &[],
|
||||||
|
},
|
||||||
|
wgpu::util::TextureDataOrder::LayerMajor,
|
||||||
|
¶ms.as_texture_data(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_sampler(device: &wgpu::Device) -> wgpu::Sampler {
|
||||||
|
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
||||||
|
label: Some("ColorMap Sampler"),
|
||||||
|
address_mode_u: wgpu::AddressMode::ClampToEdge,
|
||||||
|
address_mode_v: wgpu::AddressMode::ClampToEdge,
|
||||||
|
address_mode_w: wgpu::AddressMode::ClampToEdge,
|
||||||
|
mag_filter: wgpu::FilterMode::Nearest,
|
||||||
|
min_filter: wgpu::FilterMode::Nearest,
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
|
sampler
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,2 +1 @@
|
|||||||
pub mod colormap;
|
pub mod colormap;
|
||||||
pub mod ppi;
|
|
||||||
@ -2,8 +2,8 @@ use crate::Shaders;
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
pub fn get_shader(name: &str) -> Cow<'static, str> {
|
pub fn get_shader(name: &str) -> String {
|
||||||
let file = Shaders::get(name).unwrap();
|
let file = Shaders::get(name).unwrap();
|
||||||
let string = String::from_utf8_lossy(&file.data);
|
let string = String::from_utf8(file.data.to_vec()).unwrap();
|
||||||
string
|
string
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user