mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-21 13:18:11 +08:00
Add raster module to graphene_core
This commit is contained in:
Generated
+1
@@ -185,6 +185,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"dyn-any",
|
"dyn-any",
|
||||||
|
"serde",
|
||||||
"spirv-std",
|
"spirv-std",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -20,3 +20,4 @@ dyn-any = {path = "../../libraries/dyn-any", features = ["derive"], optional = t
|
|||||||
|
|
||||||
spirv-std = { git = "https://github.com/EmbarkStudios/rust-gpu", features = ["glam"] , optional = true}
|
spirv-std = { git = "https://github.com/EmbarkStudios/rust-gpu", features = ["glam"] , optional = true}
|
||||||
async-trait = {version = "0.1", optional = true}
|
async-trait = {version = "0.1", optional = true}
|
||||||
|
serde = "1.0"
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use async_trait::async_trait;
|
|||||||
pub mod generic;
|
pub mod generic;
|
||||||
pub mod ops;
|
pub mod ops;
|
||||||
//pub mod structural;
|
//pub mod structural;
|
||||||
|
pub mod raster;
|
||||||
pub mod value;
|
pub mod value;
|
||||||
|
|
||||||
pub trait Node<'n> {
|
pub trait Node<'n> {
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
|
use crate::Node;
|
||||||
|
|
||||||
|
use self::color::Color;
|
||||||
|
|
||||||
|
pub mod color;
|
||||||
|
|
||||||
|
pub struct GrayscaleNode<'n, N: Node<'n, Output = Color>>(pub N, PhantomData<&'n ()>);
|
||||||
|
|
||||||
|
impl<'n, N: Node<'n, Output = Color>> Node<'n> for GrayscaleNode<'n, N> {
|
||||||
|
type Output = Color;
|
||||||
|
fn eval(&'n self) -> Color {
|
||||||
|
let color = self.0.eval();
|
||||||
|
let avg = (color.r() + color.g() + color.b()) / 3.0;
|
||||||
|
Color::from_rgbaf32(avg, avg, avg, color.a()).expect("Grayscale node created an invalid color")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,173 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
/// Structure that represents a color.
|
||||||
|
/// Internally alpha is stored as `f32` that ranges from `0.0` (transparent) to `1.0` (opaque).
|
||||||
|
/// The other components (RGB) are stored as `f32` that range from `0.0` up to `f32::MAX`,
|
||||||
|
/// the values encode the brightness of each channel proportional to the light intensity in cd/m² (nits) in HDR, and `0.0` (black) to `1.0` (white) in SDR color.
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize)]
|
||||||
|
pub struct Color {
|
||||||
|
red: f32,
|
||||||
|
green: f32,
|
||||||
|
blue: f32,
|
||||||
|
alpha: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Color {
|
||||||
|
pub const BLACK: Color = Color::from_unsafe(0., 0., 0.);
|
||||||
|
pub const WHITE: Color = Color::from_unsafe(1., 1., 1.);
|
||||||
|
pub const RED: Color = Color::from_unsafe(1., 0., 0.);
|
||||||
|
pub const GREEN: Color = Color::from_unsafe(0., 1., 0.);
|
||||||
|
pub const BLUE: Color = Color::from_unsafe(0., 0., 1.);
|
||||||
|
|
||||||
|
/// Returns `Some(Color)` if `red`, `green`, `blue` and `alpha` have a valid value. Negative numbers (including `-0.0`), NaN, and infinity are not valid values and return `None`.
|
||||||
|
/// Alpha values greater than `1.0` are not valid.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// use graphene_core::raster::color::Color;
|
||||||
|
/// let color = Color::from_rgbaf32(0.3, 0.14, 0.15, 0.92).unwrap();
|
||||||
|
/// assert!(color.components() == (0.3, 0.14, 0.15, 0.92));
|
||||||
|
///
|
||||||
|
/// let color = Color::from_rgbaf32(1.0, 1.0, 1.0, f32::NAN);
|
||||||
|
/// assert!(color == None);
|
||||||
|
/// ```
|
||||||
|
pub fn from_rgbaf32(red: f32, green: f32, blue: f32, alpha: f32) -> Option<Color> {
|
||||||
|
if alpha > 1. || [red, green, blue, alpha].iter().any(|c| c.is_sign_negative() || !c.is_finite()) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(Color { red, green, blue, alpha })
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return an opaque `Color` from given `f32` RGB channels.
|
||||||
|
pub const fn from_unsafe(red: f32, green: f32, blue: f32) -> Color {
|
||||||
|
Color { red, green, blue, alpha: 1. }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return an opaque SDR `Color` given RGB channels from `0` to `255`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// use graphene_core::raster::color::Color;
|
||||||
|
/// let color = Color::from_rgb8(0x72, 0x67, 0x62);
|
||||||
|
/// let color2 = Color::from_rgba8(0x72, 0x67, 0x62, 0xFF);
|
||||||
|
/// assert!(color == color2)
|
||||||
|
/// ```
|
||||||
|
pub fn from_rgb8(red: u8, green: u8, blue: u8) -> Color {
|
||||||
|
Color::from_rgba8(red, green, blue, 255)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return an SDR `Color` given RGBA channels from `0` to `255`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// use graphene_core::raster::color::Color;
|
||||||
|
/// let color = Color::from_rgba8(0x72, 0x67, 0x62, 0x61);
|
||||||
|
/// ```
|
||||||
|
pub fn from_rgba8(red: u8, green: u8, blue: u8, alpha: u8) -> Color {
|
||||||
|
let map_range = |int_color| int_color as f32 / 255.0;
|
||||||
|
Color {
|
||||||
|
red: map_range(red),
|
||||||
|
green: map_range(green),
|
||||||
|
blue: map_range(blue),
|
||||||
|
alpha: map_range(alpha),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the `red` component.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// use graphene_core::raster::color::Color;
|
||||||
|
/// let color = Color::from_rgbaf32(0.114, 0.103, 0.98, 0.97).unwrap();
|
||||||
|
/// assert!(color.r() == 0.114);
|
||||||
|
/// ```
|
||||||
|
pub fn r(&self) -> f32 {
|
||||||
|
self.red
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the `green` component.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// use graphene_core::raster::color::Color;
|
||||||
|
/// let color = Color::from_rgbaf32(0.114, 0.103, 0.98, 0.97).unwrap();
|
||||||
|
/// assert!(color.g() == 0.103);
|
||||||
|
/// ```
|
||||||
|
pub fn g(&self) -> f32 {
|
||||||
|
self.green
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the `blue` component.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// use graphene_core::raster::color::Color;
|
||||||
|
/// let color = Color::from_rgbaf32(0.114, 0.103, 0.98, 0.97).unwrap();
|
||||||
|
/// assert!(color.b() == 0.98);
|
||||||
|
/// ```
|
||||||
|
pub fn b(&self) -> f32 {
|
||||||
|
self.blue
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the `alpha` component without checking its expected `0.0` to `1.0` range.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// use graphene_core::raster::color::Color;
|
||||||
|
/// let color = Color::from_rgbaf32(0.114, 0.103, 0.98, 0.97).unwrap();
|
||||||
|
/// assert!(color.a() == 0.97);
|
||||||
|
/// ```
|
||||||
|
pub fn a(&self) -> f32 {
|
||||||
|
self.alpha
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the all components as a tuple, first component is red, followed by green, followed by blue, followed by alpha.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// use graphene_core::raster::color::Color;
|
||||||
|
/// let color = Color::from_rgbaf32(0.114, 0.103, 0.98, 0.97).unwrap();
|
||||||
|
/// assert!(color.components() == (0.114, 0.103, 0.98, 0.97));
|
||||||
|
/// ```
|
||||||
|
pub fn components(&self) -> (f32, f32, f32, f32) {
|
||||||
|
(self.red, self.green, self.blue, self.alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Readd formatting
|
||||||
|
|
||||||
|
/// Creates a color from a 8-character RGBA hex string (without a # prefix).
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// use graphene_core::raster::color::Color;
|
||||||
|
/// let color = Color::from_rgba_str("7C67FA61").unwrap();
|
||||||
|
/// ```
|
||||||
|
pub fn from_rgba_str(color_str: &str) -> Option<Color> {
|
||||||
|
if color_str.len() != 8 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let r = u8::from_str_radix(&color_str[0..2], 16).ok()?;
|
||||||
|
let g = u8::from_str_radix(&color_str[2..4], 16).ok()?;
|
||||||
|
let b = u8::from_str_radix(&color_str[4..6], 16).ok()?;
|
||||||
|
let a = u8::from_str_radix(&color_str[6..8], 16).ok()?;
|
||||||
|
|
||||||
|
Some(Color::from_rgba8(r, g, b, a))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a color from a 6-character RGB hex string (without a # prefix).
|
||||||
|
/// ```
|
||||||
|
/// use graphene_core::raster::color::Color;
|
||||||
|
/// let color = Color::from_rgb_str("7C67FA").unwrap();
|
||||||
|
/// ```
|
||||||
|
pub fn from_rgb_str(color_str: &str) -> Option<Color> {
|
||||||
|
if color_str.len() != 6 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let r = u8::from_str_radix(&color_str[0..2], 16).ok()?;
|
||||||
|
let g = u8::from_str_radix(&color_str[2..4], 16).ok()?;
|
||||||
|
let b = u8::from_str_radix(&color_str[4..6], 16).ok()?;
|
||||||
|
|
||||||
|
Some(Color::from_rgb8(r, g, b))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
# [cfg (target_arch = "spirv")]pub mod gpu {
|
|
||||||
# [repr (C )]pub struct PushConsts {
|
|
||||||
n : u32 , node : u32 ,
|
|
||||||
}
|
|
||||||
use super :: * ;
|
|
||||||
use spirv_std :: glam :: UVec3 ;
|
|
||||||
# [allow (unused )]# [spirv (compute (threads (64)))]pub fn "add"(# [spirv (global_invocation_id )]global_id : UVec3 , # [spirv (storage_buffer , descriptor_set = 0, binding = 0)]a : & [u32 ], # [spirv (storage_buffer , descriptor_set = 0, binding = 1)]y : & mut [u32 ], # [spirv (push_constant )]push_consts : & PushConsts , ){
|
|
||||||
fn node_graph (input : u32 )-> u32 {
|
|
||||||
let n0 = graphene_core :: value :: ValueNode :: new (input );
|
|
||||||
let n1 = graphene_core :: value :: ValueNode :: new (1u32);
|
|
||||||
let n2 = graphene_core :: ops :: AddNode :: new ((& n0 , & n1 ));
|
|
||||||
n2 . eval ()
|
|
||||||
}
|
|
||||||
let gid = global_id . x as usize ;
|
|
||||||
if global_id . x < push_consts . n {
|
|
||||||
y [gid ]= node_graph (a [gid ]);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -6,7 +6,7 @@ pub mod memo;
|
|||||||
|
|
||||||
pub use graphene_core::*;
|
pub use graphene_core::*;
|
||||||
|
|
||||||
use dyn_any::{downcast_ref, DynAny, StaticType};
|
use dyn_any::DynAny;
|
||||||
pub type DynNode<'n, T> = &'n (dyn Node<'n, Output = T> + 'n);
|
pub type DynNode<'n, T> = &'n (dyn Node<'n, Output = T> + 'n);
|
||||||
pub type DynAnyNode<'n> = &'n (dyn Node<'n, Output = &'n dyn DynAny<'n>> + 'n);
|
pub type DynAnyNode<'n> = &'n (dyn Node<'n, Output = &'n dyn DynAny<'n>> + 'n);
|
||||||
|
|
||||||
|
|||||||
+23
-23
@@ -1,15 +1,15 @@
|
|||||||
use borrow_stack::BorrowStack;
|
|
||||||
//#![feature(generic_associated_types)]
|
//#![feature(generic_associated_types)]
|
||||||
use dyn_any::{DynAny, StaticType};
|
// use borrow_stack::BorrowStack;
|
||||||
use graphene_std::value::{AnyRefNode, AnyValueNode, StorageNode, ValueNode};
|
// use dyn_any::{DynAny, StaticType};
|
||||||
use graphene_std::*;
|
// use graphene_std::value::{AnyRefNode, AnyValueNode, StorageNode, ValueNode};
|
||||||
|
// use graphene_std::*;
|
||||||
|
|
||||||
/*fn mul(#[dyn_any(default)] a: f32, b: f32) -> f32 {
|
/*fn mul(#[dyn_any(default)] a: f32, b: f32) -> f32 {
|
||||||
a * b
|
a * b
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
mod mul {
|
mod mul {
|
||||||
use dyn_any::{downcast_ref, DynAny, StaticType};
|
use dyn_any::downcast_ref;
|
||||||
use graphene_std::{DynAnyNode, DynNode, DynamicInput, Node};
|
use graphene_std::{DynAnyNode, DynNode, DynamicInput, Node};
|
||||||
pub struct MulNodeInput<'n> {
|
pub struct MulNodeInput<'n> {
|
||||||
pub a: &'n f32,
|
pub a: &'n f32,
|
||||||
@@ -28,7 +28,7 @@ mod mul {
|
|||||||
impl<'n> Node<'n> for MulNodeAnyProxy<'n> {
|
impl<'n> Node<'n> for MulNodeAnyProxy<'n> {
|
||||||
type Output = MulNodeInput<'n>;
|
type Output = MulNodeInput<'n>;
|
||||||
fn eval(&'n self) -> <Self as graphene_std::Node<'n>>::Output {
|
fn eval(&'n self) -> <Self as graphene_std::Node<'n>>::Output {
|
||||||
let a = self.a.unwrap().eval();
|
// let a = self.a.unwrap().eval();
|
||||||
let a: &f32 = self.a.map(|v| downcast_ref(v.eval()).unwrap()).unwrap_or(&1.);
|
let a: &f32 = self.a.map(|v| downcast_ref(v.eval()).unwrap()).unwrap_or(&1.);
|
||||||
/*let b: &f32 = self
|
/*let b: &f32 = self
|
||||||
.b
|
.b
|
||||||
@@ -55,7 +55,7 @@ mod mul {
|
|||||||
//pub(crate) use new;
|
//pub(crate) use new;
|
||||||
|
|
||||||
impl<'n> DynamicInput<'n> for MulNodeAnyProxy<'n> {
|
impl<'n> DynamicInput<'n> for MulNodeAnyProxy<'n> {
|
||||||
fn set_kwarg_by_name(&mut self, name: &str, value: DynAnyNode<'n>) {
|
fn set_kwarg_by_name(&mut self, _name: &str, _value: DynAnyNode<'n>) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
fn set_arg_by_index(&mut self, index: usize, value: DynAnyNode<'n>) {
|
fn set_arg_by_index(&mut self, index: usize, value: DynAnyNode<'n>) {
|
||||||
@@ -68,29 +68,29 @@ mod mul {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
type SNode<'n> = dyn Node<'n, Output = &'n dyn DynAny<'n>>;
|
// type SNode<'n> = dyn Node<'n, Output = &'n dyn DynAny<'n>>;
|
||||||
|
|
||||||
struct NodeStore<'n>(borrow_stack::FixedSizeStack<'n, Box<SNode<'n>>>);
|
// struct NodeStore<'n>(borrow_stack::FixedSizeStack<'n, Box<SNode<'n>>>);
|
||||||
|
|
||||||
impl<'n> NodeStore<'n> {
|
// impl<'n> NodeStore<'n> {
|
||||||
fn len(&self) -> usize {
|
// fn len(&self) -> usize {
|
||||||
self.0.len()
|
// self.0.len()
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn push(&'n mut self, f: fn(&'n [Box<SNode>]) -> Box<SNode<'n>>) {
|
// fn push(&'n mut self, f: fn(&'n [Box<SNode>]) -> Box<SNode<'n>>) {
|
||||||
unsafe { self.0.push(f(self.0.get())) };
|
// unsafe { self.0.push(f(self.0.get())) };
|
||||||
}
|
// }
|
||||||
|
|
||||||
/*fn get_index(&'n self, index: usize) -> &'n SNode<'n> {
|
// /*fn get_index(&'n self, index: usize) -> &'n SNode<'n> {
|
||||||
assert!(index < self.0.len());
|
// assert!(index < self.0.len());
|
||||||
&unsafe { self.0.get()[index] }
|
// &unsafe { self.0.get()[index] }
|
||||||
}*/
|
// }*/
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
use graphene_std::*;
|
use graphene_std::*;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::parse::Parse;
|
// use syn::parse::Parse;
|
||||||
let nodes = vec![
|
let nodes = vec![
|
||||||
NodeKind::Input,
|
NodeKind::Input,
|
||||||
NodeKind::Value(syn::parse_quote!(1u32)),
|
NodeKind::Value(syn::parse_quote!(1u32)),
|
||||||
@@ -99,7 +99,7 @@ fn main() {
|
|||||||
|
|
||||||
//println!("{}", node_graph(1));
|
//println!("{}", node_graph(1));
|
||||||
|
|
||||||
let nodegraph = NodeGraph {
|
let _nodegraph = NodeGraph {
|
||||||
nodes,
|
nodes,
|
||||||
input: syn::Type::Verbatim(quote! {u32}),
|
input: syn::Type::Verbatim(quote! {u32}),
|
||||||
output: syn::Type::Verbatim(quote! {u32}),
|
output: syn::Type::Verbatim(quote! {u32}),
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use core::marker::PhantomData;
|
|||||||
pub use graphene_core::value::*;
|
pub use graphene_core::value::*;
|
||||||
use graphene_core::Node;
|
use graphene_core::Node;
|
||||||
|
|
||||||
use dyn_any::{DynAny, StaticType, StaticTypeSized};
|
use dyn_any::DynAny;
|
||||||
|
|
||||||
pub struct AnyRefNode<'n, N: Node<'n>>(N, PhantomData<&'n ()>);
|
pub struct AnyRefNode<'n, N: Node<'n>>(N, PhantomData<&'n ()>);
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ fn generate_to_string(parsed: ItemFn, string: String) -> TokenStream {
|
|||||||
let types = extract_arg_types(fn_args);
|
let types = extract_arg_types(fn_args);
|
||||||
let types = types.iter().map(|t| t.to_token_stream()).collect::<Vec<_>>();
|
let types = types.iter().map(|t| t.to_token_stream()).collect::<Vec<_>>();
|
||||||
let idents = idents.iter().map(|t| t.to_token_stream()).collect::<Vec<_>>();
|
let idents = idents.iter().map(|t| t.to_token_stream()).collect::<Vec<_>>();
|
||||||
let const_idents = idents
|
let _const_idents = idents
|
||||||
.iter()
|
.iter()
|
||||||
.map(|t| {
|
.map(|t| {
|
||||||
let name = t.to_string().to_uppercase();
|
let name = t.to_string().to_uppercase();
|
||||||
|
|||||||
Reference in New Issue
Block a user