Make noise generation resolution aware (#1909)
* Make noise generation resolution aware * Invert "Scale" so it's not "Frequency"; make "Clipping" 100x100 not 1x1 --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
parent
0dfddd529b
commit
c5dde18fd6
|
|
@ -776,48 +776,10 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||||
identifier: "Noise Pattern",
|
identifier: "Noise Pattern",
|
||||||
node_template: NodeTemplate {
|
node_template: NodeTemplate {
|
||||||
document_node: DocumentNode {
|
document_node: DocumentNode {
|
||||||
implementation: DocumentNodeImplementation::Network(NodeNetwork {
|
|
||||||
exports: vec![NodeInput::node(NodeId(1), 0)],
|
|
||||||
nodes: vec![
|
|
||||||
DocumentNode {
|
|
||||||
inputs: vec![
|
|
||||||
NodeInput::network(concrete!(()), 0),
|
|
||||||
NodeInput::network(concrete!(UVec2), 1),
|
|
||||||
NodeInput::network(concrete!(u32), 2),
|
|
||||||
NodeInput::network(concrete!(f64), 3),
|
|
||||||
NodeInput::network(concrete!(graphene_core::raster::NoiseType), 4),
|
|
||||||
NodeInput::network(concrete!(graphene_core::raster::FractalType), 5),
|
|
||||||
NodeInput::network(concrete!(f64), 6),
|
|
||||||
NodeInput::network(concrete!(graphene_core::raster::FractalType), 7),
|
|
||||||
NodeInput::network(concrete!(u32), 8),
|
|
||||||
NodeInput::network(concrete!(f64), 9),
|
|
||||||
NodeInput::network(concrete!(f64), 10),
|
|
||||||
NodeInput::network(concrete!(f64), 11),
|
|
||||||
NodeInput::network(concrete!(f64), 12),
|
|
||||||
NodeInput::network(concrete!(graphene_core::raster::CellularDistanceFunction), 13),
|
|
||||||
NodeInput::network(concrete!(graphene_core::raster::CellularReturnType), 14),
|
|
||||||
NodeInput::network(concrete!(f64), 15),
|
|
||||||
],
|
|
||||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_std::raster::NoisePatternNode<_, _, _, _, _, _, _, _, _, _, _, _, _, _, _>")),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
// TODO: Make noise pattern node resolution aware and remove the cull node
|
|
||||||
DocumentNode {
|
|
||||||
inputs: vec![NodeInput::node(NodeId(0), 0)],
|
|
||||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::transform::CullNode<_>")),
|
|
||||||
manual_composition: Some(concrete!(Footprint)),
|
manual_composition: Some(concrete!(Footprint)),
|
||||||
..Default::default()
|
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_std::raster::NoisePatternNode<_, _, _, _, _, _, _, _, _, _, _, _, _, _, _>")),
|
||||||
},
|
|
||||||
]
|
|
||||||
.into_iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(id, node)| (NodeId(id as u64), node))
|
|
||||||
.collect(),
|
|
||||||
..Default::default()
|
|
||||||
}),
|
|
||||||
inputs: vec![
|
inputs: vec![
|
||||||
NodeInput::value(TaggedValue::None, false),
|
NodeInput::value(TaggedValue::Bool(true), false),
|
||||||
NodeInput::value(TaggedValue::UVec2((512, 512).into()), false),
|
|
||||||
NodeInput::value(TaggedValue::U32(0), false),
|
NodeInput::value(TaggedValue::U32(0), false),
|
||||||
NodeInput::value(TaggedValue::F64(10.), false),
|
NodeInput::value(TaggedValue::F64(10.), false),
|
||||||
NodeInput::value(TaggedValue::NoiseType(NoiseType::default()), false),
|
NodeInput::value(TaggedValue::NoiseType(NoiseType::default()), false),
|
||||||
|
|
@ -837,8 +799,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||||
},
|
},
|
||||||
persistent_node_metadata: DocumentNodePersistentMetadata {
|
persistent_node_metadata: DocumentNodePersistentMetadata {
|
||||||
input_names: vec![
|
input_names: vec![
|
||||||
"None".to_string(),
|
"Clip".to_string(),
|
||||||
"Dimensions".to_string(),
|
|
||||||
"Seed".to_string(),
|
"Seed".to_string(),
|
||||||
"Scale".to_string(),
|
"Scale".to_string(),
|
||||||
"Noise Type".to_string(),
|
"Noise Type".to_string(),
|
||||||
|
|
|
||||||
|
|
@ -945,15 +945,15 @@ pub fn extract_channel_properties(document_node: &DocumentNode, node_id: NodeId,
|
||||||
// As soon as there are more types of noise, this should be uncommented.
|
// As soon as there are more types of noise, this should be uncommented.
|
||||||
pub fn noise_pattern_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
pub fn noise_pattern_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
||||||
// Get the current values of the inputs of interest so they can set whether certain inputs are disabled based on various conditions.
|
// Get the current values of the inputs of interest so they can set whether certain inputs are disabled based on various conditions.
|
||||||
let current_noise_type = match &document_node.inputs[4].as_value() {
|
let current_noise_type = match &document_node.inputs[3].as_value() {
|
||||||
Some(&TaggedValue::NoiseType(noise_type)) => Some(noise_type),
|
Some(&TaggedValue::NoiseType(noise_type)) => Some(noise_type),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
let current_domain_warp_type = match &document_node.inputs[5].as_value() {
|
let current_domain_warp_type = match &document_node.inputs[4].as_value() {
|
||||||
Some(&TaggedValue::DomainWarpType(domain_warp_type)) => Some(domain_warp_type),
|
Some(&TaggedValue::DomainWarpType(domain_warp_type)) => Some(domain_warp_type),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
let current_fractal_type = match &document_node.inputs[7].as_value() {
|
let current_fractal_type = match &document_node.inputs[6].as_value() {
|
||||||
Some(&TaggedValue::FractalType(fractal_type)) => Some(fractal_type),
|
Some(&TaggedValue::FractalType(fractal_type)) => Some(fractal_type),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
@ -966,28 +966,30 @@ pub fn noise_pattern_properties(document_node: &DocumentNode, node_id: NodeId, _
|
||||||
!domain_warp_active && (current_fractal_type == Some(FractalType::DomainWarpIndependent) || current_fractal_type == Some(FractalType::DomainWarpProgressive));
|
!domain_warp_active && (current_fractal_type == Some(FractalType::DomainWarpIndependent) || current_fractal_type == Some(FractalType::DomainWarpProgressive));
|
||||||
|
|
||||||
// All
|
// All
|
||||||
let dimensions = vec2_widget(document_node, node_id, 1, "Dimensions", "W", "H", "px", Some(1.), add_blank_assist);
|
let clip = LayoutGroup::Row {
|
||||||
let seed = number_widget(document_node, node_id, 2, "Seed", NumberInput::default().min(0.).is_integer(true), true);
|
widgets: bool_widget(document_node, node_id, 0, "Clip", true),
|
||||||
let scale = number_widget(document_node, node_id, 3, "Scale", NumberInput::default().min(0.).disabled(!coherent_noise_active), true);
|
};
|
||||||
let noise_type_row = noise_type(document_node, node_id, 4, "Noise Type", true);
|
let seed = number_widget(document_node, node_id, 1, "Seed", NumberInput::default().min(0.).is_integer(true), true);
|
||||||
|
let scale = number_widget(document_node, node_id, 2, "Scale", NumberInput::default().min(0.).disabled(!coherent_noise_active), true);
|
||||||
|
let noise_type_row = noise_type(document_node, node_id, 3, "Noise Type", true);
|
||||||
|
|
||||||
// Domain Warp
|
// Domain Warp
|
||||||
let domain_warp_type_row = domain_warp_type(document_node, node_id, 5, "Domain Warp Type", true, !coherent_noise_active);
|
let domain_warp_type_row = domain_warp_type(document_node, node_id, 4, "Domain Warp Type", true, !coherent_noise_active);
|
||||||
let domain_warp_amplitude = number_widget(
|
let domain_warp_amplitude = number_widget(
|
||||||
document_node,
|
document_node,
|
||||||
node_id,
|
node_id,
|
||||||
6,
|
5,
|
||||||
"Domain Warp Amplitude",
|
"Domain Warp Amplitude",
|
||||||
NumberInput::default().min(0.).disabled(!coherent_noise_active || !domain_warp_active),
|
NumberInput::default().min(0.).disabled(!coherent_noise_active || !domain_warp_active),
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Fractal
|
// Fractal
|
||||||
let fractal_type_row = fractal_type(document_node, node_id, 7, "Fractal Type", true, !coherent_noise_active);
|
let fractal_type_row = fractal_type(document_node, node_id, 6, "Fractal Type", true, !coherent_noise_active);
|
||||||
let fractal_octaves = number_widget(
|
let fractal_octaves = number_widget(
|
||||||
document_node,
|
document_node,
|
||||||
node_id,
|
node_id,
|
||||||
8,
|
7,
|
||||||
"Fractal Octaves",
|
"Fractal Octaves",
|
||||||
NumberInput::default()
|
NumberInput::default()
|
||||||
.mode_range()
|
.mode_range()
|
||||||
|
|
@ -1001,7 +1003,7 @@ pub fn noise_pattern_properties(document_node: &DocumentNode, node_id: NodeId, _
|
||||||
let fractal_lacunarity = number_widget(
|
let fractal_lacunarity = number_widget(
|
||||||
document_node,
|
document_node,
|
||||||
node_id,
|
node_id,
|
||||||
9,
|
8,
|
||||||
"Fractal Lacunarity",
|
"Fractal Lacunarity",
|
||||||
NumberInput::default()
|
NumberInput::default()
|
||||||
.mode_range()
|
.mode_range()
|
||||||
|
|
@ -1013,7 +1015,7 @@ pub fn noise_pattern_properties(document_node: &DocumentNode, node_id: NodeId, _
|
||||||
let fractal_gain = number_widget(
|
let fractal_gain = number_widget(
|
||||||
document_node,
|
document_node,
|
||||||
node_id,
|
node_id,
|
||||||
10,
|
9,
|
||||||
"Fractal Gain",
|
"Fractal Gain",
|
||||||
NumberInput::default()
|
NumberInput::default()
|
||||||
.mode_range()
|
.mode_range()
|
||||||
|
|
@ -1025,7 +1027,7 @@ pub fn noise_pattern_properties(document_node: &DocumentNode, node_id: NodeId, _
|
||||||
let fractal_weighted_strength = number_widget(
|
let fractal_weighted_strength = number_widget(
|
||||||
document_node,
|
document_node,
|
||||||
node_id,
|
node_id,
|
||||||
11,
|
10,
|
||||||
"Fractal Weighted Strength",
|
"Fractal Weighted Strength",
|
||||||
NumberInput::default()
|
NumberInput::default()
|
||||||
.mode_range()
|
.mode_range()
|
||||||
|
|
@ -1037,7 +1039,7 @@ pub fn noise_pattern_properties(document_node: &DocumentNode, node_id: NodeId, _
|
||||||
let fractal_ping_pong_strength = number_widget(
|
let fractal_ping_pong_strength = number_widget(
|
||||||
document_node,
|
document_node,
|
||||||
node_id,
|
node_id,
|
||||||
12,
|
11,
|
||||||
"Fractal Ping Pong Strength",
|
"Fractal Ping Pong Strength",
|
||||||
NumberInput::default()
|
NumberInput::default()
|
||||||
.mode_range()
|
.mode_range()
|
||||||
|
|
@ -1048,12 +1050,12 @@ pub fn noise_pattern_properties(document_node: &DocumentNode, node_id: NodeId, _
|
||||||
);
|
);
|
||||||
|
|
||||||
// Cellular
|
// Cellular
|
||||||
let cellular_distance_function_row = cellular_distance_function(document_node, node_id, 13, "Cellular Distance Function", true, !coherent_noise_active || !cellular_noise_active);
|
let cellular_distance_function_row = cellular_distance_function(document_node, node_id, 12, "Cellular Distance Function", true, !coherent_noise_active || !cellular_noise_active);
|
||||||
let cellular_return_type = cellular_return_type(document_node, node_id, 14, "Cellular Return Type", true, !coherent_noise_active || !cellular_noise_active);
|
let cellular_return_type = cellular_return_type(document_node, node_id, 13, "Cellular Return Type", true, !coherent_noise_active || !cellular_noise_active);
|
||||||
let cellular_jitter = number_widget(
|
let cellular_jitter = number_widget(
|
||||||
document_node,
|
document_node,
|
||||||
node_id,
|
node_id,
|
||||||
15,
|
14,
|
||||||
"Cellular Jitter",
|
"Cellular Jitter",
|
||||||
NumberInput::default()
|
NumberInput::default()
|
||||||
.mode_range()
|
.mode_range()
|
||||||
|
|
@ -1065,7 +1067,7 @@ pub fn noise_pattern_properties(document_node: &DocumentNode, node_id: NodeId, _
|
||||||
|
|
||||||
vec![
|
vec![
|
||||||
// All
|
// All
|
||||||
dimensions,
|
clip,
|
||||||
LayoutGroup::Row { widgets: seed },
|
LayoutGroup::Row { widgets: seed },
|
||||||
LayoutGroup::Row { widgets: scale },
|
LayoutGroup::Row { widgets: scale },
|
||||||
noise_type_row,
|
noise_type_row,
|
||||||
|
|
|
||||||
|
|
@ -168,9 +168,7 @@ impl Footprint {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scale(&self) -> DVec2 {
|
pub fn scale(&self) -> DVec2 {
|
||||||
let x = self.transform.transform_vector2((1., 0.).into()).length();
|
self.transform.decompose_scale()
|
||||||
let y = self.transform.transform_vector2((0., 1.).into()).length();
|
|
||||||
DVec2::new(x, y)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn offset(&self) -> DVec2 {
|
pub fn offset(&self) -> DVec2 {
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ use graphene_core::value::CopiedNode;
|
||||||
use graphene_core::{AlphaBlending, Color, Node, WasmNotSend};
|
use graphene_core::{AlphaBlending, Color, Node, WasmNotSend};
|
||||||
|
|
||||||
use fastnoise_lite;
|
use fastnoise_lite;
|
||||||
use glam::{DAffine2, DVec2, UVec2, Vec2};
|
use glam::{DAffine2, DVec2, Vec2};
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use rand_chacha::ChaCha8Rng;
|
use rand_chacha::ChaCha8Rng;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
@ -586,7 +586,7 @@ fn image_frame<_P: Pixel>(image: Image<_P>, transform: DAffine2) -> graphene_cor
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct NoisePatternNode<
|
pub struct NoisePatternNode<
|
||||||
Dimensions,
|
Clip,
|
||||||
Seed,
|
Seed,
|
||||||
Scale,
|
Scale,
|
||||||
NoiseType,
|
NoiseType,
|
||||||
|
|
@ -602,7 +602,7 @@ pub struct NoisePatternNode<
|
||||||
CellularReturnType,
|
CellularReturnType,
|
||||||
CellularJitter,
|
CellularJitter,
|
||||||
> {
|
> {
|
||||||
dimensions: Dimensions,
|
clip: Clip,
|
||||||
seed: Seed,
|
seed: Seed,
|
||||||
scale: Scale,
|
scale: Scale,
|
||||||
noise_type: NoiseType,
|
noise_type: NoiseType,
|
||||||
|
|
@ -622,8 +622,8 @@ pub struct NoisePatternNode<
|
||||||
#[node_macro::node_fn(NoisePatternNode)]
|
#[node_macro::node_fn(NoisePatternNode)]
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn noise_pattern(
|
fn noise_pattern(
|
||||||
_no_primary_input: (),
|
footprint: Footprint,
|
||||||
dimensions: UVec2,
|
clip: bool,
|
||||||
seed: u32,
|
seed: u32,
|
||||||
scale: f64,
|
scale: f64,
|
||||||
noise_type: NoiseType,
|
noise_type: NoiseType,
|
||||||
|
|
@ -639,11 +639,33 @@ fn noise_pattern(
|
||||||
cellular_return_type: CellularReturnType,
|
cellular_return_type: CellularReturnType,
|
||||||
cellular_jitter: f64,
|
cellular_jitter: f64,
|
||||||
) -> graphene_core::raster::ImageFrame<Color> {
|
) -> graphene_core::raster::ImageFrame<Color> {
|
||||||
|
let viewport_bounds = footprint.viewport_bounds_in_local_space();
|
||||||
|
|
||||||
|
let mut size = viewport_bounds.size();
|
||||||
|
let mut offset = viewport_bounds.start;
|
||||||
|
if clip {
|
||||||
|
// TODO: Remove "clip" entirely (and its arbitrary 100x100 clipping square) once we have proper resolution-aware layer clipping
|
||||||
|
const CLIPPING_SQUARE_SIZE: f64 = 100.;
|
||||||
|
let image_bounds = Bbox::from_transform(DAffine2::from_scale(DVec2::splat(CLIPPING_SQUARE_SIZE))).to_axis_aligned_bbox();
|
||||||
|
let intersection = viewport_bounds.intersect(&image_bounds);
|
||||||
|
|
||||||
|
offset = (intersection.start - image_bounds.start).max(DVec2::ZERO);
|
||||||
|
size = intersection.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the image would not be visible, return an empty image
|
||||||
|
if size.x <= 0. || size.y <= 0. {
|
||||||
|
return ImageFrame::empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
let footprint_scale = footprint.scale();
|
||||||
|
let width = (size.x * footprint_scale.x) as u32;
|
||||||
|
let height = (size.y * footprint_scale.y) as u32;
|
||||||
|
|
||||||
// All
|
// All
|
||||||
let [width, height] = dimensions.to_array();
|
|
||||||
let mut image = Image::new(width, height, Color::from_luminance(0.5));
|
let mut image = Image::new(width, height, Color::from_luminance(0.5));
|
||||||
let mut noise = fastnoise_lite::FastNoiseLite::with_seed(seed as i32);
|
let mut noise = fastnoise_lite::FastNoiseLite::with_seed(seed as i32);
|
||||||
noise.set_frequency(Some(scale as f32 / 1000.));
|
noise.set_frequency(Some(1. / (scale as f32).max(f32::EPSILON)));
|
||||||
|
|
||||||
// Domain Warp
|
// Domain Warp
|
||||||
let domain_warp_type = match domain_warp_type {
|
let domain_warp_type = match domain_warp_type {
|
||||||
|
|
@ -665,6 +687,8 @@ fn noise_pattern(
|
||||||
NoiseType::ValueCubic => fastnoise_lite::NoiseType::ValueCubic,
|
NoiseType::ValueCubic => fastnoise_lite::NoiseType::ValueCubic,
|
||||||
NoiseType::Value => fastnoise_lite::NoiseType::Value,
|
NoiseType::Value => fastnoise_lite::NoiseType::Value,
|
||||||
NoiseType::WhiteNoise => {
|
NoiseType::WhiteNoise => {
|
||||||
|
// TODO: Generate in layer space, not viewport space
|
||||||
|
|
||||||
let mut rng = ChaCha8Rng::seed_from_u64(seed as u64);
|
let mut rng = ChaCha8Rng::seed_from_u64(seed as u64);
|
||||||
|
|
||||||
for y in 0..height {
|
for y in 0..height {
|
||||||
|
|
@ -677,7 +701,7 @@ fn noise_pattern(
|
||||||
|
|
||||||
return ImageFrame::<Color> {
|
return ImageFrame::<Color> {
|
||||||
image,
|
image,
|
||||||
transform: DAffine2::from_scale(DVec2::new(width as f64, height as f64)),
|
transform: DAffine2::from_translation(offset) * DAffine2::from_scale(size),
|
||||||
alpha_blending: AlphaBlending::default(),
|
alpha_blending: AlphaBlending::default(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -718,12 +742,16 @@ fn noise_pattern(
|
||||||
noise.set_cellular_return_type(Some(cellular_return_type));
|
noise.set_cellular_return_type(Some(cellular_return_type));
|
||||||
noise.set_cellular_jitter(Some(cellular_jitter as f32));
|
noise.set_cellular_jitter(Some(cellular_jitter as f32));
|
||||||
|
|
||||||
|
let coordinate_offset = offset.as_vec2();
|
||||||
|
let scale = size.as_vec2() / Vec2::new(width as f32, height as f32);
|
||||||
// Calculate the noise for every pixel
|
// Calculate the noise for every pixel
|
||||||
for y in 0..height {
|
for y in 0..height {
|
||||||
for x in 0..width {
|
for x in 0..width {
|
||||||
let pixel = image.get_pixel_mut(x, y).unwrap();
|
let pixel = image.get_pixel_mut(x, y).unwrap();
|
||||||
|
let pos = Vec2::new(x as f32, y as f32);
|
||||||
|
let vec = pos * scale + coordinate_offset;
|
||||||
|
|
||||||
let (mut x, mut y) = (x as f32, y as f32);
|
let (mut x, mut y) = (vec.x, vec.y);
|
||||||
if domain_warp_active && domain_warp_amplitude > 0. {
|
if domain_warp_active && domain_warp_amplitude > 0. {
|
||||||
(x, y) = noise.domain_warp_2d(x, y);
|
(x, y) = noise.domain_warp_2d(x, y);
|
||||||
}
|
}
|
||||||
|
|
@ -736,7 +764,7 @@ fn noise_pattern(
|
||||||
// Return the coherent noise image
|
// Return the coherent noise image
|
||||||
ImageFrame::<Color> {
|
ImageFrame::<Color> {
|
||||||
image,
|
image,
|
||||||
transform: DAffine2::from_scale(DVec2::new(width as f64, height as f64)),
|
transform: DAffine2::from_translation(offset) * DAffine2::from_scale(size),
|
||||||
alpha_blending: AlphaBlending::default(),
|
alpha_blending: AlphaBlending::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -748,20 +776,17 @@ pub struct MandelbrotNode;
|
||||||
fn mandelbrot_node(footprint: Footprint) -> ImageFrame<Color> {
|
fn mandelbrot_node(footprint: Footprint) -> ImageFrame<Color> {
|
||||||
let viewport_bounds = footprint.viewport_bounds_in_local_space();
|
let viewport_bounds = footprint.viewport_bounds_in_local_space();
|
||||||
|
|
||||||
let width = footprint.resolution.x;
|
|
||||||
let height = footprint.resolution.y;
|
|
||||||
|
|
||||||
let image_bounds = Bbox::from_transform(DAffine2::IDENTITY).to_axis_aligned_bbox();
|
let image_bounds = Bbox::from_transform(DAffine2::IDENTITY).to_axis_aligned_bbox();
|
||||||
let intersection = viewport_bounds.intersect(&image_bounds);
|
let intersection = viewport_bounds.intersect(&image_bounds);
|
||||||
let size = intersection.size();
|
let size = intersection.size();
|
||||||
|
|
||||||
|
let offset = (intersection.start - image_bounds.start).max(DVec2::ZERO);
|
||||||
|
|
||||||
// If the image would not be visible, return an empty image
|
// If the image would not be visible, return an empty image
|
||||||
if size.x <= 0. || size.y <= 0. {
|
if size.x <= 0. || size.y <= 0. {
|
||||||
return ImageFrame::empty();
|
return ImageFrame::empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
let offset = (intersection.start - image_bounds.start).max(DVec2::ZERO);
|
|
||||||
|
|
||||||
let scale = footprint.scale();
|
let scale = footprint.scale();
|
||||||
let width = (size.x * scale.x) as u32;
|
let width = (size.x * scale.x) as u32;
|
||||||
let height = (size.y * scale.y) as u32;
|
let height = (size.y * scale.y) as u32;
|
||||||
|
|
|
||||||
|
|
@ -644,7 +644,7 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
||||||
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Footprint, output: TextureFrame, fn_params: [Footprint => TextureFrame]),
|
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Footprint, output: TextureFrame, fn_params: [Footprint => TextureFrame]),
|
||||||
register_node!(graphene_core::structural::ConsNode<_, _>, input: Image<Color>, params: [&str]),
|
register_node!(graphene_core::structural::ConsNode<_, _>, input: Image<Color>, params: [&str]),
|
||||||
register_node!(graphene_std::raster::ImageFrameNode<_, _>, input: Image<Color>, params: [DAffine2]),
|
register_node!(graphene_std::raster::ImageFrameNode<_, _>, input: Image<Color>, params: [DAffine2]),
|
||||||
register_node!(graphene_std::raster::NoisePatternNode<_, _, _, _, _, _, _, _, _, _, _, _, _, _, _>, input: (), params: [UVec2, u32, f64, NoiseType, DomainWarpType, f64, FractalType, u32, f64, f64, f64, f64, CellularDistanceFunction, CellularReturnType, f64]),
|
register_node!(graphene_std::raster::NoisePatternNode<_, _, _, _, _, _, _, _, _, _, _, _, _, _, _>, input: Footprint, params: [bool, u32, f64, NoiseType, DomainWarpType, f64, FractalType, u32, f64, f64, f64, f64, CellularDistanceFunction, CellularReturnType, f64]),
|
||||||
#[cfg(feature = "quantization")]
|
#[cfg(feature = "quantization")]
|
||||||
register_node!(graphene_std::quantization::GenerateQuantizationNode<_, _>, input: ImageFrame<Color>, params: [u32, u32]),
|
register_node!(graphene_std::quantization::GenerateQuantizationNode<_, _>, input: ImageFrame<Color>, params: [u32, u32]),
|
||||||
register_node!(graphene_core::quantization::QuantizeNode<_>, input: Color, params: [QuantizationChannels]),
|
register_node!(graphene_core::quantization::QuantizeNode<_>, input: Color, params: [QuantizationChannels]),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue