aboutsummaryrefslogtreecommitdiff
path: root/src/rendering/render_path.cpp
blob: 172e13c2f83f62809d13395311def8a4c363dd33 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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).
    }
}