init
This commit is contained in:
commit
22f43dbb78
12 changed files with 4314 additions and 0 deletions
1
.envrc
Normal file
1
.envrc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
use flake . --impure
|
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
/target
|
||||||
|
/.direnv
|
||||||
|
/.devenv
|
2
.helix/languages.toml
Normal file
2
.helix/languages.toml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
[language-server.rust-analyzer]
|
||||||
|
# config = { cargo = { target = "wasm32-unknown-unknown" } }
|
3737
Cargo.lock
generated
Normal file
3737
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
28
Cargo.toml
Normal file
28
Cargo.toml
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
[package]
|
||||||
|
name = "mathe-img-processor"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bytemuck = "1.16.0"
|
||||||
|
eframe = {version = "0.27", features = ["wgpu"]}
|
||||||
|
env_logger = "0.11.3"
|
||||||
|
# winit = { version = "0.30", features = ["rwh_05" ] }
|
||||||
|
# log = "0.4"
|
||||||
|
# console_error_panic_hook = "0.1.6"
|
||||||
|
# console_log = "1.0"
|
||||||
|
# cfg-if = "1"
|
||||||
|
# wgpu = { version = "0.19", features = ["webgl"]}
|
||||||
|
# wasm-bindgen = "0.2"
|
||||||
|
# wasm-bindgen-futures = "0.4.30"
|
||||||
|
# web-sys = { version = "0.3", features = [
|
||||||
|
# "Document",
|
||||||
|
# "Window",
|
||||||
|
# "Element",
|
||||||
|
# ]}
|
||||||
|
|
||||||
|
# [lib]
|
||||||
|
# crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
# [build]
|
||||||
|
# target = "wasm32-unknown-unknown"
|
21
TODO.md
Normal file
21
TODO.md
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# TODOs
|
||||||
|
|
||||||
|
- [ ] GPU/Processing/Rendering
|
||||||
|
- [ ] color matrix multiplication
|
||||||
|
- [ ] transform matrix multiplication
|
||||||
|
- [ ] Optional: convolutions
|
||||||
|
- [ ] abstractions over egui stuff
|
||||||
|
- [ ] independent lib/cli app?
|
||||||
|
- [ ] ui
|
||||||
|
- [ ] components
|
||||||
|
- [ ] number picker with slider at bottom?
|
||||||
|
- [ ] (arbitrary size?) matrix component
|
||||||
|
- [ ] matrix list that outputs single matrix multiplied from them all
|
||||||
|
- [ ] Optional: help/what is this buttons
|
||||||
|
- [ ] Optional: explainer per pixel what's happening on hover
|
||||||
|
- [ ] view
|
||||||
|
- [ ] image view
|
||||||
|
- [ ] matrix ("columns"?) to apply
|
||||||
|
- [ ] transform
|
||||||
|
- [ ] color
|
||||||
|
- [ ] Optional: Convolution
|
179
flake.lock
Normal file
179
flake.lock
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"crane": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1715274763,
|
||||||
|
"narHash": "sha256-3Iv1PGHJn9sV3HO4FlOVaaztOxa9uGLfOmUWrH7v7+A=",
|
||||||
|
"owner": "ipetkov",
|
||||||
|
"repo": "crane",
|
||||||
|
"rev": "27025ab71bdca30e7ed0a16c88fd74c5970fc7f5",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "ipetkov",
|
||||||
|
"repo": "crane",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fenix": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"rust-analyzer-src": "rust-analyzer-src"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1715927173,
|
||||||
|
"narHash": "sha256-2S8hVck6nlyiBifzymDvePl5HWgqvVgxkBZCRax1qD8=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "fenix",
|
||||||
|
"rev": "a2d19ef9305841f26c8ab908b1c09a84ca307e18",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "fenix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1710146030,
|
||||||
|
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-utils_2": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems_2"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1689068808,
|
||||||
|
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1715867414,
|
||||||
|
"narHash": "sha256-cu4UEffKkBByyGR6CFs9XP6iSNsKTkq1r66DA5BkYnE=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "bf446f08bff6814b569265bef8374cfdd3d8f0e0",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixpkgs-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"crane": "crane",
|
||||||
|
"fenix": "fenix",
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"wgsl_analyzer": "wgsl_analyzer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rust-analyzer-src": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1715839492,
|
||||||
|
"narHash": "sha256-EyjtjocGLtB7tqyqwBfadP4y5BBtT5EkoG3kq/zym5U=",
|
||||||
|
"owner": "rust-lang",
|
||||||
|
"repo": "rust-analyzer",
|
||||||
|
"rev": "83ba42043166948db91fcfcfe30e0b7eac10b3d5",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "rust-lang",
|
||||||
|
"ref": "nightly",
|
||||||
|
"repo": "rust-analyzer",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"wgsl_analyzer": {
|
||||||
|
"inputs": {
|
||||||
|
"crane": [
|
||||||
|
"crane"
|
||||||
|
],
|
||||||
|
"flake-utils": "flake-utils_2",
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1702151450,
|
||||||
|
"narHash": "sha256-bhosTihbW89vkqp1ua0C1HGLJJdCNfRde98z4+IjkOc=",
|
||||||
|
"owner": "wgsl-analyzer",
|
||||||
|
"repo": "wgsl-analyzer",
|
||||||
|
"rev": "8851962fc191aa5ea85a25b0ebd10cb9f70627b3",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "wgsl-analyzer",
|
||||||
|
"repo": "wgsl-analyzer",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
90
flake.nix
Normal file
90
flake.nix
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
{
|
||||||
|
description = "Build a cargo project without extra checks";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||||
|
|
||||||
|
crane = {
|
||||||
|
url = "github:ipetkov/crane";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
fenix = {
|
||||||
|
url = "github:nix-community/fenix";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
|
||||||
|
wgsl_analyzer = {
|
||||||
|
url = "github:wgsl-analyzer/wgsl-analyzer";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
inputs.crane.follows = "crane";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = {
|
||||||
|
self,
|
||||||
|
nixpkgs,
|
||||||
|
crane,
|
||||||
|
fenix,
|
||||||
|
flake-utils,
|
||||||
|
wgsl_analyzer,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
flake-utils.lib.eachDefaultSystem (system: let
|
||||||
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
|
|
||||||
|
craneLib = crane.lib.${system};
|
||||||
|
rs-toolchain = with fenix.packages.${system};
|
||||||
|
combine [
|
||||||
|
complete.toolchain
|
||||||
|
targets.wasm32-unknown-unknown.latest.rust-std
|
||||||
|
# rust-analyzer
|
||||||
|
];
|
||||||
|
my-crate = craneLib.buildPackage {
|
||||||
|
src = craneLib.cleanCargoSource (craneLib.path ./.);
|
||||||
|
strictDeps = true;
|
||||||
|
|
||||||
|
buildInputs =
|
||||||
|
[
|
||||||
|
# Add additional build inputs here
|
||||||
|
]
|
||||||
|
++ pkgs.lib.optionals pkgs.stdenv.isDarwin [
|
||||||
|
# Additional darwin specific inputs can be set here
|
||||||
|
pkgs.libiconv
|
||||||
|
];
|
||||||
|
|
||||||
|
# Additional environment variables can be set directly
|
||||||
|
# MY_CUSTOM_VAR = "some value";
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
packages.default = my-crate;
|
||||||
|
|
||||||
|
apps.default = flake-utils.lib.mkApp {
|
||||||
|
drv = my-crate;
|
||||||
|
};
|
||||||
|
|
||||||
|
devShells.default = pkgs.mkShell rec {
|
||||||
|
buildInputs = with pkgs; [
|
||||||
|
pkg-config
|
||||||
|
rs-toolchain
|
||||||
|
udev
|
||||||
|
alsa-lib
|
||||||
|
vulkan-loader
|
||||||
|
libxkbcommon
|
||||||
|
wayland
|
||||||
|
xorg.libX11
|
||||||
|
xorg.libXcursor
|
||||||
|
xorg.libXi
|
||||||
|
xorg.libXrandr # mold-wrapped
|
||||||
|
gtk3
|
||||||
|
clang
|
||||||
|
trunk
|
||||||
|
binaryen
|
||||||
|
wgsl_analyzer.outputs.packages."x86_64-linux".default
|
||||||
|
];
|
||||||
|
|
||||||
|
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath buildInputs;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
11
index.html
Normal file
11
index.html
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=, initial-scale=">
|
||||||
|
<title>Wasm test</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
39
src/custom3d_wgpu_shader.wgsl
Normal file
39
src/custom3d_wgpu_shader.wgsl
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
struct VertexOut {
|
||||||
|
@location(0) color: vec4<f32>,
|
||||||
|
@builtin(position) position: vec4<f32>,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Uniforms {
|
||||||
|
@size(16) angle: f32, // pad to 16 bytes
|
||||||
|
};
|
||||||
|
|
||||||
|
@group(0) @binding(0)
|
||||||
|
var<uniform> uniforms: Uniforms;
|
||||||
|
|
||||||
|
var<private> v_positions: array<vec2<f32>, 3> = array<vec2<f32>, 3>(
|
||||||
|
vec2<f32>(0.0, 1.0),
|
||||||
|
vec2<f32>(1.0, -1.0),
|
||||||
|
vec2<f32>(-1.0, -1.0),
|
||||||
|
);
|
||||||
|
|
||||||
|
var<private> v_colors: array<vec4<f32>, 3> = array<vec4<f32>, 3>(
|
||||||
|
vec4<f32>(1.0, 0.0, 0.0, 1.0),
|
||||||
|
vec4<f32>(0.0, 1.0, 0.0, 1.0),
|
||||||
|
vec4<f32>(0.0, 0.0, 1.0, 1.0),
|
||||||
|
);
|
||||||
|
|
||||||
|
@vertex
|
||||||
|
fn vs_main(@builtin(vertex_index) v_idx: u32) -> VertexOut {
|
||||||
|
var out: VertexOut;
|
||||||
|
|
||||||
|
out.position = vec4<f32>(v_positions[v_idx], 0.0, 1.0);
|
||||||
|
out.position.x = out.position.x * cos(uniforms.angle);
|
||||||
|
out.color = v_colors[v_idx];
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn fs_main(in: VertexOut) -> @location(0) vec4<f32> {
|
||||||
|
return in.color;
|
||||||
|
}
|
190
src/lib.rs
Normal file
190
src/lib.rs
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
use std::num::NonZeroU64;
|
||||||
|
|
||||||
|
use cb::TriangleRenderResources;
|
||||||
|
use eframe::{
|
||||||
|
egui, egui_wgpu,
|
||||||
|
wgpu::{self, util::DeviceExt},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::cb::CustomTriangleCallback;
|
||||||
|
|
||||||
|
pub struct App {
|
||||||
|
name: String,
|
||||||
|
age: u32,
|
||||||
|
}
|
||||||
|
impl App {
|
||||||
|
pub fn new<'a>(cc: &'a eframe::CreationContext<'a>) -> Option<Self> {
|
||||||
|
// Get the WGPU render state from the eframe creation context. This can also be retrieved
|
||||||
|
// from `eframe::Frame` when you don't have a `CreationContext` available.
|
||||||
|
let wgpu_render_state = cc.wgpu_render_state.as_ref()?;
|
||||||
|
|
||||||
|
let device = &wgpu_render_state.device;
|
||||||
|
|
||||||
|
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||||
|
label: Some("custom3d"),
|
||||||
|
source: wgpu::ShaderSource::Wgsl(include_str!("./custom3d_wgpu_shader.wgsl").into()),
|
||||||
|
});
|
||||||
|
|
||||||
|
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
|
label: Some("custom3d"),
|
||||||
|
entries: &[wgpu::BindGroupLayoutEntry {
|
||||||
|
binding: 0,
|
||||||
|
visibility: wgpu::ShaderStages::VERTEX,
|
||||||
|
ty: wgpu::BindingType::Buffer {
|
||||||
|
ty: wgpu::BufferBindingType::Uniform,
|
||||||
|
has_dynamic_offset: false,
|
||||||
|
min_binding_size: NonZeroU64::new(16),
|
||||||
|
},
|
||||||
|
count: None,
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
|
||||||
|
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||||
|
label: Some("custom3d"),
|
||||||
|
bind_group_layouts: &[&bind_group_layout],
|
||||||
|
push_constant_ranges: &[],
|
||||||
|
});
|
||||||
|
|
||||||
|
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||||
|
label: Some("custom3d"),
|
||||||
|
layout: Some(&pipeline_layout),
|
||||||
|
vertex: wgpu::VertexState {
|
||||||
|
module: &shader,
|
||||||
|
entry_point: "vs_main",
|
||||||
|
buffers: &[],
|
||||||
|
// compilation_options: wgpu::PipelineCompilationOptions::default(),
|
||||||
|
},
|
||||||
|
fragment: Some(wgpu::FragmentState {
|
||||||
|
module: &shader,
|
||||||
|
entry_point: "fs_main",
|
||||||
|
targets: &[Some(wgpu_render_state.target_format.into())],
|
||||||
|
// compilation_options: wgpu::PipelineCompilationOptions::default(),
|
||||||
|
}),
|
||||||
|
primitive: wgpu::PrimitiveState::default(),
|
||||||
|
depth_stencil: None,
|
||||||
|
multisample: wgpu::MultisampleState::default(),
|
||||||
|
multiview: None,
|
||||||
|
});
|
||||||
|
|
||||||
|
let uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
|
label: Some("custom3d"),
|
||||||
|
contents: bytemuck::cast_slice(&[0.0_f32; 4]), // 16 bytes aligned!
|
||||||
|
// Mapping at creation (as done by the create_buffer_init utility) doesn't require us to to add the MAP_WRITE usage
|
||||||
|
// (this *happens* to workaround this bug )
|
||||||
|
usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::UNIFORM,
|
||||||
|
});
|
||||||
|
|
||||||
|
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||||
|
label: Some("custom3d"),
|
||||||
|
layout: &bind_group_layout,
|
||||||
|
entries: &[wgpu::BindGroupEntry {
|
||||||
|
binding: 0,
|
||||||
|
resource: uniform_buffer.as_entire_binding(),
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
|
||||||
|
// Because the graphics pipeline must have the same lifetime as the egui render pass,
|
||||||
|
// instead of storing the pipeline in our `Custom3D` struct, we insert it into the
|
||||||
|
// `paint_callback_resources` type map, which is stored alongside the render pass.
|
||||||
|
wgpu_render_state
|
||||||
|
.renderer
|
||||||
|
.write()
|
||||||
|
.callback_resources
|
||||||
|
.insert(TriangleRenderResources {
|
||||||
|
pipeline,
|
||||||
|
bind_group,
|
||||||
|
uniform_buffer,
|
||||||
|
});
|
||||||
|
|
||||||
|
Some(Self {
|
||||||
|
name: "Jade".to_owned(),
|
||||||
|
age: 19,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl eframe::App for App {
|
||||||
|
fn update(&mut self, ctx: &eframe::egui::Context, frame: &mut eframe::Frame) {
|
||||||
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
ui.heading("My egui Application");
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
let name_label = ui.label("Your name: ");
|
||||||
|
ui.text_edit_singleline(&mut self.name)
|
||||||
|
.labelled_by(name_label.id);
|
||||||
|
});
|
||||||
|
ui.add(egui::Slider::new(&mut self.age, 0..=120).text("age"));
|
||||||
|
if ui.button("Increment").clicked() {
|
||||||
|
self.age += 1;
|
||||||
|
}
|
||||||
|
ui.label(format!("Hello '{}', age {}", self.name, self.age));
|
||||||
|
|
||||||
|
egui::Frame::canvas(ui.style()).show(ui, |ui| {
|
||||||
|
let (rect, response) =
|
||||||
|
ui.allocate_exact_size(egui::Vec2::splat(300.0), egui::Sense::drag());
|
||||||
|
dbg!(response);
|
||||||
|
|
||||||
|
let callback = egui_wgpu::Callback::new_paint_callback(
|
||||||
|
rect,
|
||||||
|
CustomTriangleCallback { angle: 0.5 },
|
||||||
|
);
|
||||||
|
ui.painter().add(callback);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod cb {
|
||||||
|
use eframe::{egui, egui_wgpu, wgpu};
|
||||||
|
|
||||||
|
pub struct CustomTriangleCallback {
|
||||||
|
pub angle: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl egui_wgpu::CallbackTrait for CustomTriangleCallback {
|
||||||
|
fn prepare(
|
||||||
|
&self,
|
||||||
|
device: &wgpu::Device,
|
||||||
|
queue: &wgpu::Queue,
|
||||||
|
_screen_descriptor: &egui_wgpu::ScreenDescriptor,
|
||||||
|
_egui_encoder: &mut wgpu::CommandEncoder,
|
||||||
|
resources: &mut egui_wgpu::CallbackResources,
|
||||||
|
) -> Vec<wgpu::CommandBuffer> {
|
||||||
|
let resources: &TriangleRenderResources = resources.get().unwrap();
|
||||||
|
resources.prepare(device, queue, self.angle);
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn paint<'a>(
|
||||||
|
&self,
|
||||||
|
_info: egui::PaintCallbackInfo,
|
||||||
|
render_pass: &mut wgpu::RenderPass<'a>,
|
||||||
|
resources: &'a egui_wgpu::CallbackResources,
|
||||||
|
) {
|
||||||
|
let resources: &TriangleRenderResources = resources.get().unwrap();
|
||||||
|
resources.paint(render_pass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub struct TriangleRenderResources {
|
||||||
|
pub pipeline: wgpu::RenderPipeline,
|
||||||
|
pub bind_group: wgpu::BindGroup,
|
||||||
|
pub uniform_buffer: wgpu::Buffer,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TriangleRenderResources {
|
||||||
|
fn prepare(&self, _device: &wgpu::Device, queue: &wgpu::Queue, angle: f32) {
|
||||||
|
// Update our uniform buffer with the angle from the UI
|
||||||
|
queue.write_buffer(
|
||||||
|
&self.uniform_buffer,
|
||||||
|
0,
|
||||||
|
bytemuck::cast_slice(&[angle, 0.0, 0.0, 0.0]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn paint<'rp>(&'rp self, render_pass: &mut wgpu::RenderPass<'rp>) {
|
||||||
|
// Draw our triangle!
|
||||||
|
render_pass.set_pipeline(&self.pipeline);
|
||||||
|
render_pass.set_bind_group(0, &self.bind_group, &[]);
|
||||||
|
render_pass.draw(0..3, 0..1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
src/main.rs
Normal file
13
src/main.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
use mathe_img_processor::App;
|
||||||
|
|
||||||
|
fn main() -> Result<(), eframe::Error> {
|
||||||
|
env_logger::init();
|
||||||
|
eframe::run_native(
|
||||||
|
"meow",
|
||||||
|
eframe::NativeOptions {
|
||||||
|
renderer: eframe::Renderer::Wgpu,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Box::new(|cc| Box::new(App::new(cc).unwrap())),
|
||||||
|
)
|
||||||
|
}
|
Loading…
Reference in a new issue