lumen_engine/node/processing/
exposure.rs1use crate::node::{NodeId, NodeParamEvalContext, NodeParams, PortRef};
2
3use crate::gpu::{
4 BoundFrame, CompiledOutput, FrameBindContext, GpuCompileNode, GpuCompiledNode, RasterHandle,
5 compiler,
6};
7
8pub(crate) const SHADER: &str = include_str!("exposure.wgsl");
9
10#[derive(Debug, Clone, lumen_macros::Delegate)]
11pub struct ExposureParams {
12 #[meta(step = 0.01)]
14 pub exposure: f64,
15 #[meta(min = 0, step = 0.01)]
17 pub contrast: f64,
18 #[meta(step = 0.01)]
20 pub offset: f64,
21}
22
23impl Default for ExposureParams {
24 fn default() -> Self {
25 Self {
26 exposure: 0.0,
27 contrast: 1.0,
28 offset: 0.0,
29 }
30 }
31}
32
33#[derive(Debug, Clone, lumen_macros::Node)]
35#[node(kind = "exposure", name = "Exposure", category = "processing")]
36pub struct Exposure {
37 pub id: NodeId,
38 #[params]
39 pub params: ExposureParamsDelegate,
40 #[input()]
41 pub source: PortRef,
42}
43
44impl Default for Exposure {
45 fn default() -> Self {
46 Self {
47 id: NodeId::new(0),
48 params: ExposureParamsDelegate::default(),
49 source: PortRef::empty(),
50 }
51 }
52}
53
54#[derive(Debug, Clone)]
55struct CompiledExposure {
56 node_id: NodeId,
57 params: ExposureParamsDelegate,
58 buffer: lumen_gpu::BufferId,
59}
60
61impl GpuCompiledNode for CompiledExposure {
62 fn node_id(&self) -> NodeId {
63 self.node_id
64 }
65
66 fn bind(&self, ctx: &FrameBindContext<'_>, bound: &mut BoundFrame) -> crate::Result<()> {
67 let params = self.params.eval(&NodeParamEvalContext {
68 node_id: self.node_id,
69 expr: &ctx.expr_context(self.node_id, "params"),
70 })?;
71 let params = compiler::ExposureParams {
72 exposure: params.exposure as f32,
73 contrast: params.contrast as f32,
74 offset: params.offset as f32,
75 _pad: 0.0,
76 };
77 bound.write_buffer(self.buffer, 0, bytemuck::bytes_of(¶ms));
78 Ok(())
79 }
80}
81
82impl GpuCompileNode for Exposure {
83 fn compile_gpu(
84 &self,
85 ctx: &mut crate::gpu::CompileContext<'_>,
86 port: &PortRef,
87 ) -> crate::Result<CompiledOutput> {
88 let (source, texture, params) = ctx.compile_unary_filter(
89 self.id,
90 &self.source,
91 port,
92 "exposure",
93 SHADER,
94 std::mem::size_of::<compiler::ExposureParams>() as u64,
95 )?;
96 ctx.register_compiled_node(CompiledExposure {
97 node_id: self.id,
98 params: self.params.clone(),
99 buffer: params,
100 });
101 Ok(CompiledOutput::Raster(RasterHandle {
102 texture,
103 domain: source.domain,
104 metadata: source.metadata,
105 }))
106 }
107}