MayaFlux 0.5.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
62void RaymarchProcessor::set_max_steps(uint32_t steps) { m_params.max_steps = steps; }
65void RaymarchProcessor::set_absorption(float absorption) { m_params.absorption = absorption; }
66void RaymarchProcessor::set_emission(float emission) { m_params.emission = emission; }
68
69void RaymarchProcessor::set_emission_ramp(const glm::vec3& cool, const glm::vec3& hot)
70{
71 m_params.cool_r = cool.r;
72 m_params.cool_g = cool.g;
73 m_params.cool_b = cool.b;
74 m_params.hot_r = hot.r;
75 m_params.hot_g = hot.g;
76 m_params.hot_b = hot.b;
77}
78
79void RaymarchProcessor::on_attach(const std::shared_ptr<Buffer>& buffer)
80{
81 auto vk_buffer = std::dynamic_pointer_cast<VKBuffer>(buffer);
82 if (!vk_buffer) {
84 "RaymarchProcessor requires a VKBuffer");
85 return;
86 }
87
88 stage_params(vk_buffer);
89
90 if (m_source) {
91 stage_descriptor(vk_buffer, m_source());
92 }
93}
94
95void RaymarchProcessor::processing_function(const std::shared_ptr<Buffer>& buffer)
96{
97 auto vk_buffer = std::dynamic_pointer_cast<VKBuffer>(buffer);
98 if (!vk_buffer || !m_source) {
99 return;
100 }
101
102 const vk::Buffer handle = m_source();
103 if (!handle) {
104 return;
105 }
106
107 stage_descriptor(vk_buffer, handle);
108 stage_params(vk_buffer);
109}
110
112 const std::shared_ptr<VKBuffer>& buffer, vk::Buffer handle)
113{
114 auto& bindings = buffer->get_pipeline_context().descriptor_buffer_bindings;
115
116 auto it = std::ranges::find_if(bindings, [this](const auto& entry) {
117 return entry.set == m_set && entry.binding == m_binding;
118 });
119
120 if (it == bindings.end()) {
121 bindings.push_back(Portal::Graphics::DescriptorBindingInfo {
122 .set = m_set,
123 .binding = m_binding,
124 .type = vk::DescriptorType::eStorageBuffer,
125 .buffer_info = vk::DescriptorBufferInfo(handle, 0, m_field_bytes),
126 .name = k_binding_name,
127 .count = 1,
128 });
129 return;
130 }
131
132 it->buffer_info.buffer = handle;
133 it->buffer_info.offset = 0;
134 it->buffer_info.range = m_field_bytes;
135}
136
137void RaymarchProcessor::stage_params(const std::shared_ptr<VKBuffer>& buffer)
138{
139 auto& fragments = buffer->get_pipeline_context().push_constant_bindings;
140
141 const auto* bytes = reinterpret_cast<const uint8_t*>(&m_params);
142
143 auto it = std::ranges::find_if(fragments, [](const auto& entry) {
144 return entry.name == k_fragment_name;
145 });
146
147 if (it == fragments.end()) {
149 .offset = 0,
150 .data = std::vector<uint8_t>(bytes, bytes + sizeof(MarchParams)),
151 .name = k_fragment_name,
152 });
153 return;
154 }
155
156 it->offset = 0;
157 it->data.assign(bytes, bytes + sizeof(MarchParams));
158}
159
160} // namespace MayaFlux::Buffers
#define MF_ERROR(comp, ctx,...)
float scale
float threshold
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.
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.