mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-19 10:58:04 +08:00
Add the Pixel Preview render mode (#3881)
* Add pixel preview render mode * Fix fmt * Remove unused sampler * Remove unnecessary mutex * Code review --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
pub mod any;
|
||||
pub mod pixel_preview;
|
||||
pub mod render_cache;
|
||||
pub mod render_node;
|
||||
pub mod text;
|
||||
|
||||
71
node-graph/nodes/gstd/src/pixel_preview.rs
Normal file
71
node-graph/nodes/gstd/src/pixel_preview.rs
Normal file
@@ -0,0 +1,71 @@
|
||||
use crate::render_node::RenderOutputType;
|
||||
use core_types::transform::{Footprint, Transform};
|
||||
use core_types::{CloneVarArgs, Context, Ctx, ExtractAll, OwnedContextImpl};
|
||||
use glam::{DAffine2, DVec2, UVec2};
|
||||
use graph_craft::document::value::RenderOutput;
|
||||
use graph_craft::wasm_application_io::WasmEditorApi;
|
||||
use graphene_application_io::{ApplicationIo, ImageTexture};
|
||||
use rendering::{RenderOutputType as RenderOutputTypeRequest, RenderParams};
|
||||
use vector_types::vector::style::RenderMode;
|
||||
|
||||
#[node_macro::node(category(""))]
|
||||
pub async fn pixel_preview<'a: 'n>(
|
||||
ctx: impl Ctx + ExtractAll + CloneVarArgs + Sync,
|
||||
editor_api: &'a WasmEditorApi,
|
||||
data: impl Node<Context<'static>, Output = RenderOutput> + Send + Sync,
|
||||
) -> RenderOutput {
|
||||
let Some(render_params) = ctx.vararg(0).ok().and_then(|v| v.downcast_ref::<RenderParams>()).cloned() else {
|
||||
log::error!("invalid render params for pixel preview");
|
||||
let context = OwnedContextImpl::from(ctx).into_context();
|
||||
return data.eval(context).await;
|
||||
};
|
||||
let physical_scale = render_params.scale;
|
||||
|
||||
let footprint = *ctx.footprint();
|
||||
let viewport_zoom = footprint.decompose_scale().x;
|
||||
|
||||
if render_params.render_mode != RenderMode::PixelPreview || !matches!(render_params.render_output_type, RenderOutputTypeRequest::Vello) || viewport_zoom <= 1. {
|
||||
let context = OwnedContextImpl::from(ctx).into_context();
|
||||
return data.eval(context).await;
|
||||
}
|
||||
|
||||
let physical_resolution = footprint.resolution;
|
||||
let logical_resolution = physical_resolution.as_dvec2() / physical_scale;
|
||||
|
||||
let logical_footprint = Footprint {
|
||||
resolution: logical_resolution.as_uvec2().max(UVec2::ONE),
|
||||
..footprint
|
||||
};
|
||||
|
||||
let bounds = logical_footprint.viewport_bounds_in_local_space();
|
||||
|
||||
let upstream_min = bounds.start.floor();
|
||||
let upstream_max = bounds.end.ceil();
|
||||
|
||||
let upstream_size = (upstream_max - upstream_min).max(DVec2::ONE);
|
||||
let upstream_resolution = upstream_size.as_uvec2().max(UVec2::ONE);
|
||||
|
||||
let upstream_footprint = Footprint {
|
||||
transform: DAffine2::from_scale(DVec2::splat(1.0 / physical_scale)) * DAffine2::from_translation(-upstream_min),
|
||||
resolution: upstream_resolution,
|
||||
quality: footprint.quality,
|
||||
};
|
||||
|
||||
let new_ctx = OwnedContextImpl::from(ctx).with_footprint(upstream_footprint).with_vararg(Box::new(render_params)).into_context();
|
||||
let mut result = data.eval(new_ctx).await;
|
||||
|
||||
let RenderOutputType::Texture(ref source_texture) = result.data else { return result };
|
||||
|
||||
let transform = DAffine2::from_translation(-upstream_min) * footprint.transform.inverse() * DAffine2::from_scale(logical_resolution);
|
||||
|
||||
let exec = editor_api.application_io.as_ref().unwrap().gpu_executor().unwrap();
|
||||
let resampled = exec.resample_texture(&source_texture.texture, physical_resolution, &transform);
|
||||
|
||||
result.data = RenderOutputType::Texture(ImageTexture { texture: resampled });
|
||||
|
||||
result
|
||||
.metadata
|
||||
.apply_transform(footprint.transform * DAffine2::from_translation(upstream_min) * DAffine2::from_scale(DVec2::splat(physical_scale)));
|
||||
|
||||
result
|
||||
}
|
||||
@@ -184,8 +184,7 @@ async fn render<'a: 'n>(ctx: impl Ctx + ExtractFootprint + ExtractVarArgs, edito
|
||||
// We now replace all transforms which are supposed to be infinite with a transform which covers the entire viewport
|
||||
// See <https://xi.zulipchat.com/#narrow/channel/197075-vello/topic/Full.20screen.20color.2Fgradients/near/538435044> for more detail
|
||||
let scaled_infinite_transform = vello::kurbo::Affine::scale_non_uniform(physical_resolution.x as f64, physical_resolution.y as f64);
|
||||
let encoding = scene.encoding_mut();
|
||||
for transform in encoding.transforms.iter_mut() {
|
||||
for transform in scene.encoding_mut().transforms.iter_mut() {
|
||||
if transform.matrix[0] == f32::INFINITY {
|
||||
*transform = vello_encoding::Transform::from_kurbo(&scaled_infinite_transform);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user