Add "Blend" node (#1024)

* Add Blend node

* Add more implementations

Currently, known buggy implementations:
* Color Burn
* Saturation

Opacity is currently achieved by linear interpolation, this will be changed as soon as all filters are implemented.

* Add more implementations

Currently, known incorrect implementations:
* Color Burn
* Saturation

Not yet Tested:
* Linear Burn
* Linear Dodge
* Vivid Light
* Linear Light
* Pin Light
* Hard Mix
* Subtract
* Divide

Opacity is currently achieved by linear interpolation, this will be changed as soon as all filters are implemented.

* Cleanup

* Removed Unused Code
* Fixed Clamping Issue
* Fixed Inverted Opacity
* Moved Opacity Calculation from individual  Blend Functions into 'blend_node' function

* Fix 'Color Burn' blend mode

Currently, known incorrect implementations:
* Saturation

Not yet Tested:
* Linear Burn
* Darker Color
* Linear Dodge
* Lighter Color
* Vivid Light
* Linear Light
* Pin Light
* Hard Mix
* Subtract
* Divide

Opacity is currently achieved by linear interpolation, this will be changed as soon as all filters are implemented.

* Fix 'Saturation' blend mode

Currently, known incorrect implementations:
* None :D

Not yet Tested:
* Linear Burn
* Darker Color
* Linear Dodge
* Lighter Color
* Vivid Light
* Linear Light
* Pin Light
* Hard Mix
* Subtract
* Divide

Opacity is currently achieved by linear interpolation, this will be changed as soon as all filters are implemented.

* Final Cleanups

* Add proper Inputs

* cargo fmt

* Add test for doubling number

* Display implementation for ProtoNetwork

* Switch top and bottom

* Add input types for blend image node

* Fix test

---------

Co-authored-by: 0hypercube <0hypercube@gmail.com>
Co-authored-by: Dennis Kobert <dennis@kobert.dev>
This commit is contained in:
isiko
2023-02-23 12:55:32 +01:00
committed by Keavon Chambers
parent 48dcc2774b
commit 8fe19063c1
10 changed files with 534 additions and 10 deletions

View File

@@ -115,4 +115,49 @@ mod tests {
let val = *dyn_any::downcast::<u32>(result).unwrap();
assert_eq!(val, 33_u32);
}
#[test]
fn double_number() {
use graph_craft::document::*;
use graph_craft::*;
let network = NodeNetwork {
inputs: vec![0],
outputs: vec![NodeOutput::new(1, 0)],
nodes: [
// Simple identity node taking a number as input from ouside the graph
(
0,
DocumentNode {
name: "id".into(),
inputs: vec![NodeInput::Network(concrete!(u32))],
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::IdNode")),
metadata: DocumentNodeMetadata::default(),
},
),
// An add node adding the result of the id node to its self
(
1,
DocumentNode {
name: "Add".into(),
inputs: vec![NodeInput::node(0, 0), NodeInput::node(0, 0)],
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::AddParameterNode<_>")),
metadata: DocumentNodeMetadata::default(),
},
),
]
.into_iter()
.collect(),
..Default::default()
};
use crate::executor::DynamicExecutor;
use graph_craft::executor::{Compiler, Executor};
let compiler = Compiler {};
let protograph = compiler.compile_single(network, true).expect("Graph should be generated");
let exec = DynamicExecutor::new(protograph).map(|e| panic!("The network should not type check: {:#?}", e)).unwrap_err();
}
}

View File

@@ -115,6 +115,25 @@ fn node_registry() -> HashMap<NodeIdentifier, HashMap<NodeIOTypes, NodeConstruct
// Filters
raster_node!(graphene_core::raster::LuminanceNode<_>, params: [LuminanceCalculation]),
raster_node!(graphene_core::raster::LevelsNode<_, _, _, _, _>, params: [f64, f64, f64, f64, f64]),
(
NodeIdentifier::new("graphene_core::raster::BlendNode<_, _, _, _>"),
|args| {
use graphene_core::Node;
let image: DowncastBothNode<(), Image> = DowncastBothNode::new(args[0]);
let blend_mode: DowncastBothNode<(), BlendMode> = DowncastBothNode::new(args[1]);
let opacity: DowncastBothNode<(), f64> = DowncastBothNode::new(args[2]);
let blend_node = graphene_core::raster::BlendNode::new(ClonedNode::new(blend_mode.eval(())), ClonedNode::new(opacity.eval(())));
let node = graphene_std::raster::BlendImageNode::new(image, ValueNode::new(blend_node));
let _ = &node as &dyn for<'i> Node<'i, Image, Output = Image>;
let any: DynAnyNode<Image, _, _> = graphene_std::any::DynAnyNode::new(graphene_core::value::ValueNode::new(node));
any.into_type_erased()
},
NodeIOTypes::new(
concrete!(Image),
concrete!(Image),
vec![(concrete!(()), concrete!(Image)), (concrete!(()), concrete!(BlendMode)), (concrete!(()), concrete!(f64))],
),
),
raster_node!(graphene_core::raster::GrayscaleNode<_, _, _, _, _, _, _>, params: [Color, f64, f64, f64, f64, f64, f64]),
raster_node!(graphene_core::raster::HueSaturationNode<_, _, _>, params: [f64, f64, f64]),
raster_node!(graphene_core::raster::InvertRGBNode, params: []),