lumen_engine/node/processing/
alpha_premultiply.rs1use crate::node::{Deferred, NodeId, NodeParamEvalContext, NodeParams, PortRef};
2
3use crate::gpu::{
4 AlphaMode, BoundFrame, CompiledOutput, FrameBindContext, GpuCompileNode, GpuCompiledNode,
5 RasterHandle, compiler,
6};
7
8pub(crate) const SHADER: &str = include_str!("alpha_premultiply.wgsl");
9
10#[derive(Debug, Clone, lumen_macros::Delegate)]
12pub struct AlphaPremultiplyParams {
13 #[meta(format = "alpha_premultiply_mode")]
15 pub mode: String,
16}
17
18impl Default for AlphaPremultiplyParams {
19 fn default() -> Self {
20 Self {
21 mode: "premultiply".to_string(),
22 }
23 }
24}
25
26#[derive(Debug, Clone, lumen_macros::Node)]
28#[node(
29 kind = "alpha_premultiply",
30 name = "Alpha Premultiply",
31 category = "processing"
32)]
33pub struct AlphaPremultiply {
34 pub id: NodeId,
35 #[params]
36 pub params: AlphaPremultiplyParamsDelegate,
37
38 #[input()]
39 pub source: PortRef,
40}
41
42impl Default for AlphaPremultiply {
43 fn default() -> Self {
44 Self {
45 id: NodeId::new(0),
46 params: AlphaPremultiplyParamsDelegate::default(),
47 source: PortRef::empty(),
48 }
49 }
50}
51
52#[derive(Debug, Clone)]
53struct CompiledAlphaPremultiply {
54 node_id: NodeId,
55 params: AlphaPremultiplyParamsDelegate,
56 buffer: lumen_gpu::BufferId,
57}
58
59impl GpuCompiledNode for CompiledAlphaPremultiply {
60 fn node_id(&self) -> NodeId {
61 self.node_id
62 }
63
64 fn bind(&self, ctx: &FrameBindContext<'_>, bound: &mut BoundFrame) -> crate::Result<()> {
65 let evaluated = self.params.eval(&NodeParamEvalContext {
66 node_id: self.node_id,
67 expr: &ctx.expr_context(self.node_id, "params"),
68 })?;
69 let gpu_params = compiler::AlphaPremultiplyParams {
70 values: [
71 compiler::alpha_operation(self.node_id, &evaluated.mode)?,
72 0.0,
73 0.0,
74 0.0,
75 ],
76 };
77 bound.write_buffer(self.buffer, 0, bytemuck::bytes_of(&gpu_params));
78 Ok(())
79 }
80}
81
82impl GpuCompileNode for AlphaPremultiply {
83 fn compile_gpu(
84 &self,
85 ctx: &mut crate::gpu::CompileContext<'_>,
86 port: &PortRef,
87 ) -> crate::Result<CompiledOutput> {
88 let metadata = match &self.params.mode {
89 Deferred::Value(mode) if compiler::alpha_operation(self.id, mode)? < 0.5 => {
90 Some(AlphaMode::Premultiplied)
91 }
92 Deferred::Value(mode) if compiler::alpha_operation(self.id, mode)? >= 0.5 => {
93 Some(AlphaMode::Unpremultiplied)
94 }
95 _ => None,
96 };
97 let (source, texture, params) = ctx.compile_unary_filter(
98 self.id,
99 &self.source,
100 port,
101 "alpha-premultiply",
102 SHADER,
103 std::mem::size_of::<compiler::AlphaPremultiplyParams>() as u64,
104 )?;
105 ctx.register_compiled_node(CompiledAlphaPremultiply {
106 node_id: self.id,
107 params: self.params.clone(),
108 buffer: params,
109 });
110
111 let mut output_metadata = source.metadata;
112 if let Some(alpha_mode) = metadata {
113 output_metadata.alpha_mode = alpha_mode;
114 }
115 Ok(CompiledOutput::Raster(RasterHandle {
116 texture,
117 domain: source.domain,
118 metadata: output_metadata,
119 }))
120 }
121}