aboutsummaryrefslogtreecommitdiff
path: root/src/rendering/render_path.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/rendering/render_path.cpp')
-rw-r--r--src/rendering/render_path.cpp94
1 files changed, 94 insertions, 0 deletions
diff --git a/src/rendering/render_path.cpp b/src/rendering/render_path.cpp
new file mode 100644
index 0000000..172e13c
--- /dev/null
+++ b/src/rendering/render_path.cpp
@@ -0,0 +1,94 @@
+#include "render_path.h"
+
+#include "scene/scene.h"
+
+#include <glm/gtc/matrix_transform.hpp>
+#include <algorithm>
+#include <cmath>
+
+namespace Donut
+{
+ auto RenderPath::init(RHI::Device& device, const std::string& hdri_path) -> bool
+ {
+ m_device = &device;
+ m_hdri_path = hdri_path;
+ m_cubemap = device.create_cubemap_from_hdri(hdri_path);
+
+ m_scene_renderer = create_scope<SceneRenderer>();
+ m_scene_renderer->init(device);
+ m_black_hole_renderer = create_scope<BlackHoleRenderer>();
+ m_black_hole_renderer->init(device);
+ return true;
+ }
+
+ auto RenderPath::sync_hdri(const std::string& hdri_path) -> void
+ {
+ if (hdri_path == m_hdri_path || !m_device) return;
+ m_device->wait_idle();
+ m_cubemap = m_device->create_cubemap_from_hdri(hdri_path); // old cube freed after idle
+ m_hdri_path = hdri_path;
+ }
+
+ auto RenderPath::render(RHI::CommandList& cmd, Scene& scene, View view,
+ int fb_width, int fb_height, bool moving, float time) -> void
+ {
+ const glm::vec4 clear(0.05f, 0.06f, 0.10f, 1.0f);
+
+ // The black hole is the only view with an off-screen pass; it renders (and
+ // runs the expensive geodesic) ONLY on the Simulation tab. Scene and None
+ // are a single swapchain pass — None draws nothing (empty viewport).
+ if (view != View::BlackHole)
+ {
+ cmd.begin_render_pass(nullptr, clear);
+ if (view == View::Scene)
+ {
+ float aspect = (float)fb_width / (float)std::max(fb_height, 1);
+ scene.scene_camera.set_projection(45.0f, aspect, 0.1f, 1000.0f);
+ CameraView cv;
+ cv.view = scene.scene_camera.get_view_matrix();
+ cv.projection = scene.scene_camera.get_projection_matrix();
+ cv.position = scene.scene_camera.get_orbital_position();
+ cv.fb_width = fb_width; cv.fb_height = fb_height;
+ m_scene_renderer->render(cmd, cv, scene.objects, scene.selected_object, m_cubemap.get());
+ }
+ m_device->imgui_render(cmd);
+ cmd.end_render_pass();
+ }
+ else
+ {
+ GeodesicView gv;
+ glm::vec3 pos, fwd;
+ if (scene.sim_camera.get_camera_mode() == CameraMode::FPS)
+ {
+ pos = scene.sim_camera.get_position();
+ fwd = scene.sim_camera.get_forward_direction();
+ }
+ else
+ {
+ pos = scene.sim_camera.get_orbital_position();
+ fwd = glm::normalize(scene.sim_camera.get_orbital_target() - pos);
+ }
+ glm::vec3 right = glm::normalize(glm::cross(fwd, glm::vec3(0, 1, 0)));
+ gv.position = pos; gv.right = right; gv.up = glm::cross(right, fwd); gv.forward = fwd;
+ gv.tan_half_fov = (float)tan(glm::radians(scene.black_hole.fov_degrees * 0.5f));
+ gv.aspect = (float)BlackHoleRenderer::GEO_HI_W / (float)BlackHoleRenderer::GEO_HI_H;
+ gv.moving = moving;
+ gv.time = time;
+
+ m_black_hole_renderer->render_geodesic(cmd, gv, scene.black_hole, m_cubemap.get());
+ cmd.begin_render_pass(nullptr, clear);
+ m_black_hole_renderer->blit(cmd, fb_width, fb_height);
+ m_device->imgui_render(cmd);
+ cmd.end_render_pass();
+ }
+ }
+
+ auto RenderPath::shutdown() -> void
+ {
+ m_scene_renderer.reset();
+ m_black_hole_renderer.reset();
+ m_cubemap.reset();
+ // Backend-specific HDRI/GPU resource cleanup is the device's job (see e.g.
+ // the OpenGL device clearing the HDRIManager texture cache on shutdown).
+ }
+}