34 m_downsample_samplers.resize(16);
35 m_filter_samplers.resize(16);
36 for (std::size_t i = 0; i < m_downsample_samplers.size(); ++i)
38 m_downsample_samplers[i] = std::make_shared<gl::sampler>
50 static_cast<float>(i),
54 m_filter_samplers[i] = std::make_shared<gl::sampler>
66 static_cast<float>(i),
72 m_vertex_array = std::make_unique<gl::vertex_array>();
76 rebuild_cubemap_to_sh_shader_program();
80 rebuild_cubemap_downsample_shader_program();
84 rebuild_cubemap_filter_lut_shader_program();
87 m_cubemap_filter_lut_texture = std::make_shared<gl::texture_2d>
89 std::make_shared<gl::image_view_2d>
91 std::make_shared<gl::image_2d>
94 static_cast<std::uint32_t
>(m_cubemap_filter_sample_count),
95 static_cast<std::uint32_t
>(m_cubemap_filter_mip_count - 1)
98 std::make_shared<gl::sampler>
112 m_cubemap_filter_lut_texture->get_image_view(),
115 m_cubemap_filter_lut_framebuffer = std::make_unique<gl::framebuffer>(attachments, m_cubemap_filter_lut_texture->get_image_view()->get_image()->get_dimensions()[0], m_cubemap_filter_lut_texture->get_image_view()->get_image()->get_dimensions()[1]);
118 rebuild_cubemap_filter_lut_texture();
122 rebuild_cubemap_filter_shader_program();
128 if (light_probes.empty())
133 update_light_probes_luminance(light_probes);
134 update_light_probes_illuminance(light_probes);
137 void light_probe_stage::update_light_probes_luminance(
const std::vector<scene::object_base*>& light_probes)
139 bool state_bound =
false;
145 std::begin(light_probes),
146 std::end(light_probes),
171 const auto base_mip_face_size = light_probe.
get_luminance_texture()->get_image_view()->get_image()->get_dimensions()[0];
177 const auto current_mip_face_size = base_mip_face_size >> i;
182 static_cast<float>(current_mip_face_size),
183 static_cast<float>(current_mip_face_size)
197 m_pipeline->
draw(1, 1, 0, 0);
204 m_cubemap_filter_filter_lut_var->
update(*m_cubemap_filter_lut_texture);
210 m_cubemap_filter_mip_level_var->
update(
static_cast<int>(i));
213 const auto current_mip_face_size = base_mip_face_size >>
i;
218 static_cast<float>(current_mip_face_size),
219 static_cast<float>(current_mip_face_size)
233 m_pipeline->
draw(1, 1, 0, 0);
245 void light_probe_stage::update_light_probes_illuminance(
const std::vector<scene::object_base*>& light_probes)
247 bool state_bound =
false;
253 std::begin(light_probes),
254 std::end(light_probes),
290 m_pipeline->
draw(3, 1, 0, 0);
297 m_reproject_sh =
false;
300 void light_probe_stage::set_sh_sample_count(std::size_t
count)
302 if (m_sh_sample_count !=
count)
304 m_sh_sample_count =
count;
305 sh_parameters_changed();
309 void light_probe_stage::set_cubemap_filter_sample_count(std::size_t
count)
311 if (m_cubemap_filter_sample_count !=
count)
313 m_cubemap_filter_sample_count =
count;
314 cubemap_filter_parameters_changed();
318 void light_probe_stage::set_cubemap_filter_mip_bias(
float bias)
320 if (m_cubemap_filter_mip_bias != bias)
322 m_cubemap_filter_mip_bias = bias;
323 cubemap_filter_parameters_changed();
327 void light_probe_stage::rebuild_cubemap_to_sh_shader_program()
329 m_cubemap_to_sh_shader_program = m_cubemap_to_sh_shader_template->build({{
"SAMPLE_COUNT", std::to_string(m_sh_sample_count)}});
330 if (!m_cubemap_to_sh_shader_program->linked())
332 debug::log_error(
"Failed to build cubemap to spherical harmonics shader program: {}", m_cubemap_to_sh_shader_program->info());
334 m_cubemap_to_sh_cubemap_var =
nullptr;
336 throw std::runtime_error(
"Failed to build cubemap to spherical harmonics shader program.");
340 m_cubemap_to_sh_cubemap_var = m_cubemap_to_sh_shader_program->variable(
"cubemap");
341 if (!m_cubemap_to_sh_cubemap_var)
343 throw std::runtime_error(
"Cubemap to spherical harmonics shader program has no `cubemap` variable.");
348 void light_probe_stage::rebuild_cubemap_downsample_shader_program()
350 m_cubemap_downsample_shader_program = m_cubemap_downsample_shader_template->build({});
351 if (!m_cubemap_downsample_shader_program->linked())
353 debug::log_error(
"Failed to build cubemap downsample shader program: {}", m_cubemap_downsample_shader_program->info());
355 m_cubemap_downsample_cubemap_var =
nullptr;
357 throw std::runtime_error(
"Failed to build cubemap downsample shader program.");
361 m_cubemap_downsample_cubemap_var = m_cubemap_downsample_shader_program->variable(
"cubemap");
362 if (!m_cubemap_downsample_cubemap_var)
364 throw std::runtime_error(
"Cubemap downsample shader program has no `cubemap` variable.");
369 void light_probe_stage::rebuild_cubemap_filter_lut_shader_program()
371 m_cubemap_filter_lut_shader_program = m_cubemap_filter_lut_shader_template->build({});
372 if (!m_cubemap_filter_lut_shader_program->linked())
374 debug::log_error(
"Failed to build cubemap filter LUT shader program: {}", m_cubemap_filter_lut_shader_program->info());
376 m_cubemap_filter_lut_resolution_var =
nullptr;
377 m_cubemap_filter_lut_face_size_var =
nullptr;
378 m_cubemap_filter_lut_mip_bias_var =
nullptr;
380 throw std::runtime_error(
"Failed to build cubemap filter LUT shader program.");
384 m_cubemap_filter_lut_resolution_var = m_cubemap_filter_lut_shader_program->variable(
"resolution");
385 m_cubemap_filter_lut_face_size_var = m_cubemap_filter_lut_shader_program->variable(
"face_size");
386 m_cubemap_filter_lut_mip_bias_var = m_cubemap_filter_lut_shader_program->variable(
"mip_bias");
387 if (!m_cubemap_filter_lut_resolution_var || !m_cubemap_filter_lut_face_size_var || !m_cubemap_filter_lut_mip_bias_var)
389 throw std::runtime_error(
"Cubemap filter LUT shader program is missing one or more required shader variables.");
394 void light_probe_stage::rebuild_cubemap_filter_lut_texture()
396 m_pipeline->set_color_blend_enabled(
false);
397 m_pipeline->bind_framebuffer(m_cubemap_filter_lut_framebuffer.get());
399 const auto& cubemap_filter_lut_dimensions = m_cubemap_filter_lut_texture->get_image_view()->get_image()->get_dimensions();
404 static_cast<float>(cubemap_filter_lut_dimensions[0]),
405 static_cast<float>(cubemap_filter_lut_dimensions[1])
407 m_pipeline->set_viewport(0, viewport);
409 m_pipeline->bind_shader_program(m_cubemap_filter_lut_shader_program.get());
410 m_cubemap_filter_lut_resolution_var->update(
math::fvec2{
static_cast<float>(cubemap_filter_lut_dimensions[0]),
static_cast<float>(cubemap_filter_lut_dimensions[1])});
411 m_cubemap_filter_lut_face_size_var->update(128.0f);
412 m_cubemap_filter_lut_mip_bias_var->update(m_cubemap_filter_mip_bias);
413 m_cubemap_filter_lut_framebuffer->resize(cubemap_filter_lut_dimensions[0], cubemap_filter_lut_dimensions[1]);
415 m_pipeline->bind_vertex_array(m_vertex_array.get());
417 m_pipeline->draw(3, 1, 0, 0);
420 void light_probe_stage::rebuild_cubemap_filter_shader_program()
422 m_cubemap_filter_shader_program = m_cubemap_filter_shader_template->build({{
"SAMPLE_COUNT", std::to_string(m_cubemap_filter_sample_count)}});
423 if (!m_cubemap_filter_shader_program->linked())
425 debug::log_error(
"Failed to build cubemap filter shader program: {}", m_cubemap_filter_shader_program->info());
427 m_cubemap_filter_cubemap_var =
nullptr;
428 m_cubemap_filter_filter_lut_var =
nullptr;
429 m_cubemap_filter_mip_level_var =
nullptr;
431 throw std::runtime_error(
"Failed to build cubemap filter shader program.");
435 m_cubemap_filter_cubemap_var = m_cubemap_filter_shader_program->variable(
"cubemap");
436 m_cubemap_filter_filter_lut_var = m_cubemap_filter_shader_program->variable(
"filter_lut");
437 m_cubemap_filter_mip_level_var = m_cubemap_filter_shader_program->variable(
"mip_level");
439 if (!m_cubemap_filter_cubemap_var || !m_cubemap_filter_filter_lut_var || !m_cubemap_filter_mip_level_var)
441 throw std::runtime_error(
"Cubemap filter shader program is missing one or more required shader variables.");
446 void light_probe_stage::sh_parameters_changed()
448 rebuild_cubemap_to_sh_shader_program();
449 m_reproject_sh =
true;
452 void light_probe_stage::cubemap_filter_parameters_changed()
454 m_refilter_cubemaps =
true;
Graphics pipeline interface.
void set_primitive_topology(primitive_topology topology)
Sets the primitive topology to use for drawing.
void bind_shader_program(const gl::shader_program *shader_program)
Sets the vertex input.
void bind_framebuffer(const gl::framebuffer *framebuffer)
Sets the vertex input.
void set_color_blend_enabled(bool enabled)
Controls whether blending is enabled for the corresponding color attachment.
void set_viewport(std::uint32_t first_viewport, std::span< const viewport > viewports)
Sets one or more viewports.
void draw(std::uint32_t vertex_count, std::uint32_t instance_count, std::uint32_t first_vertex, std::uint32_t first_instance)
Draws primitives.
void bind_vertex_array(const vertex_array *array)
Binds a vertex array.
Template used to for generating one or more shader variants from a single source.
virtual void update(bool value) const
Updates the value of the variable.
void execute(render::context &ctx) override
Executes the render stage.
light_probe_stage(gl::pipeline &pipeline, ::resource_manager &resource_manager)
Constructs a light probe stage.
Manages the loading, caching, and saving of resources.
std::shared_ptr< T > load(const std::filesystem::path &path)
Loads and caches a resource.
const std::vector< object_base * > & get_objects() const noexcept
Returns all objects in the collection.
const std::shared_ptr< gl::framebuffer > & get_illuminance_framebuffer() const noexcept
Returns the light probe's illuminance framebuffer.
bool is_luminance_outdated() const noexcept
Returns true if the light probe's luminance is outdated.
const std::shared_ptr< gl::texture_cube > & get_luminance_texture() const noexcept
Returns the light probe's luminance texture.
void set_illuminance_outdated(bool outdated)
Marks the light probe's illuminance as either outdated or current.
bool is_illuminance_outdated() const noexcept
Returns true if the light probe's illuminance is outdated.
const std::vector< std::shared_ptr< gl::framebuffer > > & get_luminance_framebuffers() const noexcept
Returns the light probe's luminance framebuffers.
void set_luminance_outdated(bool outdated)
Marks the light probe's luminance as either outdated or current.
Abstract base class for scene objects.
static const std::atomic< std::size_t > object_type_id
Unique type ID for this scene object type.
constexpr int count(T x) noexcept
Returns the number of set bits in a value, known as a population count or Hamming weight.
log_message< log_message_severity::warning, Args... > log_warning
Formats and logs a warning message.
log_message< log_message_severity::error, Args... > log_error
Formats and logs an error message.
@ repeat
Repeat wrap mode.
@ clamp_to_edge
Clamp to edge wrap mode.
@ color_attachment_bit
Framebuffer color attachment.
@ vertex
Vertex shader stage.
@ linear
Linear filtering.
@ nearest
Nearest filtering.
@ linear
Linear filtering.
@ nearest
Nearest filtering.
@ point_list
Separate point primitives.
@ triangle_list
Separate triangle primitives.
@ less
Comparison evaluates reference < test.
Viewport position, dimensions, and depth range.
scene::collection * collection
Collection of scene objects being rendered.