Introduction
An individual project, the final project for Northeastern University CS 5310 Computer Graphics class. A black hole rendered in OpenGL. You can press arrow buttons and your mouse to move your camera.
Reference
Download
There's a macOS build in the repository that is ./project. You can also build this project locally on macOS by python3 build.py, but running or building this project requires an OpenGL 3.3+ and all dependencies environment.
Features
Frame Buffer and Coordinate Transform
In order to apply the light marching feature to this project, I first rendered the background(including a starry skybox and two suns) into a frame buffer. All the post effects are rendered on top of this frame buffer.
To realize the light marching algorithm (details https://zhuanlan.zhihu.com/p/105531637, a Chinese website), I need to transfer the frame buffer pixels coordinate from Screen to World. I realized this by multiplying the inversed projection and view matrix to the pixel coordinate(mapped into [-1, 1]). The detailed algorithm is below:
// Map pixel coordinate to [-1, 1]
vec2 uv = v_texCoord * 2.0f - 1.0f;
// Transfer pixels from screen coordinate to world coordinate
vec3 sd = vec3(uv.x, uv.y, -1.0f);
vec4 ray_clip = vec4(sd, 1.0f);
vec4 ray_eye = inverse(projection) * ray_clip;
vec4 ray_world = inverse(view) * ray_eye;
if(ray_world.w != 0.0f){
ray_world.x = ray_world.x / ray_world.w;
ray_world.y = ray_world.y / ray_world.w;
ray_world.z = ray_world.z / ray_world.w;
}
sd = vec3(ray_world.x, ray_world.y, ray_world.z);
Gravity Lens
Use the physical formulas to bend marching light fragments. All pixels within the event horizon will be rendered as black to simulate the black hole. Other bent lights will hit the frame buffer pixels and return the bent pixel color value, which will realize the gravity lens effect.
Photon Sphere
This is a physical phenomenon that which photons will accrete around the event horizon of the black hole and will make it brighter than the background. In my shader, to simulate this phenomenon, basically, I applied a formula like
Brightness = 1/(Distance to blackhole)^2
To get the pixels around the event horizon brighter.
Accretion Disc
An accretion disk is stardusts rotating around the black hole. In order to simulate this effect, I applied a Signed Distance Field to represent the accretion disk area:
// Whether to show an accretion disk
float torus_sdf( vec3 p, vec2 t )
{
vec2 q = vec2(length(p.xz)-t.x,p.y);
return length(q)-t.y;
}
Then use some pixel color calculations to show this area. On top of that, I applied a white noise texture to make the accretion disk more realistic.
Relativistic Jet
A relativistic jet is periodically emitted high-speed particles from the black hole. This part is much easier, basically, a post effect that added two light column that shows up periodically, its proximal part is blue and the distal part is red (due to different energy).
Comments