MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
RaymarchProcessor.hpp
Go to the documentation of this file.
1#pragma once
2
5
6namespace MayaFlux::Buffers {
7
8/**
9 * @class RaymarchProcessor
10 * @brief Stages a scalar field and its march parameters onto the buffer a
11 * RenderProcessor draws, so the fragment stage integrates the field
12 * through a proxy volume.
13 *
14 * Dispatches nothing and records no commands. Each cycle it resolves a
15 * vk::Buffer from its field source, writes a DescriptorBindingInfo for it
16 * into the attached buffer's pipeline context, and writes its parameter
17 * block as a staged push constant fragment. RenderProcessor unifies both
18 * into the pipeline it builds and updates the descriptor before binding
19 * the set, which is the designed path for handing resources to the
20 * renderer without a processor of its own.
21 *
22 * The field source is a callable rather than a handle because a
23 * double-buffered field's read slot moves whenever an upstream stage
24 * swaps. Calling it fresh each cycle picks that up. It is also what keeps
25 * this class free of any dependency on VolumeGridBuffer: any callable
26 * returning a valid handle to a float array of the lattice's cell count
27 * works, whatever owns it.
28 *
29 * Set 1 binding 0 by default. Set 0 is the engine's ViewTransform
30 * reservation and cannot be used.
31 */
32class MAYAFLUX_API RaymarchProcessor : public VKBufferProcessor {
33public:
34 /**
35 * @brief Callable resolving the handle to sample this cycle.
36 *
37 * Returning a null handle skips the cycle's staging, leaving the
38 * previous cycle's descriptor in place.
39 */
40 using FieldSource = std::function<vk::Buffer()>;
41
42 /**
43 * @struct MarchParams
44 * @brief Parameter block staged as a push constant fragment.
45 *
46 * Offsets are fixed by this declaration. The fragment is staged at
47 * offset zero, so these are absolute offsets in the render pipeline's
48 * push constant range.
49 */
50 struct MarchParams {
51 uint32_t width;
52 uint32_t height;
53 uint32_t depth;
54 uint32_t max_steps;
63 float cool_r;
64 float cool_g;
65 float cool_b;
67 float hot_r;
68 float hot_g;
69 float hot_b;
70 float emission;
71 float threshold;
72 float pad0;
73 float pad1;
74 float pad2;
75 };
76
77 static_assert(sizeof(MarchParams) == 96);
78 static_assert(sizeof(MarchParams) % 16 == 0);
79
80 /**
81 * @struct MarchConfig
82 * @brief Every march setting in one aggregate, for configure().
83 *
84 * Fields left out keep the processor's own defaults. A max_steps of zero
85 * means enough steps to cross the lattice diagonal at the step scale,
86 * capped at 512, and it follows later changes to the step scale.
87 */
88 struct MarchConfig {
89 uint32_t max_steps { 0 };
90 float step_scale { 0.5F };
91 float density_scale { 1.0F };
92 float absorption { 12.0F };
93 float emission { 2.2F };
94 glm::vec3 cool { 0.35F, 0.10F, 0.05F };
95 glm::vec3 hot { 1.0F, 0.82F, 0.45F };
96 float threshold { 0.02F };
97 };
98
99 /**
100 * @brief Construct a march staging processor.
101 * @param source Callable resolving the field handle each cycle.
102 * @param field_bytes Byte size of one slot of that field.
103 * @param lattice Discretization the field is stored over. Must match
104 * the lattice the field was allocated against.
105 * @param set Descriptor set index. Must not be zero.
106 * @param binding Binding index within that set.
107 */
109 FieldSource source,
110 size_t field_bytes,
111 Kinesis::Lattice3D lattice,
112 uint32_t set = 1,
113 uint32_t binding = 0);
114
115 ~RaymarchProcessor() override = default;
116
117 /**
118 * @brief Set the sample count along the longest ray through the volume.
119 * @param steps Step count. Higher resolves thin structure, linearly
120 * more expensive per covered pixel.
121 */
122 void set_max_steps(uint32_t steps);
123
124 /**
125 * @brief Set the step length as a fraction of one cell.
126 * @param scale Below one oversamples, above one undersamples and bands.
127 */
128 void set_step_scale(float scale);
129
130 /**
131 * @brief Set the multiplier applied to every sample before integration.
132 * @param scale Raises or lowers apparent opacity without touching the field.
133 */
134 void set_density_scale(float scale);
135
136 /**
137 * @brief Set the extinction coefficient.
138 * @param absorption Higher makes the volume opaque in a shorter distance.
139 */
140 void set_absorption(float absorption);
141
142 /**
143 * @brief Set the emission colours interpolated by sample value.
144 * @param cool Colour at the threshold.
145 * @param hot Colour at and above unity.
146 */
147 void set_emission_ramp(const glm::vec3& cool, const glm::vec3& hot);
148
149 /**
150 * @brief Set the emissive strength.
151 * @param emission Zero gives pure absorption, a density shadow.
152 */
153 void set_emission(float emission);
154
155 /**
156 * @brief Set the sample value below which a step contributes nothing.
157 * @param threshold Cutoff. Suppresses the smeared tail advection leaves.
158 */
159 void set_threshold(float threshold);
160
161 /**
162 * @brief Replace every march setting at once.
163 * @param config Settings. Unnamed fields take their defaults, not the current values.
164 */
165 void configure(const MarchConfig& config);
166
167 /** @brief The lattice the sampled field is stored over. */
168 [[nodiscard]] const Kinesis::Lattice3D& get_lattice() const { return m_lattice; }
169
170 /** @brief The staged parameter block. */
171 [[nodiscard]] const MarchParams& get_params() const { return m_params; }
172
173 void on_attach(const std::shared_ptr<Buffer>& buffer) override;
174 void processing_function(const std::shared_ptr<Buffer>& buffer) override;
175
176private:
177 /**
178 * @brief Write the lattice-derived words of the parameter block.
179 */
180 void write_lattice_params();
181
182 /**
183 * @brief Steps needed to cross the lattice diagonal at the current step scale, capped at 512.
184 */
185 [[nodiscard]] uint32_t auto_steps() const;
186
187 /**
188 * @brief Insert or replace the descriptor entry for the field handle.
189 * @param buffer Buffer whose pipeline context is staged onto.
190 * @param handle Handle resolved this cycle.
191 */
192 void stage_descriptor(const std::shared_ptr<VKBuffer>& buffer, vk::Buffer handle);
193
194 /**
195 * @brief Insert or replace the push constant fragment.
196 * @param buffer Buffer whose pipeline context is staged onto.
197 */
198 void stage_params(const std::shared_ptr<VKBuffer>& buffer);
199
203 uint32_t m_set;
204 uint32_t m_binding;
205
206 MarchParams m_params {};
207 bool m_auto_steps { false };
208};
209
210} // namespace MayaFlux::Buffers
std::shared_ptr< NetworkGeometryBuffer > buffer
float threshold
const MarchParams & get_params() const
The staged parameter block.
std::function< vk::Buffer()> FieldSource
Callable resolving the handle to sample this cycle.
const Kinesis::Lattice3D & get_lattice() const
The lattice the sampled field is stored over.
Stages a scalar field and its march parameters onto the buffer a RenderProcessor draws,...
Every march setting in one aggregate, for configure().
Parameter block staged as a push constant fragment.
A regular subdivision of an AABB3D into a cell count per axis.
Definition Lattice.hpp:25