• Advertisement
Sign in to follow this  

Starfield with 3D points: ideas on how to create light effect around the stars in a shader

This topic is 705 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi there, my first post in this great community after reading it for years. I am currently working on a solar system simulator for an educational game I was hired to work on.

 

For the background starfield, I have to use real 3D points (not merely painted on a skybox), since the user can eventually zoom in to them without loading types. I have implemented that in the GPU via shaders, for better performance. Now, I am starting to move towards graphical enhancements to improve the immersion of the user.

 

The effect I am looking after is the one seen in the picture attached to this post. I am talking about the lighter/brighter tones that the dark sky gets around the stars, specially intense where the stars are brighter or more concentrated. It looks like a very subtle bloom effect.

 

What I would like to know from you experts is how could I achieve a similar effect, in a way as performant as possible (again, consider that the stars are real objects in my case, not part of a texture). Conceptual ideas, suggestions, code examples or references are all helpful at this point.

 

Share this post


Link to post
Share on other sites
Advertisement

Some kind of bloom effect would probably help get nearer what you want.

I think if you did that coupled with a fractal noise you could be well on the way.

 

So use a down-sampled version of the image to blur it based on light intensity, then overlay that onto the original image. I would also use that blur texture as a alpha map for some kind of noise (such as fractal) to get that "cloudy" look. Depending on how you built the initial image you may need to think about how a noise texture might swim as the camera moves and you will need to fix that, i.e. maybe sample a cube map there, just guessing at this point :D

Share this post


Link to post
Share on other sites

hm, if they are indeed objects you could just use point-sprites using a small texture with a dot and some blur.
probably depends on the amount of points if sprites or a render-to-texture-and-bloom-it-approach would be more performant.

Edited by ninnghazad

Share this post


Link to post
Share on other sites

Yeah I would try point sprites / small quads too.

 

I was coincidentally thinking about a sky renderer recently and one idea I came up with was:

  • Import a star catalogue with coordinates, intensity values.
  • Convert coordinates into 3D directions in the game-world's coordinate system.
  • Create a cube-map of sufficient resolution, fill with black pixels. Make it a floating point texture for simplicity (not required though).
  • For each star, find the texel in the cubemap in the direction for this star.
    At that location, write the exact (x,y,z) direction into RGB, and the intensity in Alpha.

At runtime, to render the sky:

  • For each background pixel, ray get the direction away from the camera.
    Rotate this into the coordinate system that was used to generate the cubemap (e.g. if on the surface of earth, this will vary with time of day / month / location).
  • Fetch the N closest cubemap texels to this direction. If you use N=1, this is a single point-filtered texture fetch.
  • For each texel, calculate the angular difference between the ray's direction and the stored XYZ value (dot product). Define a gaussian centred on this XYZ direction, with a width defined by the star's intensity (texel Alpha value). Compute where the view ray intersects this distribution. Add that value (scaled by the star's intensity) to this view-ray's colour.

This should give a guassian-blurred starfield (similar to a post-process bloom, but with better anti-aliasing) without any of the blocky/pixely texture artifacts you'd get from a low-resolution cubemap. The downside is that with a low-res texture, you can't have two stars appear close together... The cubemap simply has to be high enough resolution that no two stars try to store themselves in the same cubemap texel... If that does happen, then just store the brightest star only. You can also adjust cost/quality by increasing/decreasing the width of your guassian distribution, though as you make it wider, you have to increase the N value as well.

 

As an extension, use an R8G8B8A8 cubemap, storing the direction in Crytek BFN format, and the intensity in some kind of logarithmic encoding (or another way to compress this data smaller - e.g. 2D delta from the texel direction and a 16bit intensity). Also, instead of intersecting a ray with the Gaussian curve, integrate the intersection of a screen-pixel sized cone (defined by the pixel's solid angle) with the star's guassian distribution, which will give much better / anti-aliased results when zoomed out. Can combine with another background cubemap for general starfield glow (milky way shape), star colour tints / etc...

Share this post


Link to post
Share on other sites

Thank you all for such insightful replies. So a few follow-ups:

 

(...) So use a down-sampled version of the image to blur it based on light intensity, then overlay that onto the original image. I would also use that blur texture as a alpha map for some kind of noise (such as fractal) to get that "cloudy" look (...)

 

 

This can be done by some kind of blur effect as described here in this NVidia papers

http://http.developer.nvidia.com/GPUGems/gpugems_ch21.html (...)

Just to double-check, you both are talking about using applying blur or glow in a screen shader, am I correct in such assumption? I mean, considering that each star is a different object, I imagine what you are suggesting is that I use the final screen-image that is about to be rendered and apply a post-effect on it.
 

hm, if they are indeed objects you could just use point-sprites using a small texture with a dot and some blur.
probably depends on the amount of points if sprites or a render-to-texture-and-bloom-it-approach would be more performant.

I thought of using a bigger sprite with a bigger radius for the "light gradient effect" of each star. Besides any performance considerations (like increasing quite a lot the area with transparency to be rendered), the main problem I see in that solution is that the only area of surrounding light that gets magnified when two stars are close to each other is the intersection between the circles of each star - which is not quite realistic and worse, is noticeable  (did you get what I mean about this? Tell me if I wasn't clear enough on the description of this problem).

 

Yeah I would try point sprites / small quads too.

 

I was coincidentally thinking about a sky renderer recently and one idea I came up with was: (...)

 

Very detailed and interesting suggestion! Many thanks for it. Of course, I didn't grasp on everything you said, but I think you gave some ideas. However, let me ask you this. First is a broad one: so what you are suggesting is in essence that I actually paint the projection of each star object on a cubemap texture during each render? Second is practical: I didn't get where the "angular difference between the ray's direction and the stored XYZ value" is used since the description of the technique that comes after that part does not mention it anymore. I mean, as far as I understood, it's completely possible to define a gaussian distribution centered at the XYZ ray of the star with variance = intensity without needing the information given by the angular difference between view ray and the stored XYZ. Third is conceptual: why is the view ray important in calculating the gaussian-blur of the stars? I mean, so the blur would become dependent on the angle trough which the user looks? Last and fourth is both conceptual and practical: I didn't get how in that technique one star would also affect each other's light-blur area.
 

Again, many thanks for all your generous ideas!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement