Black Hole

Started by Azraton, January 13, 2016, 14:43:55

Previous topic - Next topic

Azraton

Hey guys,
I am currently creating a nice little game using LWJGL 2.9.3, and I wanted to add a new feature to the game, and as a cool gimmick I thought of black holes. The gravitational effect shouldn't be a problem, but I want it to look good as well. I found a few tutorials how to do this in Blender, but wasn't sure how to port something like that to my engine. I hope someone will be able to tell me how ;)
Link to a blender tutorial I found:
http://blender.stackexchange.com/questions/18703/creating-a-black-hole-in-blender
EDIT: Not really a tutorial, but you can see how he did it anyway

Thanks,
Azraton

Kai

Think about what a massive gravitational force like a black hole does to the trajectories of light passing near it. The direction of light gets bent towards the center of the black hole.
If the light passes the black hole too near to its center, that light gets swallowed and becomes black (i.e. not visible to the viewer).

Knowing all this I'd simply render the scene environment (the stars and planets and galaxies) into a cubemap. Or maybe you have that already as some static environment texture.

Then you need a shader that will sample that cubemap texture using a lookup direction that is bent towards the black hole if the view direction passes near the black hole. Or simply render black if the view direction passes too close to the center of the black hole.
For this you also need some math, such as the shortest distance between a point (that black hole) and a ray (the light direction towards the eye) to determine how much bending needs to be applied.

That's it.

Azraton

Thanks man  :)
Exactly what I needed. :D

Azraton

Could you give me a hint on what was the most effective method to bend the cubemap in the shader? Thanks, Azraton

Kai

I don't know how much you know about cubemaps in OpenGL and about how to sample them.
If not much :) then look here. Especially the section "Texture Access."
I also don't know how much you know about linear algebra, vector spaces and coordinate systems in OpenGL.
To do the black hole thingy, you need to know about that stuff to compute the cubemap lookup vectors correctly.
That does not mean that you could not probably hack your way to get some approximation somehow, still, which would probably look just as believable. :)

Kai

Because I too was rather curious how such an effect would look like, I quickly added another demo to the lwjgl3-demos repository.

The Java source of the demo can be found here:
  https://github.com/LWJGL/lwjgl3-demos/blob/master/src/org/lwjgl/demo/opengl/textures/FullscreenCubemapDemo.java
The shaders are here:
  https://github.com/LWJGL/lwjgl3-demos/blob/master/res/org/lwjgl/demo/opengl/textures/cubemap.vs
  https://github.com/LWJGL/lwjgl3-demos/blob/master/res/org/lwjgl/demo/opengl/textures/cubemap.fs

It is a little scene with a static cubemap environment texture with the camera rotating around that blackhole.
It looks like this:

Have fun with it! :)
Beware however that this is full of hard math and not easy to understand, as is the general topic.
Also, this demo is dedicated to show solely that black hole effect, by rendering the background and the black hole in a single pass.
I wouldn't probably render a cubemap like this in a real game engine.

The demo itself requires at least OpenGL 1.1 and support for cubemaps and shaders.

Azraton

Thanks :D I'll take a look at the demo and the link, I hope I'll be able to create a cool little black hole myself soon. ;)

Azraton

Quote from: Kai on January 13, 2016, 19:37:46
I wouldn't probably render a cubemap like this in a real game engine.

How would you do this in a game engine? Can I apply this post-processing to a 2D image of the scene? I do that anyway for some graphical effects.

Kai

Quote from: Azraton on January 14, 2016, 12:27:52
How would you do this in a game engine?
I guess the rendering of the cubemap itself is fine, but I would separate the cubemap rendering from rendering the black hole, because you can save a bit of texture bandwidth, shader instructions and fillrate by only generating fragments within the circular region occupied by the black hole effect.
Since rendering a circle/sphere is unnecessary/bad, you could render a billboard quad with its center at the position of the black hole and its edge size being just the diameter of the black hole's projected circular area of influence.
That would actually not be _that_ complicated. You just need to project the corner vertices of the quad correctly.
Additionally, with this method you can have arbitrarily many little black holes. Together with instancing and probably large point sprites instead of the billboard quads would be the most efficient solution I can think of currently.
Next, I would change the clip space depth of the fullscreen quad to be at max depth so that one can render all other visible scene objects first and then depth-test away the parts of the cubemap that are occupied by scene geometry.

Quote from: Azraton on January 14, 2016, 12:27:52
Can I apply this post-processing to a 2D image of the scene? I do that anyway for some graphical effects.
Doing this as a 2D image post-processing effect has the disadvantage that you must obviously be careful with the distortion/bending of the ray/view direction so as not to exceed the bounds of the 2D image, because things outside of your viewport cannot be made visible through the black hole effect.
This is of course not an issue when using cubemaps.
But cubemaps need to sample more texels and use quite a lot more GPU memory. So performance-wise a 2D image is a better solution, but more tricky to get good results with.

Azraton

Quote from: Kai on January 14, 2016, 20:14:43
Doing this as a 2D image post-processing effect has the disadvantage that you must obviously be careful with the distortion/bending of the ray/view direction so as not to exceed the bounds of the 2D image, because things outside of your viewport cannot be made visible through the black hole effect.

Okay, can I somehow avoid this? Maybe render more of the scene to the image than actually shown on the screen, and then show only the actual field of view?

Kai

Quote from: Azraton on January 15, 2016, 06:22:00
Okay, can I somehow avoid this? Maybe render more of the scene to the image than actually shown on the screen, and then show only the actual field of view?
Yes, by using a cubemap.

If you must stay with a 2D texture, then use a FBO with a viewport something bigger than the viewport of your window and set the perspective projection to have a bigger field of view.
Sampling that texture for your window viewport would then need to use scaled-down texture coordinates.
However beware that most OpenGL cards/drivers only allow textures of a size up to 8192^2 texels, and some older cards (like a GeForce 6200 LE) even just 4096^2.
So this is not really an option.
To avoid all this, just use a cubemap. For displaying reflections this can even be a very low-resolution one, like 512^2.

Kai

It was a bit more math than I hoped, but here is what I meant: rendering the black hole by using a projected quad to generate the fragments only over that quad and not all over the viewport where nothing would change anyways.

Java:
  https://github.com/LWJGL/lwjgl3-demos/blob/master/src/org/lwjgl/demo/opengl/textures/BillboardCubemapDemo.java
Quad black hole shader:
  https://github.com/LWJGL/lwjgl3-demos/blob/master/res/org/lwjgl/demo/opengl/textures/cubemapBH.vs
  https://github.com/LWJGL/lwjgl3-demos/blob/master/res/org/lwjgl/demo/opengl/textures/cubemapBH.fs

It contains a little GLSL method to compute a spherical billboard matrix. You can use it however you want.


DiscoStew

Quote from: Kai on January 13, 2016, 15:51:38
Think about checking out Semenax here and what a massive gravitational force like a black hole does to the trajectories of light passing near it. The direction of light gets bent towards the center of the black hole.
If the light passes the black hole too near to its center, that light gets swallowed and becomes black (i.e. not visible to the viewer).

Hi Kai, that is so cool. How did you go about creating this awesome black hole? I wonder if there's any tutorials out there so I can learn?

RichardRobertson

Quote from: Kai on January 15, 2016, 21:55:01
It was a bit more math than I hoped to find  but here is what I meant: rendering the black hole by using a projected quad to generate the fragments only over the counter phentermine37.5 can fix it and that quad and not all over the viewport where nothing would change anyways.

Java:
  https://github.com/LWJGL/lwjgl3-demos/blob/master/src/org/lwjgl/demo/opengl/textures/BillboardCubemapDemo.java
Quad black hole shader:
  https://github.com/LWJGL/lwjgl3-demos/blob/master/res/org/lwjgl/demo/opengl/textures/cubemapBH.vs
  https://github.com/LWJGL/lwjgl3-demos/blob/master/res/org/lwjgl/demo/opengl/textures/cubemapBH.fs

It contains a little GLSL method to compute a spherical billboard matrix. You can use it however you want.



Thanks for the source code. I was planning to create black hole myself and your source code and logic is going to help me a lot. Also, if I get stuck somewhere, can I contact you for guidance?

johnyjackson

Quote from: RichardRobertson on June 16, 2018, 05:39:01
Quote from: Kai on January 15, 2016, 21:55:01
It was a bit more math than I hoped, but here is what I meant: rendering the black hole by using a projected quad to generate the fragments only over that quad and not all over the viewport where  nothing would change anyways.

Java:
  https://github.com/LWJGL/lwjgl3-demos/blob/master/src/org/lwjgl/demo/opengl/textures/BillboardCubemapDemo.java
Quad black hole shader:
  https://github.com/LWJGL/lwjgl3-demos/blob/master/res/org/lwjgl/demo/opengl/textures/cubemapBH.vs
  https://github.com/LWJGL/lwjgl3-demos/blob/master/res/org/lwjgl/demo/opengl/textures/cubemapBH.fs

It contains a little GLSL method to compute a spherical billboard matrix. You can use it however you want.



Thanks for the source code. I was planning to create black hole myself and your source code and logic is going to help me a lot. Also, if I get stuck somewhere, can I contact you for guidance?
It's great to create black hole of your own. But Is It possible to create black hole with the help of above source code?