aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assets/shaders/equirect_to_cubemap.slang4
-rw-r--r--assets/shaders/geodesic.slang71
-rw-r--r--assets/shaders/grid.slang2
-rw-r--r--assets/shaders/skybox.slang2
-rw-r--r--assets/shaders/sphere.slang2
-rw-r--r--assets/shaders/textured_quad.slang4
-rw-r--r--assets/shaders/vk_pipeline_test.slang4
-rw-r--r--src/core/application.cpp16
-rw-r--r--src/core/application.h10
-rw-r--r--src/core/window.cpp10
-rw-r--r--src/platform/opengl/opengl_device.cpp23
-rw-r--r--src/platform/opengl/shader.cpp16
-rw-r--r--src/platform/opengl/shader.h2
-rw-r--r--src/platform/opengl/texture.cpp18
-rw-r--r--src/platform/vulkan/vulkan_common.h25
-rw-r--r--src/platform/vulkan/vulkan_device.cpp4
-rw-r--r--src/platform/vulkan/vulkan_device.h4
-rw-r--r--src/platform/vulkan/vulkan_resources.cpp10
-rw-r--r--src/platform/vulkan/vulkan_swapchain.cpp8
-rw-r--r--src/rendering/black_hole_renderer.cpp18
-rw-r--r--src/rendering/black_hole_renderer.h12
-rw-r--r--src/rendering/export_config.h12
-rw-r--r--src/rendering/render_api.h4
-rw-r--r--src/rendering/render_path.cpp18
-rw-r--r--src/rendering/render_path.h14
-rw-r--r--src/rendering/rhi.h38
-rw-r--r--src/rendering/scene_renderer.cpp18
-rw-r--r--src/rendering/scene_renderer.h8
-rw-r--r--src/rendering/view.h8
-rw-r--r--src/scene/scene.cpp6
-rw-r--r--src/scene/scene.h13
-rw-r--r--src/scene/scene_types.h12
-rw-r--r--src/ui/ui_layer.cpp24
-rw-r--r--src/ui/ui_layer.h16
-rw-r--r--src/ui/workspace.h8
35 files changed, 231 insertions, 233 deletions
diff --git a/assets/shaders/equirect_to_cubemap.slang b/assets/shaders/equirect_to_cubemap.slang
index 510e6b0..5b4caff 100644
--- a/assets/shaders/equirect_to_cubemap.slang
+++ b/assets/shaders/equirect_to_cubemap.slang
@@ -1,7 +1,7 @@
-// Equirectangular HDRI -> cubemap face projection. NOTE: the OpenGL path uses the
+// equirectangular HDRI -> cubemap face projection. NOTE: the OpenGL path uses the
// hand-written assets/shaders/EquirectToCubemap.glsl instead; this Slang version
// feeds the Vulkan cubemap bake (vulkan_cubemap.cpp), which binds the view /
-// projection as a $Globals UBO. Kept as loose `uniform` globals (not a
+// projection as a $Globals UBO. kept as loose `uniform` globals (not a
// ConstantBuffer) so both paths bind them the same way.
uniform float4x4 u_projection;
diff --git a/assets/shaders/geodesic.slang b/assets/shaders/geodesic.slang
index eb536c9..937674e 100644
--- a/assets/shaders/geodesic.slang
+++ b/assets/shaders/geodesic.slang
@@ -1,8 +1,8 @@
-// Ray-traced Schwarzschild black hole: back-traces one null geodesic per pixel
+// ray-traced Schwarzschild black hole: back-traces one null geodesic per pixel
// through curved spacetime, shading the accretion disk, the lensed HDRI
-// background, and placed objects. Runs as a full-screen fragment pass. Uniforms
+// background, and placed objects. runs as a full-screen fragment pass. uniforms
// live in ConstantBuffers (UBOs) driven through the RHI; the HDRI is a cubemap
-// sampler. See docs/physics.md for the maths.
+// sampler. see docs/physics.md for the maths.
struct VSInput { float2 position : POSITION; float2 texCoord : TEXCOORD0; };
struct VSOutput { float4 position : SV_Position; float2 texCoord : TEXCOORD0; };
@@ -61,7 +61,7 @@ ConstantBuffer<Simulation> sim;
SamplerCube u_HDRIEnvironment;
-// Schwarzschild radius of Sgr A* (metres). Geometric units with c = G = 1 are
+// Schwarzschild radius of Sgr A* (metres). geometric units with c = G = 1 are
// used throughout the geodesic integration; the black-hole mass is M = r_s / 2.
static const float SagA_rs = 1.269e10;
static const float D_LAMBDA = 1e7;
@@ -69,7 +69,7 @@ static const float ESCAPE_R = 1e30;
static const float R_ISCO = 3.0 * SagA_rs; // innermost stable circular orbit (6M)
static const float R_PHOTON = 1.5 * SagA_rs; // photon sphere (3M)
-static const float FLUX_PEAK = 0.0569; // peak of the r^-3(1-sqrt(r_in/r)) profile (at r/r_in ~ 1.36)
+static const float FLUX_PEAK = 0.0569; // peak of the r^-3(1-sqrt(r_in/r)) profile (~r/r_in 1.36); worked it out once, now it's just the normaliser
static const int DEFAULT_MAX_STEPS_MOVING = 12000;
static const int DEFAULT_MAX_STEPS_STATIC = 8000;
@@ -78,8 +78,8 @@ static const float DEFAULT_EARLY_EXIT_DISTANCE = 2e12;
static const float MIN_STEP_SIZE = 1e6;
static const float MAX_STEP_SIZE = 2e10;
-// Display mapping for the (relative) Novikov-Thorne flux -> visible colour.
-// The RADIAL PROFILE is physical; the absolute temperature scale is a display
+// display mapping for the (relative) Novikov-Thorne flux -> visible colour.
+// the RADIAL PROFILE is physical; the absolute temperature scale is a display
// choice (a real Sgr A* disk is far cooler / redder than this).
struct Hit
@@ -91,6 +91,7 @@ struct Hit
float hash(float3 p)
{
+ // magic primes, don't ask — they just scramble bits into a clean 0..1 hash
p = frac(p * float3(0.1031, 0.1030, 0.0973));
p += dot(p, p.yxz + 33.33);
return frac((p.x + p.y) * p.z);
@@ -129,8 +130,10 @@ float fbm(float3 x, int octaves)
return v;
}
-// Planckian-locus blackbody colour (Tanner Helland approximation), T in Kelvin.
-// Returns an sRGB-ish chromaticity normalised so the brightest channel ~ 1.
+// blackbody colour along the Planckian locus, T in Kelvin. it's Tanner Helland's
+// curve fit and the coefficients below are pure magic-number soup — idk exactly
+// how they were derived, so like just trust them. returns an sRGB-ish
+// chromaticity normalised so the brightest channel ~ 1.
float3 Blackbody(float T)
{
T = clamp(T, 1000.0, 40000.0);
@@ -149,11 +152,11 @@ float3 Blackbody(float T)
return c;
}
-// Emission from the thin accretion disk at an equatorial crossing point P, seen
-// along the (backward-traced) ray direction rayDir. Combines a Novikov-Thorne
+// emission from the thin accretion disk at an equatorial crossing point P, seen
+// along the (backward-traced) ray direction rayDir. combines a Novikov-Thorne
// temperature profile with the full gravitational + Doppler redshift.
// g = sqrt(1 - 3M/r) / (1 - beta . nhat) (verified: g -> sqrt(1/2) at ISCO)
-// Brightness follows relativistic beaming (I_obs = g^4 I_emit); colour follows
+// brightness follows relativistic beaming (I_obs = g^4 I_emit); colour follows
// the redshifted blackbody at T_obs = g * T_emit.
float3 DiskEmission(float3 P, float3 rayDir, out float outG, out float outTemit)
{
@@ -171,7 +174,7 @@ float3 DiskEmission(float3 P, float3 rayDir, out float outG, out float outTemit)
float Tn = pow(flux / FLUX_PEAK, 0.25); // normalised temperature, peak ~ 1
float Temit = disk.u_temperature * Tn;
- // Keplerian orbit (prograde about +Y). Locally-measured orbital speed for a
+ // Keplerian orbit (prograde about +Y). locally-measured orbital speed for a
// Schwarzschild circular geodesic: v = sqrt( M / (r - 2M) ) = 0.5 c at ISCO.
float3 rhat = normalize(float3(P.x, 0.0, P.z));
float3 phiHat = normalize(cross(float3(0.0, 1.0, 0.0), rhat));
@@ -184,17 +187,17 @@ float3 DiskEmission(float3 P, float3 rayDir, out float outG, out float outTemit)
float Tobs = g * Temit;
float3 colour = Blackbody(Tobs);
- // Physical bolometric intensity is ~ T_emit^4 * g^4, an enormous dynamic
- // range. The g^4 relativistic beaming (the physical asymmetry) is kept; the
+ // physical bolometric intensity is ~ T_emit^4 * g^4, an enormous dynamic
+ // range. the g^4 relativistic beaming (the physical asymmetry) is kept; the
// radial falloff is display-compressed (Tn^2) so the colour gradient across
// the disk stays visible instead of collapsing to a thin saturated ring.
float bright = pow(Tn, 2.0) * pow(g, 4.0);
- // Soft inner/outer edges (disks have no hard rim); also tames rim aliasing.
+ // soft inner/outer edges (disks have no hard rim); also tames rim aliasing.
float edge = smoothstep(rin, rin * 1.12, rc) * (1.0 - smoothstep(rout * 0.88, rout, rc));
bright *= edge;
- // Optional turbulence overlay (disk.u_turbulence = strength; 0 = smooth).
+ // optional turbulence overlay (disk.u_turbulence = strength; 0 = smooth).
if (disk.u_turbulence > 0.0)
{
float ang = sim.u_time * 0.3 / sqrt(xr);
@@ -304,13 +307,13 @@ void RK4Step(inout Ray ray, float dL)
float CalculateAdaptiveStepSize(Ray ray, float baseStepSize)
{
- // Step proportional to the distance from the photon sphere: near-flat space
+ // step proportional to the distance from the photon sphere: near-flat space
// far from the hole is crossed in a few huge steps, while the sharply curved
- // region near the photon sphere is resolved with tiny ones. This keeps the
+ // region near the photon sphere is resolved with tiny ones. this keeps the
// integration accurate near the hole regardless of how far the camera is.
float step = 0.02 * max(ray.r - R_PHOTON, 0.0);
- // Slow down when near the disk plane (within its radial extent) so the thin
+ // slow down when near the disk plane (within its radial extent) so the thin
// slab is never stepped over -- otherwise grazing rays leak through it.
float rc = length(float2(ray.x, ray.z));
if (rc < disk.u_outer_radius * 3.0 && abs(ray.y) < disk.u_thickness * 8.0)
@@ -319,12 +322,14 @@ float CalculateAdaptiveStepSize(Ray ray, float baseStepSize)
return clamp(step, MIN_STEP_SIZE, MAX_STEP_SIZE);
}
+// Narkowicz's ACES filmic tonemap. the constants are just The Numbers everyone
+// copies — idk the derivation, but it squashes HDR radiance into a nice 0..1 curve.
float3 ACESFilm(float3 x)
{
return clamp((x * (2.51 * x + 0.03)) / (x * (2.43 * x + 0.59) + 0.14), 0.0, 1.0);
}
-// A jet-ish false-colour ramp (blue -> cyan -> green -> yellow -> red) for the
+// a jet-ish false-colour ramp (blue -> cyan -> green -> yellow -> red) for the
// observable export channels. t is expected in [0, 1].
float3 Falsecolor(float t)
{
@@ -334,8 +339,8 @@ float3 Falsecolor(float t)
1.5 - abs(4.0 * t - 1.0)), 0.0, 1.0);
}
-// Trace one primary ray for the given image UV and return its linear,
-// pre-tone-map radiance. Called once per sub-sample by fragmentMain.
+// trace one primary ray for the given image UV and return its linear,
+// pre-tone-map radiance. called once per sub-sample by fragmentMain.
float3 TracePixel(float2 texCoord, out float outG, out float outTemit, out bool outHitDisk)
{
outG = 0.0; outTemit = 0.0; outHitDisk = false;
@@ -371,9 +376,9 @@ float3 TracePixel(float2 texCoord, out float outG, out float outTemit, out bool
RK4Step(ray, stepSize);
float3 newPos = float3(ray.x, ray.y, ray.z);
- // Opaque disk of small half-thickness H (a slab about the midplane y=0).
- // The ray hits when it first crosses the midplane OR enters the slab
- // while grazing along it. Real (nonzero) thickness stops the zero-height
+ // opaque disk of small half-thickness H (a slab about the midplane y=0).
+ // the ray hits when it first crosses the midplane OR enters the slab
+ // while grazing along it. real (nonzero) thickness stops the zero-height
// edge-on "razor" from aliasing into a beam streaking across the frame.
{
float H = disk.u_thickness;
@@ -397,13 +402,13 @@ float3 TracePixel(float2 texCoord, out float outG, out float outTemit, out bool
if (i % objectCheckInterval == 0 && InterceptObject(ray, hit)) { hitObject = true; break; }
- // Principled escape: once outbound in near-flat spacetime (r >> r_s) the
+ // principled escape: once outbound in near-flat spacetime (r >> r_s) the
// ray direction no longer changes, so stop and read the background.
if (ray.dr > 0.0 && ray.r > 50.0 * SagA_rs) break;
}
- // Escape direction + environment mip LOD from the ray's angular divergence.
- // Computed UNCONDITIONALLY (before the branch) so ddx/ddy are valid; strongly
+ // escape direction + environment mip LOD from the ray's angular divergence.
+ // computed UNCONDITIONALLY (before the branch) so ddx/ddy are valid; strongly
// lensed background rays diverge fast, so they read a blurred cubemap mip and
// the starfield stops aliasing into a fan along the equatorial plane.
float3 rayDir = normalize(float3(ray.x, ray.y, ray.z) - cam.u_cam_pos);
@@ -438,14 +443,14 @@ float3 TracePixel(float2 texCoord, out float outG, out float outTemit, out bool
[shader("fragment")]
float4 fragmentMain(VSOutput input) : SV_Target
{
- // Moving frame: one sample for responsiveness. Settled frame: rotated-grid
+ // moving frame: one sample for responsiveness. settled frame: rotated-grid
// 4x supersampling (the 4-rook pattern gives 4 distinct sub-pixel positions
// on BOTH axes, far better on the near-horizontal lensed edges than an
- // ordered grid). Radiance is averaged before tone-mapping; ddx/ddy give the
+ // ordered grid). radiance is averaged before tone-mapping; ddx/ddy give the
// resolution-correct per-pixel UV footprint.
- // Observable export channels: the chosen scalar quantity, either as a raw
+ // observable export channels: the chosen scalar quantity, either as a raw
// float (u_raw_output: value in RGB, validity mask in A) or false-coloured.
- // Channel 0 is the normal colour image.
+ // channel 0 is the normal colour image.
if (cam.u_output_channel != 0)
{
float g, Temit; bool hitDisk;
diff --git a/assets/shaders/grid.slang b/assets/shaders/grid.slang
index 8dc4362..13aa349 100644
--- a/assets/shaders/grid.slang
+++ b/assets/shaders/grid.slang
@@ -1,4 +1,4 @@
-// Reference grid on the XZ plane. Uniforms live in a ConstantBuffer (UBO) so both
+// reference grid on the XZ plane. uniforms live in a ConstantBuffer (UBO) so both
// backends drive it through the same RHI path (bind a uniform buffer at binding 0).
struct Grid
{
diff --git a/assets/shaders/skybox.slang b/assets/shaders/skybox.slang
index f7aeb50..ae7634c 100644
--- a/assets/shaders/skybox.slang
+++ b/assets/shaders/skybox.slang
@@ -1,4 +1,4 @@
-// Full-screen skybox cube. View/projection in a ConstantBuffer (UBO, binding 0)
+// full-screen skybox cube. view/projection in a ConstantBuffer (UBO, binding 0)
// so both backends drive it through the RHI; the cubemap is a sampler at binding 1.
struct Skybox
{
diff --git a/assets/shaders/sphere.slang b/assets/shaders/sphere.slang
index 41badde..2c547e6 100644
--- a/assets/shaders/sphere.slang
+++ b/assets/shaders/sphere.slang
@@ -1,4 +1,4 @@
-// Lit sphere (Blinn-Phong + HDRI ambient + selection rim). Uniforms in a
+// lit sphere (Blinn-Phong + HDRI ambient + selection rim). uniforms in a
// ConstantBuffer (UBO, binding 0) so both backends drive it through the RHI;
// the environment cubemap is a separate sampler at binding 1.
struct Sphere
diff --git a/assets/shaders/textured_quad.slang b/assets/shaders/textured_quad.slang
index b72db81..9ff81fd 100644
--- a/assets/shaders/textured_quad.slang
+++ b/assets/shaders/textured_quad.slang
@@ -1,5 +1,5 @@
-// Full-screen textured quad: samples one 2D texture straight to the target.
-// Used to blit an off-screen colour buffer to the swapchain.
+// full-screen textured quad: samples one 2D texture straight to the target.
+// used to blit an off-screen colour buffer to the swapchain.
struct VSInput { float2 position : POSITION; float2 texCoord : TEXCOORD0; };
struct VSOutput { float4 position : SV_Position; float2 texCoord : TEXCOORD0; };
diff --git a/assets/shaders/vk_pipeline_test.slang b/assets/shaders/vk_pipeline_test.slang
index 453fcd3..c644d7c 100644
--- a/assets/shaders/vk_pipeline_test.slang
+++ b/assets/shaders/vk_pipeline_test.slang
@@ -1,5 +1,5 @@
-// Minimal shader used only to verify the Vulkan graphics-pipeline path (SPIR-V
-// module -> pipeline -> draw -> read-back). Draws a full-screen gradient triangle
+// minimal shader used only to verify the Vulkan graphics-pipeline path (SPIR-V
+// module -> pipeline -> draw -> read-back). draws a full-screen gradient triangle
// from the vertex id, so it needs no vertex buffer, UBO, or sampler.
struct VSOutput { float4 position : SV_Position; float3 color : COLOR0; };
diff --git a/src/core/application.cpp b/src/core/application.cpp
index c24e029..5a3a21b 100644
--- a/src/core/application.cpp
+++ b/src/core/application.cpp
@@ -17,7 +17,7 @@ namespace Donut
{
Application* Application::s_instance = nullptr;
- // Scroll is delivered through a GLFW callback; accumulate it here and drain it
+ // scroll is delivered through a GLFW callback; accumulate it here and drain it
// once per frame in update_input (chaining ImGui's own scroll handler).
static double g_scroll_accum = 0.0;
static GLFWscrollfun g_prev_scroll = nullptr;
@@ -31,7 +31,7 @@ namespace Donut
{
s_instance = this;
- // Select the render API before the window is created: the window is built
+ // select the render API before the window is created: the window is built
// differently for Vulkan (GLFW_NO_API) than for OpenGL.
Logger::init();
SettingsManager::initialize();
@@ -79,7 +79,7 @@ namespace Donut
m_ui = create_scope<UILayer>();
m_device->init_imgui();
- // Load the UI font into the device-created ImGui context (backend-agnostic;
+ // load the UI font into the device-created ImGui context (backend-agnostic;
// the backend rebuilds the atlas on the next frame).
ImGuiIO& io = ImGui::GetIO();
if (!io.Fonts->AddFontFromFileTTF("assets/fonts/inter/static/Inter_18pt-Regular.ttf", 16.0f))
@@ -103,7 +103,7 @@ namespace Donut
if (!m_minimized && m_device)
render_frame();
- // With vsync off, cap to the target FPS (vsync itself paces otherwise).
+ // with vsync off, cap to the target FPS (vsync itself paces otherwise).
if (!SettingsManager::get_v_sync_enabled())
{
int fps = SettingsManager::get_target_fps();
@@ -159,8 +159,8 @@ namespace Donut
m_device->imgui_new_frame();
- // Keep the scene camera's projection current before the UI builds, so the
- // scene-tab gizmo and the render agree on the same matrices this frame.
+ // keep the scene camera's projection current before the UI builds, so the
+ // scene-view gizmo and the render agree on the same matrices this frame.
int w = 0, h = 0;
glfwGetFramebufferSize((GLFWwindow*)m_window->get_native_window(), &w, &h);
m_scene->scene_camera.set_projection(45.0f, (float)w / (float)std::max(h, 1), 0.1f, 1000.0f);
@@ -188,11 +188,11 @@ namespace Donut
glfwGetCursorPos(window, &mx, &my);
bool left_down = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS;
- // Tabs without a live viewport (Setup / Export) have no camera to drive.
+ // a None view has no live viewport, so there's no camera to drive.
if (view == View::None)
{
m_left_was_down = left_down; // keep the drag-edge state coherent
- g_scroll_accum = 0.0; // discard scroll over inert tabs
+ g_scroll_accum = 0.0; // no live view: nothing to scroll
m_user_moving = false;
return;
}
diff --git a/src/core/application.h b/src/core/application.h
index f1e40c8..bb88919 100644
--- a/src/core/application.h
+++ b/src/core/application.h
@@ -15,10 +15,10 @@
namespace Donut
{
- // Thin shell: owns the window, the RHI device, the Scene (document), the
- // RenderPath (device-side rendering) and the UILayer (tabbed workspaces), and
- // runs the frame loop that wires them together. All the rendering lives in the
- // RHI + shared renderers; all the editing lives in the Scene + workspaces.
+ // thin shell: owns the window, the RHI device, the Scene (document), the
+ // RenderPath (device-side rendering) and the UILayer (docking UI), and runs
+ // the frame loop that wires them together. all the rendering lives in the
+ // RHI + shared renderers; all the editing lives in the Scene + UI panels.
class Application : public AppActions
{
public:
@@ -32,7 +32,7 @@ namespace Donut
auto get_window() -> Window& { return *m_window; }
static auto get() -> Application& { return *s_instance; }
- // AppActions — window/device changes requested by the Setup workspace.
+ // AppActions — window/device changes requested by the Settings panel.
auto set_resolution(int w, int h) -> void override;
auto set_fullscreen(bool on) -> void override;
auto set_vsync(bool on) -> void override;
diff --git a/src/core/window.cpp b/src/core/window.cpp
index dd5882c..085d7bc 100644
--- a/src/core/window.cpp
+++ b/src/core/window.cpp
@@ -39,16 +39,16 @@ namespace Donut
if (RendererAPI::get_api() == RendererAPI::API::Vulkan)
{
- // Vulkan manages presentation itself; GLFW must not create a GL context.
+ // Vulkan does its own presentation, so GLFW must NOT sneak in a GL context.
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
}
else
{
#ifdef __APPLE__
- // macOS only exposes OpenGL up to 4.1 Core Profile, and requires a
- // forward-compatible core-profile context for any modern (>= 3.3)
- // shader to compile. Without these hints GLFW hands back a legacy
- // 2.1 context and every GLSL shader in the project fails to build.
+ // macOS caps OpenGL at 4.1 Core Profile and demands a forward-compat
+ // core-profile context for anything modern (>= 3.3) to even compile.
+ // skip these hints and GLFW hands you a dusty 2.1 context and every
+ // single shader in the project refuses to build. so, we ask nicely:
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
diff --git a/src/platform/opengl/opengl_device.cpp b/src/platform/opengl/opengl_device.cpp
index 614e515..dd5581d 100644
--- a/src/platform/opengl/opengl_device.cpp
+++ b/src/platform/opengl/opengl_device.cpp
@@ -21,7 +21,6 @@ namespace Donut::RHI
auto gl_filter(Filter f) -> GLint { return f == Filter::Nearest ? GL_NEAREST : GL_LINEAR; }
auto gl_internal(Format f) -> GLint { return f == Format::RGBA16F ? GL_RGBA16F : f == Format::RGBA32F ? GL_RGBA32F : f == Format::D32 ? GL_DEPTH_COMPONENT32F : GL_RGBA8; }
- // ---- Buffer -------------------------------------------------------
class GLBuffer : public Buffer
{
public:
@@ -42,7 +41,6 @@ namespace Donut::RHI
GLuint m_id = 0; GLenum m_target = GL_ARRAY_BUFFER;
};
- // ---- Texture ------------------------------------------------------
class GLTexture : public Texture
{
public:
@@ -69,7 +67,6 @@ namespace Donut::RHI
Ref<CubemapTexture> m_cube; // keepalive for cubemaps
};
- // ---- RenderTarget -------------------------------------------------
class GLRenderTarget : public RenderTarget
{
public:
@@ -102,7 +99,6 @@ namespace Donut::RHI
GLuint m_fbo = 0, m_depth = 0; int m_w, m_h; Scope<GLTexture> m_color;
};
- // ---- Pipeline -----------------------------------------------------
class GLPipeline : public Pipeline
{
public:
@@ -120,12 +116,12 @@ namespace Donut::RHI
{
GLuint bi = glGetUniformBlockIndex(m_prog, r.name.c_str());
if (bi != GL_INVALID_INDEX) glUniformBlockBinding(m_prog, bi, r.binding);
- // Not found: the ConstantBuffer<> type name in the shader no longer
+ // not found: the ConstantBuffer<> type name in the shader no longer
// matches this resource string, so the UBO silently won't bind.
else DONUT_WARN("GL RHI: shader '{}' has no uniform block '{}' (binding {})",
d.shader, r.name, r.binding);
}
- else // Texture: point the sampler at texture unit == binding
+ else // texture: point the sampler at texture unit == binding
{
GLint loc = glGetUniformLocation(m_prog, r.name.c_str());
if (loc >= 0) glUniform1i(loc, (GLint)r.binding);
@@ -138,7 +134,7 @@ namespace Donut::RHI
PipelineDesc m_desc; Ref<Shader> m_shader; GLuint m_prog = 0;
};
- // ---- CommandList (immediate) --------------------------------------
+ // GL has no command buffers, so every call here executes immediately.
class GLCommandList : public CommandList
{
public:
@@ -155,7 +151,7 @@ namespace Donut::RHI
glClearColor(clear.r, clear.g, clear.b, clear.a);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
- auto end_render_pass() -> void override {}
+ auto end_render_pass() -> void override {} // GL passes are a fiction; nothing to close
auto bind_pipeline(Pipeline* p) -> void override
{
@@ -208,7 +204,6 @@ namespace Donut::RHI
GLuint m_vao; GLPipeline* m_pipe = nullptr; int m_default_w = 1, m_default_h = 1;
};
- // ---- Device -------------------------------------------------------
class GLDevice : public Device
{
public:
@@ -220,17 +215,17 @@ namespace Donut::RHI
m_width = window.width; m_height = window.height;
const char* name = (const char*)glGetString(GL_RENDERER);
m_name = name ? name : "OpenGL";
- glGenVertexArrays(1, &m_vao); glBindVertexArray(m_vao); // GL core needs one bound VAO
+ glGenVertexArrays(1, &m_vao); glBindVertexArray(m_vao); // GL core wants one VAO bound at all times, so like, here's one
m_cmds = create_scope<GLCommandList>(m_vao);
DONUT_INFO("GL RHI device: {} ({}x{})", m_name, m_width, m_height);
return true;
}
auto shutdown() -> void override
{
- // Free the HDRIManager's cached GL cubemaps while our context is
- // still current (they are static-singleton-owned; letting them
- // destruct at program exit would glDeleteTextures after the context
- // is gone and crash on close).
+ // nuke the HDRIManager's cached GL cubemaps while our context is
+ // still alive. they're static-singleton-owned, so if we let them
+ // destruct at program exit they'd glDeleteTextures into a dead
+ // context and crash on close. no thanks.
HDRIManager::get().clear_cache();
if (m_imgui) { ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); m_imgui = false; }
if (m_vao) { glDeleteVertexArrays(1, &m_vao); m_vao = 0; }
diff --git a/src/platform/opengl/shader.cpp b/src/platform/opengl/shader.cpp
index 80015e6..757382b 100644
--- a/src/platform/opengl/shader.cpp
+++ b/src/platform/opengl/shader.cpp
@@ -19,8 +19,8 @@ namespace Donut
return 0;
}
- // Shaders are authored in Slang and compiled to assets/shaders/generated/
- // <name>.glsl by tools/compile-shaders.sh. Given a legacy ".../<name>.glsl"
+ // shaders are authored in Slang and compiled to assets/shaders/generated/
+ // <name>.glsl by tools/compile-shaders.sh. given a legacy ".../<name>.glsl"
// path, prefer that generated file when present; otherwise fall back to the
// hand-written GLSL (e.g. shaders not yet ported to Slang).
static std::string ResolveShaderPath(const std::string& filepath)
@@ -145,9 +145,9 @@ namespace Donut
glDeleteShader(id);
glDeleteProgram(program);
m_renderer_id = 0;
- // info_log.data() is null when the driver returns an empty log
- // (e.g. macOS rejecting a compute shader); streaming a null
- // char* into std::cout calls strlen(NULL) and crashes.
+ // info_log.data() is null when the driver hands back an empty log
+ // (e.g. macOS rejecting a compute shader). streaming a null char*
+ // into std::cout does strlen(NULL) and just explodes. cool cool cool.
const char* log = info_log.empty() ? "" : info_log.data();
std::cout << "Shader compilation failure!" << std::endl << log << std::endl;
return;
@@ -278,9 +278,9 @@ namespace Donut
auto Shader::dispatch(uint32_t x, uint32_t y, uint32_t z) -> void
{
- // Compute shaders require OpenGL 4.3+. On drivers that cap out earlier
- // (e.g. macOS, which is frozen at 4.1) glDispatchCompute is never
- // loaded and the pointer is null. Guard so we no-op instead of crash.
+ // compute shaders want OpenGL 4.3+ and macOS is frozen at 4.1, so
+ // glDispatchCompute never even loads and the pointer is null. guard it
+ // and quietly no-op instead of face-planting.
if (m_renderer_id == 0 || glDispatchCompute == nullptr)
return;
glDispatchCompute(x, y, z);
diff --git a/src/platform/opengl/shader.h b/src/platform/opengl/shader.h
index 409aca3..89963c7 100644
--- a/src/platform/opengl/shader.h
+++ b/src/platform/opengl/shader.h
@@ -59,7 +59,7 @@ namespace Donut
uint32_t m_renderer_id = 0;
std::string m_name;
- // True when loaded from a Slang-compiled GLSL. Slang expects row-major
+ // true when loaded from a Slang-compiled GLSL. Slang expects row-major
// matrix data, so matrix uniforms are transposed on upload (glm is
// column-major) to keep all matrix math correct.
bool m_is_slang = false;
diff --git a/src/platform/opengl/texture.cpp b/src/platform/opengl/texture.cpp
index 12e07f1..d2d2233 100644
--- a/src/platform/opengl/texture.cpp
+++ b/src/platform/opengl/texture.cpp
@@ -11,10 +11,10 @@
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
-// NOTE: This file targets OpenGL 4.1 (the maximum macOS exposes). It uses the
+// this file targets OpenGL 4.1 (the maximum macOS exposes). it uses the
// classic bind-based texture API rather than 4.5 Direct State Access
// (glCreateTextures / glTextureStorage2D / glTextureParameteri / glBindTextureUnit),
-// none of which exist on macOS. It also hosts the single STB_IMAGE_IMPLEMENTATION
+// none of which exist on macOS. it also hosts the single STB_IMAGE_IMPLEMENTATION
// for the whole build (the Vulkan backend links stbi_loadf from here too).
namespace Donut
@@ -84,7 +84,7 @@ namespace Donut
auto Texture2D::bind_as_image(uint32_t slot, bool read_only) const -> void
{
- // Image load/store is OpenGL 4.2 and unavailable on macOS. Guard the
+ // image load/store is OpenGL 4.2 and unavailable on macOS. guard the
// function pointer so this degrades to a no-op instead of crashing.
if (glBindImageTexture == nullptr)
return;
@@ -148,12 +148,12 @@ namespace Donut
DONUT_ERROR("Failed to load HDRI: {}", path);
float default_sky[6 * 4] =
{
- 0.5f, 0.7f, 1.0f, 1.0f, // Right
- 0.5f, 0.7f, 1.0f, 1.0f, // Left
- 0.5f, 0.7f, 1.0f, 1.0f, // Top
- 0.5f, 0.7f, 1.0f, 1.0f, // Bottom
- 0.5f, 0.7f, 1.0f, 1.0f, // Front
- 0.5f, 0.7f, 1.0f, 1.0f // Back
+ 0.5f, 0.7f, 1.0f, 1.0f, // right
+ 0.5f, 0.7f, 1.0f, 1.0f, // left
+ 0.5f, 0.7f, 1.0f, 1.0f, // top
+ 0.5f, 0.7f, 1.0f, 1.0f, // bottom
+ 0.5f, 0.7f, 1.0f, 1.0f, // front
+ 0.5f, 0.7f, 1.0f, 1.0f // back
};
glBindTexture(GL_TEXTURE_CUBE_MAP, m_renderer_id);
diff --git a/src/platform/vulkan/vulkan_common.h b/src/platform/vulkan/vulkan_common.h
index 8f02f17..cb86d69 100644
--- a/src/platform/vulkan/vulkan_common.h
+++ b/src/platform/vulkan/vulkan_common.h
@@ -1,10 +1,10 @@
#pragma once
-// Shared internals of the Vulkan RHI backend: the enum-mapping helpers, the
+// shared internals of the Vulkan RHI backend: the enum-mapping helpers, the
// opaque resource classes (Buffer/Texture/RenderTarget/Pipeline/CommandList), and
-// the VulkanDevice declaration. The implementation is split across vulkan_device
+// the VulkanDevice declaration. the implementation is split across vulkan_device
// (lifecycle + frame loop), vulkan_swapchain (instance/device/swapchain/passes),
-// vulkan_resources (buffer/texture/target/pipeline) and vulkan_cubemap. This
+// vulkan_resources (buffer/texture/target/pipeline) and vulkan_cubemap. this
// header is private to platform/vulkan/ — nothing outside includes it.
#include "vulkan_device.h" // rendering/rhi.h (base classes + factory decls)
@@ -63,7 +63,7 @@ namespace Donut::RHI
inline auto vk_cull(CullMode c) -> VkCullModeFlags
{ return c == CullMode::None ? VK_CULL_MODE_NONE : c == CullMode::Back ? VK_CULL_MODE_BACK_BIT : VK_CULL_MODE_FRONT_BIT; }
- // Buffer: host-visible + coherent, persistently mapped.
+ // buffer: host-visible + coherent, persistently mapped.
class VkBufferR : public Buffer
{
public:
@@ -81,7 +81,7 @@ namespace Donut::RHI
VkDevice m_device; VkBuffer m_buf; VkDeviceMemory m_mem; void* m_mapped; size_t m_size;
};
- // Texture: sampled image (2D or cube). Owns its handles unless it is a borrowed
+ // texture: sampled image (2D or cube). owns its handles unless it is a borrowed
// wrapper around a render-target view.
class VkTextureR : public Texture
{
@@ -138,7 +138,7 @@ namespace Donut::RHI
VkTextureR m_color; // borrowed wrapper (view+sampler) for sampling
};
- // Pipeline: the graphics pipeline + its (set-0) descriptor layout.
+ // pipeline: the graphics pipeline + its (set-0) descriptor layout.
class VkPipelineR : public Pipeline
{
public:
@@ -155,8 +155,9 @@ namespace Donut::RHI
std::vector<ResourceSlot> m_resources;
};
- // CommandList: records into the frame's command buffer. Per-draw descriptor
- // sets are allocated from a per-frame pool (no push-descriptor extension).
+ // CommandList: records into the frame's command buffer. MoltenVK has no
+ // push-descriptor extension, so we just grab a fresh descriptor set per draw
+ // from a per-frame pool. kinda wasteful, but it works and that's what counts.
class VkCommandListR : public CommandList
{
public:
@@ -219,7 +220,7 @@ namespace Donut::RHI
auto draw_indexed(uint32_t index_count) -> void override
{ flush_descriptors(); vkCmdDrawIndexed(m_cmd, index_count, 1, 0, 0, 0); }
- // Allocate + write + bind a descriptor set for the current pipeline's
+ // allocate + write + bind a descriptor set for the current pipeline's
// declared resources, using whatever was bound since bind_pipeline.
auto flush_descriptors() -> void
{
@@ -246,7 +247,7 @@ namespace Donut::RHI
vkCmdBindDescriptorSets(m_cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipe->m_layout, 0, 1, &set, 0, nullptr);
}
- // Set by the device at begin_frame:
+ // set by the device at begin_frame:
VkDevice m_device = VK_NULL_HANDLE;
VkCommandBuffer m_cmd = VK_NULL_HANDLE;
VkRenderPass m_swapchain_rp = VK_NULL_HANDLE;
@@ -259,7 +260,7 @@ namespace Donut::RHI
VkDescriptorImageInfo m_img_info[MAX_BINDINGS]{};
};
- // The backend device. Its methods are defined across vulkan_device.cpp,
+ // the backend device. its methods are defined across vulkan_device.cpp,
// vulkan_swapchain.cpp, vulkan_resources.cpp and vulkan_cubemap.cpp.
class VulkanDevice : public Device
{
@@ -298,7 +299,7 @@ namespace Donut::RHI
auto pick_physical_and_device() -> bool;
auto create_swapchain() -> bool;
auto create_image_views() -> bool;
- // Render passes are format-driven and cached: a pipeline/target's
+ // render passes are format-driven and cached: a pipeline/target's
// attachment signature (colour + optional depth, present vs sampled)
// maps to one pass. `present` = presented swapchain image.
auto get_render_pass(VkFormat color, VkFormat depth, bool present) -> VkRenderPass;
diff --git a/src/platform/vulkan/vulkan_device.cpp b/src/platform/vulkan/vulkan_device.cpp
index ff2e296..a4f9ac7 100644
--- a/src/platform/vulkan/vulkan_device.cpp
+++ b/src/platform/vulkan/vulkan_device.cpp
@@ -58,7 +58,7 @@ namespace Donut::RHI
if (!pick_physical_and_device()) return false;
if (!create_swapchain()) return false;
if (!create_image_views()) return false;
- // The swapchain is a "present" target: its colour format + a D32 depth.
+ // the swapchain is a "present" target: its colour format + a D32 depth.
m_swapchain_rp = get_render_pass(m_swapchain_format, VK_FORMAT_D32_SFLOAT, true);
if (!m_swapchain_rp) return false;
if (!create_depth_and_framebuffers())return false;
@@ -156,7 +156,7 @@ namespace Donut::RHI
VkCommandBuffer cmd; vkAllocateCommandBuffers(m_device, &cbai, &cmd);
VkCommandBufferBeginInfo bi{ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; bi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
vkBeginCommandBuffer(cmd, &bi);
- // The target ended its render pass in SHADER_READ_ONLY; move it to TRANSFER_SRC to copy.
+ // the target ended its render pass in SHADER_READ_ONLY; move it to TRANSFER_SRC to copy.
VkImageMemoryBarrier b{ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
b.oldLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; b.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
b.image = rt->m_image; b.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
diff --git a/src/platform/vulkan/vulkan_device.h b/src/platform/vulkan/vulkan_device.h
index efc2433..85cc5ca 100644
--- a/src/platform/vulkan/vulkan_device.h
+++ b/src/platform/vulkan/vulkan_device.h
@@ -4,13 +4,13 @@
namespace Donut::RHI
{
- // Vulkan implementation of the RHI Device (MoltenVK on macOS). Owns the
+ // Vulkan implementation of the RHI Device (MoltenVK on macOS). owns the
// instance/device/swapchain and translates the RHI's baked pipelines +
// recorded command lists into native Vulkan; the geometry it draws is the
// shared SceneRenderer / BlackHoleRenderer, identical to every other backend.
auto create_vulkan_device() -> Scope<Device>;
- // Must run BEFORE glfwInit() when Vulkan is the selected API: points GLFW at
+ // must run BEFORE glfwInit() when Vulkan is the selected API: points GLFW at
// the loader the app links against (its own dlopen fails on macOS/Homebrew)
// and configures the MoltenVK ICD / layer paths.
auto vulkan_prepare_glfw() -> void;
diff --git a/src/platform/vulkan/vulkan_resources.cpp b/src/platform/vulkan/vulkan_resources.cpp
index e40ded3..ee2091b 100644
--- a/src/platform/vulkan/vulkan_resources.cpp
+++ b/src/platform/vulkan/vulkan_resources.cpp
@@ -93,7 +93,7 @@ namespace Donut::RHI
smci.addressModeU = smci.addressModeV = smci.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
vkCreateSampler(m_device, &smci, nullptr, &rt->m_sampler);
- // Optional depth attachment (for off-screen passes that need a depth test).
+ // optional depth attachment (for off-screen passes that need a depth test).
rt->m_has_depth = depth != Format::None;
VkFormat dfmt = VK_FORMAT_UNDEFINED;
if (rt->m_has_depth)
@@ -126,9 +126,9 @@ namespace Donut::RHI
return rt;
}
- // Builds an environment cubemap from an equirectangular HDRI: render the 6
+ // builds an environment cubemap from an equirectangular HDRI: render the 6
// faces with the EquirectToCubemap pipeline, then a full mip chain by
- // linear down-blits (so divergence-based LOD reads a blurred sky). Returns
+ // linear down-blits (so divergence-based LOD reads a blurred sky). returns
// a Texture owning the cube image/view/sampler.
auto VulkanDevice::create_pipeline(const PipelineDesc& desc) -> Ref<Pipeline>
@@ -190,8 +190,8 @@ namespace Donut::RHI
gpci.stageCount = 2; gpci.pStages = stages;
gpci.pVertexInputState = &vin; gpci.pInputAssemblyState = &ia; gpci.pViewportState = &vps;
gpci.pRasterizationState = &rs; gpci.pMultisampleState = &ms; gpci.pColorBlendState = &cb; gpci.pDynamicState = &dsci;
- // Resolve the target's attachment signature to a (cached) render pass.
- // Pipeline<->pass compatibility is by attachment format, so this is the
+ // resolve the target's attachment signature to a (cached) render pass.
+ // pipeline<->pass compatibility is by attachment format, so this is the
// same pass the matching swapchain / render target renders into.
VkFormat pcolor = (desc.target.color == Format::Swapchain) ? m_swapchain_format : vk_format(desc.target.color);
VkFormat pdepth = (desc.target.depth == Format::None) ? VK_FORMAT_UNDEFINED : vk_format(desc.target.depth);
diff --git a/src/platform/vulkan/vulkan_swapchain.cpp b/src/platform/vulkan/vulkan_swapchain.cpp
index 5bf2f60..cbd4512 100644
--- a/src/platform/vulkan/vulkan_swapchain.cpp
+++ b/src/platform/vulkan/vulkan_swapchain.cpp
@@ -117,8 +117,8 @@ namespace Donut::RHI
sci.imageExtent = m_extent; sci.imageArrayLayers = 1;
sci.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
sci.preTransform = caps.currentTransform; sci.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
- // FIFO is always available (vsync). With vsync off, prefer IMMEDIATE
- // (uncapped, may tear) then MAILBOX, if the surface supports them.
+ // FIFO is always there (that's vsync). with vsync off we'd rather have
+ // IMMEDIATE (uncapped, might tear) then MAILBOX, if the surface is cool with it.
VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR;
if (!m_vsync)
{
@@ -153,11 +153,11 @@ namespace Donut::RHI
return true;
}
- // A render pass for one attachment signature, created once and cached.
+ // a render pass for one attachment signature, created once and cached.
// `present` targets (the swapchain) finish PRESENT_SRC and sync on the
// colour-output stage; `sampled` targets (off-screen) finish
// SHADER_READ_ONLY and round-trip through the fragment shader so the next
- // pass can sample them. Depth (VK_FORMAT_UNDEFINED = none) is optional.
+ // pass can sample them. depth (VK_FORMAT_UNDEFINED = none) is optional.
auto VulkanDevice::get_render_pass(VkFormat color, VkFormat depth, bool present) -> VkRenderPass
{
uint64_t key = (uint64_t)(uint32_t)color
diff --git a/src/rendering/black_hole_renderer.cpp b/src/rendering/black_hole_renderer.cpp
index 283435e..2310268 100644
--- a/src/rendering/black_hole_renderer.cpp
+++ b/src/rendering/black_hole_renderer.cpp
@@ -30,7 +30,7 @@ namespace Donut
m_geo_lo = device.create_render_target(GEO_LO_W, GEO_LO_H, Format::RGBA8, Format::None, Filter::Linear);
m_geo_hi = device.create_render_target(GEO_HI_W, GEO_HI_H, Format::RGBA8, Format::None, Filter::Linear);
- // Fullscreen quad shared by the geodesic and present passes: pos.xy + uv.
+ // fullscreen quad shared by the geodesic and present passes: pos.xy + uv.
const float quad[] = {
-1.f, 1.f, 0.f, 1.f, -1.f, -1.f, 0.f, 0.f, 1.f, -1.f, 1.f, 0.f,
-1.f, 1.f, 0.f, 1.f, 1.f, -1.f, 1.f, 0.f, 1.f, 1.f, 1.f, 1.f,
@@ -42,7 +42,7 @@ namespace Donut
m_obj_ubo = device.create_buffer(BufferType::Uniform, 800);
m_sim_ubo = device.create_buffer(BufferType::Uniform, 16);
- // The hole itself is the hardcoded singularity in the shader; the Objects
+ // the hole itself is the hardcoded singularity in the shader; the Objects
// UBO carries the Scene's spheres, refilled each frame in render_geodesic.
std::vector<uint8_t> obj(800, 0); // numObjects = 0 until the first frame
m_obj_ubo->update(obj.data(), obj.size());
@@ -85,13 +85,13 @@ namespace Donut
{
fill_uniforms(view, params, objects, 0, false); // channel 0 = colour, display
- // Progressive resolution: small target while moving, large once settled.
+ // progressive resolution: small target while moving so it stays snappy, big one once it settles. so like, smooth now vs crisp later.
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)
+ // 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,
@@ -114,9 +114,9 @@ namespace Donut
cam.raw = raw ? 1 : 0;
m_cam_ubo->update(&cam, sizeof(cam));
- // Same integration budget whether moving or settled (the disk vanishes at
+ // same integration budget whether moving or settled (the disk vanishes at
// steep poses below ~15000 steps); responsiveness comes from the lower-res
- // target instead. Sourced from the UI, clamped GPU-safe.
+ // target instead. sourced from the UI, clamped GPU-safe.
constexpr int kStepCeil = 15000;
SimUBO sim{};
sim.steps_static = std::clamp(params.quality_steps, 1000, kStepCeil);
@@ -125,7 +125,7 @@ namespace Donut
sim.time = view.time;
m_sim_ubo->update(&sim, sizeof(sim));
- // Disk struct: r_in, r_out, turbulence, slab half-thickness, brightness,
+ // disk struct: r_in, r_out, turbulence, slab half-thickness, brightness,
// temperature (radii in Schwarzschild radii).
float disk[8] = {
std::max(params.disk_inner_rs, 3.0f) * SagA_rs,
@@ -138,8 +138,8 @@ namespace Donut
};
m_disk_ubo->update(disk, sizeof(disk));
- // Scene objects → the geodesic's Objects UBO (std140: numObjects@0,
- // objPosRadius[i]@16+16i, objColor[i]@272+16i). They render as spheres the
+ // 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);
diff --git a/src/rendering/black_hole_renderer.h b/src/rendering/black_hole_renderer.h
index c2cb2af..17c4254 100644
--- a/src/rendering/black_hole_renderer.h
+++ b/src/rendering/black_hole_renderer.h
@@ -7,10 +7,10 @@
namespace Donut
{
- // The black-hole view, written ONCE against the RHI. Each frame it ray-traces
+ // the black-hole view, written ONCE against the RHI. each frame it ray-traces
// the geodesic shader into an off-screen target (progressive resolution: a
// small target while the camera moves, a larger one once it settles) and then
- // upscales that target onto the swapchain. The Application owns the camera and
+ // upscales that target onto the swapchain. the Application owns the camera and
// the HDRI cubemap and passes them in.
struct GeodesicView
{
@@ -29,19 +29,19 @@ namespace Donut
auto init(RHI::Device& device) -> bool;
- // Off-screen geodesic pass (opens/closes its own render pass). Call before
+ // off-screen geodesic pass (opens/closes its own render pass). call before
// the swapchain pass; `cubemap` is the shared HDRI environment. `objects`
// are the Scene's spheres — ray-traced as lensed spheres around the hole
- // (1 scene unit = 1 Schwarzschild radius). Grid units == r_s.
+ // (1 scene unit = 1 Schwarzschild radius). grid units == r_s.
auto render_geodesic(RHI::CommandList& cmd, const GeodesicView& view,
const BlackHoleParams& params,
const std::vector<SceneObject>& objects, RHI::Texture* cubemap) -> void;
- // Upscales the geodesic target onto the swapchain (call inside the open
+ // upscales the geodesic target onto the swapchain (call inside the open
// swapchain render pass, before ImGui).
auto blit(RHI::CommandList& cmd, int fb_width, int fb_height) -> void;
- // Renders one channel (0 colour, 1 redshift g, 2 emission T, 3 impact
+ // renders one channel (0 colour, 1 redshift g, 2 emission T, 3 impact
// parameter) into an arbitrary RGBA8 target — for high-res export.
auto render_export(RHI::CommandList& cmd, RHI::RenderTarget* target,
const GeodesicView& view, const BlackHoleParams& params,
diff --git a/src/rendering/export_config.h b/src/rendering/export_config.h
index e490db6..9b91878 100644
--- a/src/rendering/export_config.h
+++ b/src/rendering/export_config.h
@@ -4,15 +4,15 @@
namespace Donut
{
- // How each channel is written:
- // Png = display image (tone-mapped colour / false-coloured observable).
- // Pfm = raw float image (actual physical values; RGB, Portable Float Map).
- // Csv = raw scalar grid (the observable's value per pixel, one row per line).
+ // how each channel is written:
+ // png = display image (tone-mapped colour / false-coloured observable).
+ // pfm = raw float image (actual physical values; RGB, Portable Float Map).
+ // csv = raw scalar grid (the observable's value per pixel, one row per line).
enum class ExportFormat { Png, Pfm, Csv };
- // What the Export workspace asks the RenderPath to write to disk: which
+ // what the Export panel asks the RenderPath to write to disk: which
// observable channels to render, at what resolution, in what format, and where.
- // Each enabled channel becomes one file.
+ // each enabled channel becomes one file.
struct ExportConfig
{
bool color = true; // colour image (tone-mapped, or linear HDR when raw)
diff --git a/src/rendering/render_api.h b/src/rendering/render_api.h
index 62742c9..224c1fa 100644
--- a/src/rendering/render_api.h
+++ b/src/rendering/render_api.h
@@ -2,8 +2,8 @@
namespace Donut
{
- // Which graphics backend the app runs on, selected once at startup (from
- // settings) before the window is created. The rendering itself goes through
+ // which graphics backend the app runs on, selected once at startup (from
+ // settings) before the window is created. the rendering itself goes through
// the RHI (rendering/rhi.h) and the shared renderers; this is only the
// backend selector the window + application branch on.
class RendererAPI
diff --git a/src/rendering/render_path.cpp b/src/rendering/render_path.cpp
index 8cb0328..dfd2937 100644
--- a/src/rendering/render_path.cpp
+++ b/src/rendering/render_path.cpp
@@ -42,15 +42,15 @@ namespace Donut
{
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).
+ // the black hole is the only view with an off-screen pass; it renders (and
+ // runs the expensive geodesic) ONLY when the view is Simulation. 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)
{
- // Projection was set by the Application this frame (shared with the gizmo).
+ // projection was set by the Application this frame (shared with the gizmo).
CameraView cv;
cv.view = scene.scene_camera.get_view_matrix();
cv.projection = scene.scene_camera.get_projection_matrix();
@@ -95,11 +95,11 @@ namespace Donut
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.
+ // backend-specific HDRI/GPU resource cleanup is the device's job (see e.g.
// the OpenGL device clearing the HDRIManager texture cache on shutdown).
}
- // Portable Float Map: a raw RGB float image (the actual physical values). Its
+ // Portable Float Map: a raw RGB float image (the actual physical values). its
// raster is bottom-up; -1.0 scale flags little-endian.
static auto write_pfm(const std::string& path, int w, int h, const std::vector<float>& rgba) -> bool
{
@@ -135,11 +135,11 @@ namespace Donut
{
if (!m_device) return 0;
const int w = std::max(cfg.width, 1), h = std::max(cfg.height, 1);
- const bool raw = cfg.format != ExportFormat::Png; // Pfm / Csv want physical values
+ const bool raw = cfg.format != ExportFormat::Png; // pfm / csv want physical values
auto target = m_device->create_render_target(
w, h, raw ? RHI::Format::RGBA32F : RHI::Format::RGBA8, RHI::Format::None, RHI::Filter::Nearest);
- // Full-quality geodesic view from the sim camera (moving = false = settled).
+ // full-quality geodesic view from the sim camera (moving = false = settled).
GeodesicView gv;
glm::vec3 pos, fwd;
if (scene.sim_camera.get_camera_mode() == CameraMode::FPS)
@@ -153,7 +153,7 @@ namespace Donut
gv.moving = false;
gv.time = 0.0f;
- std::error_code ec; std::filesystem::create_directories(cfg.directory, ec);
+ std::error_code ec; std::filesystem::create_directories(cfg.directory, ec); // lowk dc, the write below complains if it mattered
char stamp[32]; std::time_t t = std::time(nullptr);
std::strftime(stamp, sizeof(stamp), "%Y%m%d_%H%M%S", std::localtime(&t));
const char* ext = cfg.format == ExportFormat::Pfm ? "pfm" : cfg.format == ExportFormat::Csv ? "csv" : "png";
diff --git a/src/rendering/render_path.h b/src/rendering/render_path.h
index c029132..e5e8bb6 100644
--- a/src/rendering/render_path.h
+++ b/src/rendering/render_path.h
@@ -13,26 +13,26 @@ namespace Donut
{
class Scene;
- // Owns the device-side rendering: the two portable renderers, the shared HDRI
+ // owns the device-side rendering: the two portable renderers, the shared HDRI
// cubemap, and the per-frame composition (off-screen geodesic pass -> present,
- // or the scene pass), with ImGui drawn on top inside the swapchain pass. The
- // Application hands it a Scene + View each frame; it knows nothing about the UI.
+ // or the scene pass), with ImGui drawn on top inside the swapchain pass. the
+ // application hands it a Scene + View each frame; it knows nothing about the UI.
class RenderPath
{
public:
auto init(RHI::Device& device, const std::string& hdri_path) -> bool;
auto shutdown() -> void;
- // Rebuilds the environment cubemap if the path changed (device-idle).
+ // rebuilds the environment cubemap if the path changed (device-idle).
auto sync_hdri(const std::string& hdri_path) -> void;
- // Composes one frame's viewport into the swapchain command list. `moving`
+ // composes one frame's viewport into the swapchain command list. `moving`
// drives the black hole's progressive resolution; `time` animates the disk.
auto render(RHI::CommandList& cmd, Scene& scene, View view,
int fb_width, int fb_height, bool moving, float time) -> void;
- // Renders the requested export channels off-screen at cfg.width x cfg.height
- // and writes one PNG per channel. Returns the number of files written.
+ // renders the requested export channels off-screen at cfg.width x cfg.height
+ // and writes one PNG per channel. returns the number of files written.
auto export_frame(Scene& scene, const ExportConfig& cfg) -> int;
private:
diff --git a/src/rendering/rhi.h b/src/rendering/rhi.h
index 6a2042a..a92d65e 100644
--- a/src/rendering/rhi.h
+++ b/src/rendering/rhi.h
@@ -3,7 +3,7 @@
// Donut RHI (Render Hardware Interface): a small, portable GPU abstraction that
// OpenGL, Vulkan (and later Metal / D3D12) implement behind ONE interface, so the
// app's rendering — the black hole, the scene — is written ONCE on top and runs
-// on any backend. The shape is modelled on the explicit APIs (baked pipelines,
+// on any backend. the shape is modelled on the explicit APIs (baked pipelines,
// recorded command lists, explicit render targets); OpenGL emulates that, which
// is easy, whereas the reverse (making Vulkan speak GL's immediate mode) is not.
@@ -26,8 +26,8 @@ namespace Donut::RHI
D32, // 32-bit depth
};
- // The attachment signature of a render pass / target: a colour format plus an
- // optional depth format. A pipeline is compatible with any target sharing this
+ // the attachment signature of a render pass / target: a colour format plus an
+ // optional depth format. a pipeline is compatible with any target sharing this
// signature, so this is what replaces "which render pass" as an explicit value.
struct RenderTargetFormat
{
@@ -35,9 +35,9 @@ namespace Donut::RHI
Format depth = Format::None;
};
- // The window the device presents into. GLFW is the windowing layer for every
+ // the window the device presents into. GLFW is the windowing layer for every
// backend, so this carries the GLFWwindow*; each backend derives what it needs
- // (a GL context, a Vulkan surface, later a CAMetalLayer / HWND) from it. The
+ // (a GL context, a Vulkan surface, later a CAMetalLayer / HWND) from it. the
// RHI names the concept "native window" rather than baking GLFW into its API.
struct NativeWindow
{
@@ -53,23 +53,23 @@ namespace Donut::RHI
enum class CompareOp { Always, Less, LessEqual };
enum class Filter { Nearest, Linear };
- // One vertex attribute; offsets/stride are in bytes. `components` is 1..4 floats.
+ // one vertex attribute; offsets/stride are in bytes. `components` is 1..4 floats.
struct VertexAttribute { uint32_t location; uint32_t components; uint32_t offset; };
struct VertexLayout { uint32_t stride = 0; std::vector<VertexAttribute> attributes; };
- // A shader resource slot the pipeline exposes. `binding` is the set-0 binding
+ // a shader resource slot the pipeline exposes. `binding` is the set-0 binding
// index used by Vulkan; `name` is the GLSL block/sampler identifier used by the
- // OpenGL backend (GL 4.1 has no binding qualifier, so it binds by name). The app
+ // OpenGL backend (GL 4.1 has no binding qualifier, so it binds by name). the app
// declares both when building a pipeline (it knows its own shader).
enum class ResourceKind { UniformBuffer, Texture };
struct ResourceSlot { ResourceKind kind; uint32_t binding; std::string name; };
- // --- opaque GPU resources (backends subclass) --------------------------
+ // opaque GPU resources; each backend subclasses these.
class Buffer { public: virtual ~Buffer() = default; virtual auto update(const void* data, size_t size) -> void = 0; };
class Texture { public: virtual ~Texture() = default; };
class Pipeline{ public: virtual ~Pipeline() = default; };
- // An off-screen target (colour, optional depth). The swapchain is the implicit
+ // an off-screen target (colour, optional depth). the swapchain is the implicit
// default target, addressed by passing nullptr to begin_render_pass.
class RenderTarget
{
@@ -94,7 +94,7 @@ namespace Donut::RHI
RenderTargetFormat target; // attachment signature of the pass it draws into
};
- // Records draws for one frame. Obtained from Device::begin_frame (targets the
+ // records draws for one frame. obtained from Device::begin_frame (targets the
// swapchain) or created transiently for off-screen passes via the Device.
class CommandList
{
@@ -118,7 +118,7 @@ namespace Donut::RHI
virtual auto draw_indexed(uint32_t index_count) -> void = 0;
};
- // The backend root: owns the device/swapchain and creates every resource.
+ // the backend root: owns the device/swapchain and creates every resource.
class Device
{
public:
@@ -129,8 +129,8 @@ namespace Donut::RHI
virtual auto resize(int width, int height) -> void = 0;
virtual auto wait_idle() -> void = 0;
- // Present pacing: GL toggles the swap interval; Vulkan swaps the present
- // mode (FIFO vs IMMEDIATE) and rebuilds the swapchain. Default: no-op.
+ // present pacing: GL toggles the swap interval; Vulkan swaps the present
+ // mode (FIFO vs IMMEDIATE) and rebuilds the swapchain. default: no-op.
virtual auto set_vsync(bool enabled) -> void { (void)enabled; }
virtual auto create_buffer(BufferType type, size_t size, const void* data = nullptr) -> Ref<Buffer> = 0;
@@ -140,23 +140,23 @@ namespace Donut::RHI
Filter sample_filter = Filter::Linear, int mip_levels = 1) -> Ref<RenderTarget> = 0;
virtual auto create_pipeline(const PipelineDesc& desc) -> Ref<Pipeline> = 0;
- // Frame loop: begin_frame returns the frame's command list (or nullptr if
+ // frame loop: begin_frame returns the frame's command list (or nullptr if
// the frame is skipped, e.g. minimised); record one or more render passes
// into it — off-screen passes into RenderTargets first, then the swapchain
// pass (begin_render_pass(nullptr, ...)) — then end_frame submits + presents.
virtual auto begin_frame(const glm::vec4& clear) -> CommandList* = 0;
virtual auto end_frame() -> void = 0;
- // One-shot off-screen work outside the frame loop (used by the exporter):
+ // one-shot off-screen work outside the frame loop (used by the exporter):
// records a self-contained pass into a transient command list and blocks
// until the GPU finishes, so the target can be read back immediately.
virtual auto run_offscreen(const std::function<void(CommandList&)>& record) -> void = 0;
- // Reads a render target's colour back to the CPU as tightly-packed RGBA8,
- // top-left origin (out is resized to width*height*4). For export/analysis.
+ // reads a render target's colour back to the CPU as tightly-packed RGBA8,
+ // top-left origin (out is resized to width*height*4). for export/analysis.
virtual auto read_render_target(RenderTarget* target, std::vector<uint8_t>& out) -> void = 0;
- // Same, but as full-float RGBA (out resized to width*height*4 floats). Read
+ // same, but as full-float RGBA (out resized to width*height*4 floats). read
// an RGBA32F target back for raw observable export.
virtual auto read_render_target_float(RenderTarget* target, std::vector<float>& out) -> void = 0;
diff --git a/src/rendering/scene_renderer.cpp b/src/rendering/scene_renderer.cpp
index bec609c..e290445 100644
--- a/src/rendering/scene_renderer.cpp
+++ b/src/rendering/scene_renderer.cpp
@@ -43,7 +43,7 @@ namespace Donut
struct SkyboxUBO { glm::mat4 projection; glm::mat4 view; };
static_assert(sizeof(SkyboxUBO) == 128, "SkyboxUBO std140 layout mismatch");
- // The hole's event horizon (1 r_s) as a marker at the origin.
+ // the hole's event horizon (1 r_s) as a marker at the origin.
constexpr float BH_SCENE_RADIUS = SCENE_UNITS_PER_RS;
}
@@ -51,7 +51,7 @@ namespace Donut
{
m_device = &device;
- // Reference grid: line list on the XZ plane (+/-50, 1-unit cells). Grid.slang
+ // reference grid: line list on the XZ plane (+/-50, 1-unit cells). grid.slang
// scales by u_GridSize/50, so u_GridSize = 50 keeps it 1:1.
{
std::vector<glm::vec3> lines;
@@ -78,7 +78,7 @@ namespace Donut
m_grid_pipeline = device.create_pipeline(d);
}
- // Lit sphere: unit UV-sphere (pos + normal), placed/scaled per object.
+ // lit sphere: unit UV-sphere (pos + normal), placed/scaled per object.
{
std::vector<float> sv; std::vector<uint32_t> si;
const int RINGS = 24, SECTORS = 48;
@@ -115,7 +115,7 @@ namespace Donut
m_sphere_pipeline = device.create_pipeline(d);
}
- // Skybox: a unit cube (36 verts) sampling the HDRI cubemap; the vertex
+ // skybox: a unit cube (36 verts) sampling the HDRI cubemap; the vertex
// shader forces depth 1 (pos.xyww) so it sits behind all scene geometry.
{
const float cube[] = {
@@ -151,13 +151,13 @@ namespace Donut
const std::vector<SceneObject>& objects, int selected,
RHI::Texture* cubemap) -> void
{
- // Full-window viewport; flip_y lets the backend match the shared top-left
+ // full-window viewport; flip_y lets the backend match the shared top-left
// orientation (Vulkan flips via a negative-height viewport, GL is a no-op).
cmd.set_viewport(0, 0, cam.fb_width, cam.fb_height, true);
glm::mat4 vp = cam.projection * cam.view;
- // Skybox background first (depth 1, no depth test/write).
+ // skybox background first (depth 1, no depth test/write).
{
SkyboxUBO sky{};
sky.projection = cam.projection;
@@ -170,7 +170,7 @@ namespace Donut
cmd.draw(36);
}
- // Opaque spheres (write depth). One UBO per object slot avoids aliasing the
+ // opaque spheres (write depth). one UBO per object slot avoids aliasing the
// per-draw uniforms across the deferred command stream.
{
int count = std::min((int)objects.size(), MAX_OBJECTS);
@@ -202,7 +202,7 @@ namespace Donut
cmd.draw_indexed(m_sphere_index_count);
}
- // Black-hole marker: a near-black sphere at the origin (radius = r_s in
+ // black-hole marker: a near-black sphere at the origin (radius = r_s in
// scene units), so the Scene shows where the hole the Simulation renders
// sits. 1 grid unit == 1 Schwarzschild radius.
SphereUBO bh{};
@@ -223,7 +223,7 @@ namespace Donut
cmd.draw_indexed(m_sphere_index_count);
}
- // Transparent grid on top (tests depth, doesn't write).
+ // transparent grid on top (tests depth, doesn't write).
{
GridUBO g{};
g.view_projection = vp;
diff --git a/src/rendering/scene_renderer.h b/src/rendering/scene_renderer.h
index f7ff992..69ab2bc 100644
--- a/src/rendering/scene_renderer.h
+++ b/src/rendering/scene_renderer.h
@@ -7,9 +7,9 @@
namespace Donut
{
- // The world-builder scene view (skybox + lit spheres + reference grid),
+ // the world-builder scene view (skybox + lit spheres + reference grid),
// written ONCE against the RHI so it renders identically on every backend.
- // The Application owns the camera, the object list and the HDRI cubemap and
+ // the Application owns the camera, the object list and the HDRI cubemap and
// passes them in each frame; this class owns only the GPU resources (meshes,
// pipelines, per-object uniform buffers) and records the draws.
struct CameraView
@@ -24,10 +24,10 @@ namespace Donut
class SceneRenderer
{
public:
- // Builds the grid/sphere/skybox meshes and pipelines on the given device.
+ // builds the grid/sphere/skybox meshes and pipelines on the given device.
auto init(RHI::Device& device) -> bool;
- // Records the scene into the currently-open swapchain render pass. `cubemap`
+ // records the scene into the currently-open swapchain render pass. `cubemap`
// is the shared HDRI environment (sphere ambient + skybox background).
auto render(RHI::CommandList& cmd, const CameraView& cam,
const std::vector<SceneObject>& objects, int selected,
diff --git a/src/rendering/view.h b/src/rendering/view.h
index 0ac6ae0..1139676 100644
--- a/src/rendering/view.h
+++ b/src/rendering/view.h
@@ -2,12 +2,12 @@
namespace Donut
{
- // What the RenderPath draws in the viewport this frame. Each UI workspace
- // (tab) declares which one it wants, so switching tabs switches the view.
+ // what the RenderPath draws in the viewport this frame. the UI's View menu
+ // (or a layout preset) picks it; the RenderPath branches on the result.
enum class View
{
- None, // empty viewport (tabs that aren't a live view, e.g. Setup / Export)
+ None, // empty viewport (no live 3D; not currently produced by the UI)
Scene, // world-builder: grid + placed objects + skybox
- BlackHole, // the ray-traced accretion-disk simulation (only the Simulation tab)
+ BlackHole, // the ray-traced accretion-disk simulation (Simulation view only)
};
}
diff --git a/src/scene/scene.cpp b/src/scene/scene.cpp
index b8ab005..8386ca6 100644
--- a/src/scene/scene.cpp
+++ b/src/scene/scene.cpp
@@ -10,7 +10,7 @@ namespace Donut
{
Scene::Scene()
{
- // Black-hole camera: large-scale orbital viewer outside the disk.
+ // black-hole camera: large-scale orbital viewer outside the disk.
sim_camera.set_camera_mode(CameraMode::Orbital);
sim_camera.set_orbital_target(glm::vec3(0.0f));
sim_camera.set_orbital_radius(4e11); // ~31 r_s: outside the 12 r_s disk
@@ -20,7 +20,7 @@ namespace Donut
sim_camera.set_azimuth(0.0f);
sim_camera.set_elevation(1.25f);
- // Scene camera: normal-scale orbital world-builder viewer.
+ // scene camera: normal-scale orbital world-builder viewer.
scene_camera.set_camera_mode(CameraMode::Orbital);
scene_camera.set_orbital_target(glm::vec3(0.0f));
scene_camera.set_orbital_radius(30.0); // frame the hole + orbiting objects (in r_s)
@@ -46,7 +46,7 @@ namespace Donut
if (enabled == is_fps) return;
if (enabled)
{
- // Seed the fly pose from the current orbital framing so the view is continuous.
+ // seed the fly pose from the current orbital framing so the view is continuous.
glm::vec3 pos = sim_camera.get_orbital_position();
glm::vec3 fwd = glm::normalize(sim_camera.get_orbital_target() - pos);
float pitch = glm::degrees(asin(glm::clamp(fwd.y, -1.0f, 1.0f)));
diff --git a/src/scene/scene.h b/src/scene/scene.h
index 23d884f..d585a28 100644
--- a/src/scene/scene.h
+++ b/src/scene/scene.h
@@ -8,31 +8,28 @@
namespace Donut
{
- // The document: everything the app edits and renders, independent of any
- // backend or UI. Workspaces (tabs) read and mutate this; the RenderPath reads
- // it to draw. It owns the two viewpoints (cameras) as scene state, plus small
+ // the document: everything the app edits and renders, independent of any
+ // backend or UI. the UI panels read and mutate this; the RenderPath reads it
+ // to draw. it owns the two viewpoints (cameras) as scene state, plus small
// camera-framing helpers, since a viewpoint is part of the document.
class Scene
{
public:
Scene();
- // world-builder content. The default object orbits clear of the hole at the
+ // world-builder content. the default object orbits clear of the hole at the
// origin (positions are in Schwarzschild radii; see BH_SCENE_RADIUS).
std::vector<SceneObject> objects{ SceneObject{ { 18.0f, 6.0f, 0.0f }, 2.0f, { 0.85f, 0.35f, 0.2f } } };
int selected_object = 0;
- // black hole / accretion disk
BlackHoleParams black_hole;
- // environment
std::string hdri_path = "assets/hdri/hdr_blue_nebulae_1.hdr";
- // viewpoints
Camera sim_camera{ 60.0f, 16.0f / 9.0f, 0.1f, 100.0f }; // black-hole view
Camera scene_camera{ 45.0f, 16.0f / 9.0f, 0.1f, 1000.0f }; // world-builder view
- // Camera framing helpers (the sim view supports orbital + free-fly).
+ // camera framing helpers (the sim view supports orbital + free-fly).
auto reset_sim_camera() -> void;
auto set_free_fly(bool enabled) -> void;
auto is_free_fly() const -> bool { return sim_camera.get_camera_mode() == CameraMode::FPS; }
diff --git a/src/scene/scene_types.h b/src/scene/scene_types.h
index 61bea35..9ca3276 100644
--- a/src/scene/scene_types.h
+++ b/src/scene/scene_types.h
@@ -4,17 +4,17 @@
namespace Donut
{
- // Backend-agnostic scene/black-hole data shared by the Application and the
- // portable renderers (SceneRenderer, BlackHoleRenderer). The rendering itself
+ // backend-agnostic scene/black-hole data shared by the Application and the
+ // portable renderers (SceneRenderer, BlackHoleRenderer). the rendering itself
// is written once on the RHI (rendering/rhi.h); these are just the inputs.
- // The scene editor and the simulation share ONE world at this scale: this many
- // grid units == one Schwarzschild radius. The SceneRenderer draws the hole's
+ // the scene editor and the simulation share ONE world at this scale: this many
+ // grid units == one Schwarzschild radius. the SceneRenderer draws the hole's
// horizon at this radius; the BlackHoleRenderer maps scene positions into
// physical units (x SagA_rs / SCENE_UNITS_PER_RS) so placed objects line up.
constexpr float SCENE_UNITS_PER_RS = 3.0f;
- // A placeable/editable sphere in the world-builder scene view. The app owns
+ // a placeable/editable sphere in the world-builder scene view. the app owns
// the list; SceneRenderer draws it the same way on every backend.
struct SceneObject
{
@@ -23,7 +23,7 @@ namespace Donut
glm::vec3 color = { 0.85f, 0.35f, 0.2f };
};
- // Live-tunable black-hole / accretion-disk parameters. Radii are in
+ // live-tunable black-hole / accretion-disk parameters. radii are in
// Schwarzschild radii; the inner edge is clamped to the ISCO (3 r_s).
struct BlackHoleParams
{
diff --git a/src/ui/ui_layer.cpp b/src/ui/ui_layer.cpp
index 88e1b1d..dc61d2d 100644
--- a/src/ui/ui_layer.cpp
+++ b/src/ui/ui_layer.cpp
@@ -16,7 +16,7 @@
namespace Donut
{
- // Panel window titles. These are the identity DockBuilder docks against, so
+ // panel window titles. these are the identity DockBuilder docks against, so
// they must match the ImGui::Begin() titles exactly.
static const char* kOutliner = "Outliner";
static const char* kProperties = "Properties";
@@ -25,7 +25,7 @@ namespace Donut
static const char* kExport = "Export";
static const char* kStats = "Stats";
- // One-time ImGui theme: rounded, roomy, dark with a warm accretion-disk accent.
+ // one-time ImGui theme: rounded, roomy, dark with a warm accretion-disk accent.
static auto apply_donut_style() -> void
{
ImGuiStyle& s = ImGui::GetStyle();
@@ -76,13 +76,13 @@ namespace Donut
draw_menu_bar(ctx);
- // Full-viewport dock space with a pass-through centre: panels dock to the
- // edges while the render shows through the middle. Sits under the menu bar.
+ // full-viewport dock space with a pass-through centre: panels dock to the
+ // edges while the render shows through the middle. sits under the menu bar.
// ImGui owns the id (stable per viewport) and persists the layout in imgui.ini.
const ImGuiID dockspace_id = ImGui::DockSpaceOverViewport(
0, ImGui::GetMainViewport(), ImGuiDockNodeFlags_PassthruCentralNode);
- // On the first frame, seed a default layout unless imgui.ini restored one
+ // on the first frame, seed a default layout unless imgui.ini restored one
// (a restored dock tree has splits/windows, so the root node isn't empty).
if (m_first_frame)
{
@@ -143,7 +143,7 @@ namespace Donut
ImGui::EndMenu();
}
- // Right-aligned mode + FPS readout.
+ // right-aligned mode + FPS readout.
char status[64];
std::snprintf(status, sizeof(status), "%s %.0f FPS",
m_mode == Mode::Scene ? "Scene" : "Simulation", ImGui::GetIO().Framerate);
@@ -154,13 +154,13 @@ namespace Donut
ImGui::EndMainMenuBar();
}
- // Rebuild the dock tree for the current layout. Windows named but not currently
+ // rebuild the dock tree for the current layout. windows named but not currently
// visible still get a dock home here, so toggling them on lands them sensibly.
auto UILayer::build_layout(unsigned int dockspace_id) -> void
{
ImGui::DockBuilderRemoveNode(dockspace_id);
- // DockSpace is a private flag, PassthruCentralNode a public one; combine as
- // int to avoid the C++20 mixed-enum bitwise-or warning.
+ // DockSpace is a private flag and PassthruCentralNode a public one, and
+ // C++20 whines about OR-ing two different enum types, so cast to int and move on.
ImGui::DockBuilderAddNode(dockspace_id,
(int)ImGuiDockNodeFlags_DockSpace | (int)ImGuiDockNodeFlags_PassthruCentralNode);
ImGui::DockBuilderSetNodeSize(dockspace_id, ImGui::GetMainViewport()->WorkSize);
@@ -215,7 +215,7 @@ namespace Donut
ImGui::DockBuilderFinish(dockspace_id);
}
- // Apply a preset: set the centre view, choose which panels are visible, and
+ // apply a preset: set the centre view, choose which panels are visible, and
// request a dock-tree rebuild next frame.
auto UILayer::apply_layout(Layout layout) -> void
{
@@ -314,8 +314,8 @@ namespace Donut
if (m_mode == Mode::Scene)
{
- // Viewport gizmo for the selected sphere, using the scene camera
- // (its projection was set for this frame by the Application). Drawn
+ // viewport gizmo for the selected sphere, using the scene camera
+ // (its projection was set for this frame by the Application). drawn
// into the background list so it sits over the render, under panels.
ImGuizmo::SetOrthographic(false);
ImGuizmo::SetDrawlist(ImGui::GetBackgroundDrawList());
diff --git a/src/ui/ui_layer.h b/src/ui/ui_layer.h
index 15b5ff8..b913bc4 100644
--- a/src/ui/ui_layer.h
+++ b/src/ui/ui_layer.h
@@ -5,9 +5,9 @@
namespace Donut
{
- // The application's docking shell. Draws a main menu bar and a full-viewport
+ // the application's docking shell. draws a main menu bar and a full-viewport
// dock space with a pass-through centre (the live 3D render shows through the
- // middle), then a set of dockable tool panels. Ships a few default layouts
+ // middle), then a set of dockable tool panels. ships a few default layouts
// built with the DockBuilder API and lets the user rearrange, hide, or restore
// panels like a normal desktop app. draw() returns the View the RenderPath
// should draw this frame.
@@ -18,9 +18,9 @@ namespace Donut
auto draw(const UIContext& ctx) -> View;
private:
- // Which 3D view fills the pass-through centre.
+ // which 3D view fills the pass-through centre.
enum class Mode { Scene, Simulation };
- // A named default arrangement of the panels.
+ // a named default arrangement of the panels.
enum class Layout { Simulation, SceneEditing, Export };
auto draw_menu_bar(const UIContext& ctx) -> void;
@@ -39,7 +39,7 @@ namespace Donut
bool m_rebuild_layout = false; // rebuild the dock tree next frame
bool m_first_frame = true; // seed the default layout once, if no saved one
- // Panel visibility (defaults match the Simulation layout the app opens in).
+ // panel visibility (defaults match the Simulation layout the app opens in).
bool m_show_outliner = false;
bool m_show_properties = false;
bool m_show_black_hole = true;
@@ -47,13 +47,13 @@ namespace Donut
bool m_show_export = false;
bool m_show_stats = true;
- // Properties-panel gizmo op (0 = translate, 1 = scale); cast in the .cpp.
+ // properties-panel gizmo op (0 = translate, 1 = scale); cast in the .cpp.
int m_gizmo_op = 0;
- // Settings panel.
+ // settings panel.
float m_ui_scale = 1.0f;
- // Export panel.
+ // export panel.
bool m_exp_color = true, m_exp_redshift = false, m_exp_temperature = false, m_exp_impact = false;
int m_exp_resolution = 1, m_exp_format = 0;
int m_exp_written = 0; bool m_exp_reported = false;
diff --git a/src/ui/workspace.h b/src/ui/workspace.h
index 16dff2a..5beedeb 100644
--- a/src/ui/workspace.h
+++ b/src/ui/workspace.h
@@ -7,8 +7,8 @@ namespace Donut
{
class Scene;
- // App-level actions the UI can request (window/device changes it can't do
- // itself). The Application implements this — it owns the window and device.
+ // app-level actions the UI can request (window/device changes it can't do
+ // itself). the Application implements this — it owns the window and device.
struct AppActions
{
virtual ~AppActions() = default;
@@ -18,12 +18,12 @@ namespace Donut
virtual auto set_ui_scale(float scale) -> void = 0;
virtual auto get_window_size(int& w, int& h) const -> void = 0;
virtual auto is_fullscreen() const -> bool = 0;
- // Renders the requested channels off-screen and writes files; returns the
+ // renders the requested channels off-screen and writes files; returns the
// number written (0 on failure).
virtual auto export_frame(const ExportConfig& cfg) -> int = 0;
};
- // What the UI panels get each frame. `scene` is mutable — panels edit the
+ // what the UI panels get each frame. `scene` is mutable — panels edit the
// document through it; `actions` performs app-level changes.
struct UIContext
{