lumen_engine/node/processing/
alpha_premultiply.rs1use crate::node::{NodeId, NodeProperty, PortRef};
2
3use crate::gpu::{
4 AlphaMode, BoundFrame, CompiledOutput, FrameBindContext, FrameBinding, GpuCompileNode,
5 GpuFrameBindNode, RasterHandle, compiler,
6};
7
8pub(crate) const SHADER: &str = include_str!("alpha_premultiply.wgsl");
9
10#[derive(Debug, Clone, lumen_macros::Node)]
12#[node(
13 kind = "alpha_premultiply",
14 name = "Alpha Premultiply",
15 category = "processing"
16)]
17pub struct AlphaPremultiply {
18 pub id: NodeId,
19 #[property(kind = "string", format = "alpha_premultiply_mode")]
21 pub mode: NodeProperty,
22 #[input()]
23 pub source: PortRef,
24}
25
26impl Default for AlphaPremultiply {
27 fn default() -> Self {
28 Self {
29 id: NodeId::new(0),
30 mode: NodeProperty::String("premultiply".to_string()),
31 source: PortRef::empty(),
32 }
33 }
34}
35
36impl GpuCompileNode for AlphaPremultiply {
37 fn compile_gpu(
38 &self,
39 ctx: &mut crate::gpu::CompileContext<'_>,
40 port: &PortRef,
41 ) -> crate::Result<CompiledOutput> {
42 let metadata = match &self.mode {
43 NodeProperty::String(mode) if compiler::alpha_operation(self.id, mode)? < 0.5 => {
44 Some(AlphaMode::Premultiplied)
45 }
46 NodeProperty::String(mode) if compiler::alpha_operation(self.id, mode)? >= 0.5 => {
47 Some(AlphaMode::Unpremultiplied)
48 }
49 _ => None,
50 };
51 let (source, texture, params) = ctx.compile_unary_filter(
52 self.id,
53 &self.source,
54 port,
55 "alpha-premultiply",
56 SHADER,
57 std::mem::size_of::<compiler::AlphaPremultiplyParams>() as u64,
58 )?;
59 ctx.push_frame_binding(FrameBinding::AlphaPremultiply {
60 node_id: self.id,
61 mode: self.mode.clone(),
62 buffer: params,
63 });
64
65 let mut output_metadata = source.metadata;
66 if let Some(alpha_mode) = metadata {
67 output_metadata.alpha_mode = alpha_mode;
68 }
69 Ok(CompiledOutput::Raster(RasterHandle {
70 texture,
71 domain: source.domain,
72 metadata: output_metadata,
73 }))
74 }
75}
76
77impl GpuFrameBindNode for AlphaPremultiply {
78 fn bind_gpu_frame(
79 &self,
80 ctx: &FrameBindContext<'_>,
81 binding: &FrameBinding,
82 bound: &mut BoundFrame,
83 ) -> crate::Result<()> {
84 let FrameBinding::AlphaPremultiply {
85 node_id,
86 mode,
87 buffer,
88 } = binding
89 else {
90 return Ok(());
91 };
92 let mode = mode.resolve_string(*node_id, "mode", &ctx.expr_context(*node_id, "mode"))?;
93 let params = compiler::AlphaPremultiplyParams {
94 values: [compiler::alpha_operation(*node_id, &mode)?, 0.0, 0.0, 0.0],
95 };
96 bound.write_buffer(*buffer, 0, bytemuck::bytes_of(¶ms));
97 Ok(())
98 }
99}