aboutsummaryrefslogtreecommitdiff
path: root/src/rendering/black_hole_renderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/rendering/black_hole_renderer.cpp')
-rw-r--r--src/rendering/black_hole_renderer.cpp62
1 files changed, 43 insertions, 19 deletions
diff --git a/src/rendering/black_hole_renderer.cpp b/src/rendering/black_hole_renderer.cpp
index 5916171..283435e 100644
--- a/src/rendering/black_hole_renderer.cpp
+++ b/src/rendering/black_hole_renderer.cpp
@@ -18,7 +18,7 @@ namespace Donut
struct CamUBO {
glm::vec3 pos; float p0; glm::vec3 right; float p1;
glm::vec3 up; float p2; glm::vec3 fwd; float p3;
- float tan_half_fov; float aspect; uint32_t moving; int p4;
+ float tan_half_fov; float aspect; uint32_t moving; int channel; int raw;
};
struct SimUBO { int steps_moving; int steps_static; float early_exit; float time; };
}
@@ -61,6 +61,8 @@ namespace Donut
d.topology = Topology::Triangles;
d.target = { Format::RGBA8, Format::None }; // colour-only off-screen target
m_geo_pipeline = device.create_pipeline(d);
+ d.target = { Format::RGBA32F, Format::None }; // raw-float export variant
+ m_geo_pipeline_hdr = device.create_pipeline(d);
}
{
PipelineDesc d;
@@ -81,11 +83,35 @@ namespace Donut
const BlackHoleParams& params,
const std::vector<SceneObject>& objects, RHI::Texture* cubemap) -> void
{
+ fill_uniforms(view, params, objects, 0, false); // channel 0 = colour, display
+
+ // Progressive resolution: small target while moving, large once settled.
+ RenderTarget* target = view.moving ? m_geo_lo.get() : m_geo_hi.get();
+ m_last_target = target;
+ draw_geodesic(cmd, target, cubemap, m_geo_pipeline.get());
+ }
+
+ // Renders one channel (0 colour, 1 redshift, 2 temperature, 3 impact parameter)
+ // into an arbitrary RGBA8 target — used by the exporter for high-res output.
+ auto BlackHoleRenderer::render_export(RHI::CommandList& cmd, RHI::RenderTarget* target,
+ const GeodesicView& view, const BlackHoleParams& params,
+ const std::vector<SceneObject>& objects,
+ RHI::Texture* cubemap, int channel, bool raw) -> void
+ {
+ fill_uniforms(view, params, objects, channel, raw);
+ draw_geodesic(cmd, target, cubemap, raw ? m_geo_pipeline_hdr.get() : m_geo_pipeline.get());
+ }
+
+ auto BlackHoleRenderer::fill_uniforms(const GeodesicView& view, const BlackHoleParams& params,
+ const std::vector<SceneObject>& objects, int channel, bool raw) -> void
+ {
CamUBO cam{};
cam.pos = view.position; cam.right = view.right; cam.up = view.up; cam.fwd = view.forward;
cam.tan_half_fov = view.tan_half_fov;
cam.aspect = view.aspect;
cam.moving = view.moving ? 1u : 0u;
+ cam.channel = channel;
+ cam.raw = raw ? 1 : 0;
m_cam_ubo->update(&cam, sizeof(cam));
// Same integration budget whether moving or settled (the disk vanishes at
@@ -115,29 +141,27 @@ namespace Donut
// Scene objects → the geodesic's Objects UBO (std140: numObjects@0,
// objPosRadius[i]@16+16i, objColor[i]@272+16i). They render as spheres the
// curved rays intersect, so the hole lenses them. 1 scene unit = 1 r_s.
+ const float k = SagA_rs / SCENE_UNITS_PER_RS; // scene units -> metres
+ std::vector<uint8_t> objbuf(800, 0);
+ int n = std::min((int)objects.size(), 16);
+ std::memcpy(objbuf.data(), &n, 4);
+ for (int i = 0; i < n; ++i)
{
- const float k = SagA_rs / SCENE_UNITS_PER_RS; // scene units -> metres
- std::vector<uint8_t> objbuf(800, 0);
- int n = std::min((int)objects.size(), 16);
- std::memcpy(objbuf.data(), &n, 4);
- for (int i = 0; i < n; ++i)
- {
- const SceneObject& o = objects[i];
- float pr[4] = { o.position.x * k, o.position.y * k, o.position.z * k, o.radius * k };
- float col[4] = { o.color.r, o.color.g, o.color.b, 1.0f };
- std::memcpy(objbuf.data() + 16 + 16 * i, pr, 16);
- std::memcpy(objbuf.data() + 272 + 16 * i, col, 16);
- }
- m_obj_ubo->update(objbuf.data(), objbuf.size());
+ const SceneObject& o = objects[i];
+ float pr[4] = { o.position.x * k, o.position.y * k, o.position.z * k, o.radius * k };
+ float col[4] = { o.color.r, o.color.g, o.color.b, 1.0f };
+ std::memcpy(objbuf.data() + 16 + 16 * i, pr, 16);
+ std::memcpy(objbuf.data() + 272 + 16 * i, col, 16);
}
+ m_obj_ubo->update(objbuf.data(), objbuf.size());
+ }
- // Progressive resolution: small target while moving, large once settled.
- RenderTarget* target = view.moving ? m_geo_lo.get() : m_geo_hi.get();
- m_last_target = target;
-
+ auto BlackHoleRenderer::draw_geodesic(RHI::CommandList& cmd, RHI::RenderTarget* target,
+ RHI::Texture* cubemap, RHI::Pipeline* pipeline) -> void
+ {
cmd.begin_render_pass(target, glm::vec4(0, 0, 0, 1));
cmd.set_viewport(0, 0, target->width(), target->height(), false);
- cmd.bind_pipeline(m_geo_pipeline.get());
+ cmd.bind_pipeline(pipeline);
cmd.bind_uniform(0, m_cam_ubo.get());
cmd.bind_uniform(1, m_disk_ubo.get());
cmd.bind_uniform(2, m_obj_ubo.get());