Skip to content

Make BlackHole3D run on macOS via a fragment-shader fallback - #46

Open
zealair12 wants to merge 5 commits into
kavan010:mainfrom
zealair12:m4-fragment-port
Open

Make BlackHole3D run on macOS via a fragment-shader fallback#46
zealair12 wants to merge 5 commits into
kavan010:mainfrom
zealair12:m4-fragment-port

Conversation

@zealair12

Copy link
Copy Markdown

Hi Kavan,

I watched the full video and thought it was really cool, since it's also something I'd always wanted to build myself.

I tried to run the project, but I'm on a Mac, and BlackHole3D exited immediately at startup. The cause is that macOS only supports OpenGL up to version 4.1, while geodesic.comp is a compute shader, which requires OpenGL 4.3. Apple never shipped that version, so the shader cannot compile on any Mac, regardless of hardware.

This PR makes the project run on macOS without changing behavior on other platforms:

  • At startup the program checks whether compute shaders are available. On Windows and Linux it uses geodesic.comp exactly as before. On macOS it runs the same ray calculations in a fragment shader (geodesic.frag), drawn into the same low-resolution texture.
  • macOS terminates GPU work that takes too long in a single batch. The fragment version therefore draws each frame in ten horizontal strips, and uses larger integration steps far from the black hole where light barely bends. On an M4 Pro a frame takes about 90 ms, and the image differs from the fixed-step version by only a few pixels out of 30,000.
  • geodesic.comp is restored to #version 430 (declared as 410 it fails to compile everywhere, since compute shaders require 4.3). The camera buffer's boolean flag is now an int to match the memory layout the shader expects. The viewport is sized from the framebuffer rather than the window, which fixes rendering on high-DPI displays.

I also added a macOS section to the README with Homebrew setup steps, measured performance, and a screenshot from my machine. The screenshot is from a test on a MacBook Pro (M4 Pro, 24 GB RAM), macOS 26.5

BlackHole3D running on macOS (M4 Pro)

- Changed OpenGL context version from 4.3 to 4.1 for better macOS support
- Added GLFW_OPENGL_FORWARD_COMPAT hint for macOS compatibility
- Updated all shader versions to 410 for consistency (geodesic.comp, grid.vert, grid.frag)
- Added helpful comments about shader file requirements
- Added black_hole binary to .gitignore
- Fixed code formatting issues
macOS caps OpenGL at 4.1, so the GL 4.3 compute shader (geodesic.comp)
can never compile there and the app exited at startup. Detect compute
support at runtime: platforms with GL 4.3+ keep using geodesic.comp
unchanged; otherwise render the identical geodesic integration with a
fragment shader (geodesic.frag) into the low-res texture via an FBO.

Also restore geodesic.comp to #version 430 (compute shaders require
GL 4.3, so declaring 410 broke it on Windows/Linux too) and fix the
camera UBO 'moving' flag: C++ bool is 1 byte but std140 bool is 4,
so the shader could read garbage padding bytes.
The single fullscreen geodesic pass took multiple seconds of GPU time
per frame, so macOS's GPU watchdog killed the command buffer (GPU Hang
Error) and eventually aborted the app. Two changes fix this:

- Split the pass into 10 horizontal scissor tiles with a glFlush between
  each, so no single command buffer approaches the watchdog limit.
- Use adaptive integration steps: D_LAMBDA near the event horizon where
  lensing accuracy matters, scaling up to 50x in the nearly-flat far
  field, and treat rays past 2e12 m (beyond max camera zoom-out) as
  escaped instead of integrating toward 1e30.

Frame time on an M4 Pro drops to ~90 ms with no GPU errors; the
rendered image is within a few pixels of the fixed-step version.
At elevation pi/2 the camera begins exactly level with the accretion
disk and inside its outer radius, so the first frame is a full-screen
wall of disk. Tilt the default elevation to 1.3 rad so the app opens
on the classic lensed view.
Size the on-screen viewport from glfwGetFramebufferSize instead of the
window size: on HiDPI displays the framebuffer is larger than the
window, and an 800x600 viewport only covered the bottom-left quarter.

Add a macOS section to the README with Homebrew setup, the fragment-
shader fallback explanation, measured performance on an M4 Pro, and a
screenshot rendered by the app.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant