MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
RaymarchProcessor.cpp
Go to the documentation of this file.
2
4
5namespace MayaFlux::Buffers {
6
7namespace {
8 constexpr const char* k_binding_name = "volume_field";
9 constexpr const char* k_fragment_name = "march_params";
10}
11
13 FieldSource source,
14 size_t field_bytes,
15 Kinesis::Lattice3D lattice,
16 uint32_t set,
17 uint32_t binding)
18 : m_source(std::move(source))
19 , m_field_bytes(field_bytes)
20 , m_lattice(lattice)
21 , m_set(set)
22 , m_binding(binding)
23{
24 if (m_set == 0) {
26 "RaymarchProcessor: set 0 is the ViewTransform reservation, "
27 "falling back to set 1");
28 m_set = 1;
29 }
30
31 m_params.max_steps = 128;
32 m_params.step_scale = 0.5F;
34 m_params.absorption = 12.0F;
35 m_params.cool_r = 0.35F;
36 m_params.cool_g = 0.10F;
37 m_params.cool_b = 0.05F;
38 m_params.hot_r = 1.0F;
39 m_params.hot_g = 0.82F;
40 m_params.hot_b = 0.45F;
41 m_params.emission = 2.2F;
42 m_params.threshold = 0.02F;
43
45}
46
61
63{
64 constexpr uint32_t k_cap = 512;
65
66 const glm::vec3 cell = m_lattice.cell_size();
67 const float step = std::min({ cell.x, cell.y, cell.z }) * std::max(m_params.step_scale, 1e-3F);
68 const float span = glm::length(m_lattice.bounds.max - m_lattice.bounds.min);
69
70 return std::min(k_cap, static_cast<uint32_t>(std::ceil(span / step)) + 1U);
71}
72
74{
75 m_params.max_steps = steps;
76 m_auto_steps = false;
77}
78
80{
81 m_params.step_scale = scale;
82 if (m_auto_steps) {
84 }
85}
86
99
101void RaymarchProcessor::set_absorption(float absorption) { m_params.absorption = absorption; }
102void RaymarchProcessor::set_emission(float emission) { m_params.emission = emission; }
104
105void RaymarchProcessor::set_emission_ramp(const glm::vec3& cool, const glm::vec3& hot)
106{
107 m_params.cool_r = cool.r;
108 m_params.cool_g = cool.g;
109 m_params.cool_b = cool.b;
110 m_params.hot_r = hot.r;
111 m_params.hot_g = hot.g;
112 m_params.hot_b = hot.b;
113}
114
115void RaymarchProcessor::on_attach(const std::shared_ptr<Buffer>& buffer)
116{
117 auto vk_buffer = std::dynamic_pointer_cast<VKBuffer>(buffer);
118 if (!vk_buffer) {
120 "RaymarchProcessor requires a VKBuffer");
121 return;
122 }
123
124 stage_params(vk_buffer);
125
126 if (m_source) {
127 stage_descriptor(vk_buffer, m_source());
128 }
129}
130
131void RaymarchProcessor::processing_function(const std::shared_ptr<Buffer>& buffer)
132{
133 auto vk_buffer = std::dynamic_pointer_cast<VKBuffer>(buffer);
134 if (!vk_buffer || !m_source) {
135 return;
136 }
137
138 const vk::Buffer handle = m_source();
139 if (!handle) {
140 return;
141 }
142
143 stage_descriptor(vk_buffer, handle);
144 stage_params(vk_buffer);
145}
146
148 const std::shared_ptr<VKBuffer>& buffer, vk::Buffer handle)
149{
150 auto& bindings = buffer->get_pipeline_context().descriptor_buffer_bindings;
151
152 auto it = std::ranges::find_if(bindings, [this](const auto& entry) {
153 return entry.set == m_set && entry.binding == m_binding;
154 });
155
156 if (it == bindings.end()) {
157 bindings.push_back(Portal::Graphics::DescriptorBindingInfo {
158 .set = m_set,
159 .binding = m_binding,
160 .type = vk::DescriptorType::eStorageBuffer,
161 .buffer_info = vk::DescriptorBufferInfo(handle, 0, m_field_bytes),
162 .name = k_binding_name,
163 .count = 1,
164 });
165 return;
166 }
167
168 it->buffer_info.buffer = handle;
169 it->buffer_info.offset = 0;
170 it->buffer_info.range = m_field_bytes;
171}
172
173void RaymarchProcessor::stage_params(const std::shared_ptr<VKBuffer>& buffer)
174{
175 auto& fragments = buffer->get_pipeline_context().push_constant_bindings;
176
177 const auto* bytes = reinterpret_cast<const uint8_t*>(&m_params);
178
179 auto it = std::ranges::find_if(fragments, [](const auto& entry) {
180 return entry.name == k_fragment_name;
181 });
182
183 if (it == fragments.end()) {
185 .offset = 0,
186 .data = std::vector<uint8_t>(bytes, bytes + sizeof(MarchParams)),
187 .name = k_fragment_name,
188 });
189 return;
190 }
191
192 it->offset = 0;
193 it->data.assign(bytes, bytes + sizeof(MarchParams));
194}
195
196} // namespace MayaFlux::Buffers
#define MF_ERROR(comp, ctx,...)
std::shared_ptr< NetworkGeometryBuffer > buffer
float threshold
void configure(const MarchConfig &config)
Replace every march setting at once.
uint32_t auto_steps() const
Steps needed to cross the lattice diagonal at the current step scale, capped at 512.
void set_emission_ramp(const glm::vec3 &cool, const glm::vec3 &hot)
Set the emission colours interpolated by sample value.
void set_step_scale(float scale)
Set the step length as a fraction of one cell.
void set_density_scale(float scale)
Set the multiplier applied to every sample before integration.
void set_threshold(float threshold)
Set the sample value below which a step contributes nothing.
std::function< vk::Buffer()> FieldSource
Callable resolving the handle to sample this cycle.
void processing_function(const std::shared_ptr< Buffer > &buffer) override
The core processing function that must be implemented by derived classes.
void on_attach(const std::shared_ptr< Buffer > &buffer) override
Called when this processor is attached to a buffer.
void set_emission(float emission)
Set the emissive strength.
void set_absorption(float absorption)
Set the extinction coefficient.
void stage_params(const std::shared_ptr< VKBuffer > &buffer)
Insert or replace the push constant fragment.
void stage_descriptor(const std::shared_ptr< VKBuffer > &buffer, vk::Buffer handle)
Insert or replace the descriptor entry for the field handle.
RaymarchProcessor(FieldSource source, size_t field_bytes, Kinesis::Lattice3D lattice, uint32_t set=1, uint32_t binding=0)
Construct a march staging processor.
void set_max_steps(uint32_t steps)
Set the sample count along the longest ray through the volume.
void write_lattice_params()
Write the lattice-derived words of the parameter block.
@ BufferProcessing
Buffer processing (Buffers::BufferManager, processing chains)
@ Init
Engine/subsystem initialization.
@ Buffers
Buffers, Managers, processors and processing chains.
Every march setting in one aggregate, for configure().
Parameter block staged as a push constant fragment.
glm::vec3 cell_size() const noexcept
Edge length of one cell along each axis.
Definition Lattice.hpp:30
AABB3D bounds
Continuous extent subdivided.
Definition Lattice.hpp:27
glm::uvec3 resolution
Cell count per axis. Zero on any axis is invalid.
Definition Lattice.hpp:26
A regular subdivision of an AABB3D into a cell count per axis.
Definition Lattice.hpp:25
Self-describing push constant fragment staged on a VKBuffer.