yahiko00

2D Procedural Generated 2D Starfield & Planet

Recommended Posts

yahiko00    287

Hi,

Not sure to post at the right place, if not, please forgive me...

For a game project I am working on, I would like to implement a 2D starfield as a background.

I do not want to deal with static tiles, since I plan to slowly animate the starfield. So, I am trying to figure out how to generate a random starfield for the entire map.

I feel that using a uniform distribution for the stars will not do the trick. Instead I would like something similar to the screenshot below, taken from the game Star Wars: Empire At War (all credits to Lucasfilm, Disney, and so on...).

595256e18d767_StarWarsEmpireatWar06_27.2

Is there someone who could have an idea of a distribution which could result in such a starfield?

Any insight would be appreciated ;)

Edited by yahiko00
Changed topic title and added tags

Share this post


Link to post
Share on other sites
sergamer1    821

Hi there,

I thought I should start with the obvious suggestion;  have you tried simply a random distribution of points?  Remember that stars do not all have uniform brightnesses so 2d random positions plus a random brightness factor would probably give you a nice effect I would have thought (and pretty simple to do).

 

Also, what do you mean by 'slowly animate'?  I don't know the game in question, but do you mean as you move around the x-y plane and you see the stars in the background move with some sort of parallax effect?  Because if that's the case, my random suggestion above still works but in that case, the brighter the star, the closer it is so the movement parallax will be bigger and pretty easy to generate I think.  Or maybe I'm thinking of something completely different to you :-)

Share this post


Link to post
Share on other sites
sergamer1    821

Sorry, I just realised you did say the word 'random', missed that one!  :-) .  But actually my point about the brightnesses still stands.  A 'random' distribution of points does not actually make a 'uniform' distribution of points.  It follows a Poisson distribution with clumps and voids naturally forming.  Adding the brightness factor I think will accentuate this and it will be a pretty decent effect I feel.

 

Of course, if that was not good enough, you could do some other things, like create some density function across the sky.  Let's say it was sinusoidal (yes, that's crap but just for example).  Then you can use something called Monte-Carlo rejection sampling.  You get some (on average) underlying density field plus an element of randomness on top.  But I think you should try the simple random x/y/brightness approach first.  I think you'll find it is better than you might first think.

Share this post


Link to post
Share on other sites
yahiko00    287

Thanks for your kinds replies @sergamer1! :)

It makes me think that years ago, I have developped a small PRNG visualizer: http://yahiko.co.nf/RNGVisualizer/ (see second row)

And that is quite true that the result is better than I expected when I opened this thread this afternoon.

Playing with the brightness would certainly improve the result too.

When I said "slowly animate", I am not still sure of what to get, but it could be nice if the starfield is not just a static picture in the background. A two-layer starfield with a parallax effect could be interesting indeed.

Also, you mentioned in your second post "density function accross the sky". Could you please explain this?

Edited by yahiko00

Share this post


Link to post
Share on other sites
sergamer1    821
50 minutes ago, yahiko00 said:

When I said "slowly animate", I am not still sure of what to get, but it could be nice if the starfield is not just a static picture in the background. A two-layer starfield with a parallax effect could be interesting indeed.

Yes, I was thinking more a 3 or 4 layer parallax starfield, but that's your preference of course.  The key to making it work is the further the starfield, the slower it moves in parallax, the more stars it has and the dimmer those stars are.  This should in principle be quite easy to do I think.

 

52 minutes ago, yahiko00 said:

Also, you mentioned in your second post "density function accross the sky". Could you please explain this?

If you have a uniform (on average) density of stars, then the simple random sampling works.  But let's say you want some structure, like the spiral arms of the galaxy, or perhaps some dense star clusters spread around?  Then you can either tabulate this or make a function of this density field of stars.  And then you perform the Monte-Carlo rejection sampling over the density field, and abracadabra, you have a more interesting density field :-) .  Other possibilities include perhaps Perlin noise or some other combination of simple density modes.  However, like I said, I think you'll find the uniform random (with different brightness parallax layers) to be more than adequate!  ;-)

Share this post


Link to post
Share on other sites
yahiko00    287

I've been quite busy this week, so I haven't been able to really work on this project.

However, I've succeeded to implement a first experiment of a 2-layer starfield as suggested. I've used TypeScript and Phaser.

starfield.gif.a0b1c84afb4205aa14ee186005c7a610.gif

For information, I've implemented a cache where I draw on a hidden canvas before displaying it.

As a begining, I find this result quite promising. A uniform distribution is not an issue after all since stars seem quite scattered with some voids and clusters.

I will try to improve this demonstration a little bit by using HSL colors instead of RGB, and chosing colors according to a gaussian distribution and not a uniform distribution, which is not realistic in such a case.

As a roadmap, I would like to implement some special objects like comets and supernovae. Also, I would be interested to have some hints to produce some gas clouds as we can seen below:

s-l300.jpg   ff6a19a808dc5888a0c99c7810c0776a.jpg

Thanks! :)

Share this post


Link to post
Share on other sites
sergamer1    821
16 hours ago, yahiko00 said:

As a begining, I find this result quite promising. A uniform distribution is not an issue after all since stars seem quite scattered with some voids and clusters.

Yes, I was pretty confident the simple prescription would still look pretty decent and not too uniform so glad to see I was not talking rubbish!  ;-)   Happy you're making progress on it anyway.

 

16 hours ago, yahiko00 said:

I will try to improve this demonstration a little bit by using HSL colors instead of RGB, and chosing colors according to a gaussian distribution and not a uniform distribution, which is not realistic in such a case.

Sure, I had a couple of things to say about the colours.  Although some are fine, some are not very 'star-like' should we say :-)  Stars typically go through a range of colours like brown-red-orange-yellow-green(ish)-blue in order of increasing mass (i.e. brown dwarfs are the smallest that are visible and blue supergiants are the largest ones you can see before they go supernova anyway)   In principle, other colours are there too but these are the typical ones.  The other thing is they seem to fade in-and-out, almost like twinkling in the night's sky.  Except star's don't twinkle in space :-)  (because it's an effect you get only with an atmosphere).  Of course, I am just saying what is realistic whereas maybe you just want what looks best ;-)

 

16 hours ago, yahiko00 said:

As a roadmap, I would like to implement some special objects like comets and supernovae. Also, I would be interested to have some hints to produce some gas clouds as we can seen below:

Okay, gas clouds are a whole other ball-game!  Their form is highly irregular and not described by some simple equation (unfortunately).  When astrophysicists try to generate such density fields, they usually try and produce some kind of fractal density field (i.e. with fractal dimension less than 3 so it has holes and other structures).   Maybe you should consider something like Perlin noise (https://en.wikipedia.org/wiki/Perlin_noise) since you'll presumably only be generating in 2d.  Many people generate irregular shaped profiles, such as mountain ranges or islands, using Perlin noise, and I think this the route to take.  I've seen other people try stuff like this (i.e. interstellar gas clouds) in the past, although I'm not sure what method they used.  If I find something that's useful, I'll post it here!  :-)

Share this post


Link to post
Share on other sites
yahiko00    287

Hello,

I'm back with some news about my project. I've brought some improvements to the star field generation.

Colors now use HSL instead of RGB. Also, I choose them over a Gaussian distribution giving the star field a more realistic aspect. All stars of a given layer now share a same "tone".

I've encountered some issues with Phaser which seemed to leak into memory above 700 stars --- and drew me lines instead of circles. :D

So, I changed to Pixi.js which is hopefully quite close to Phaser and seems more reliable since there is no more glitches for a large number of stars.

To give an overall better aspect, I've applied a blur filter to the whole scene. At first, I've tried to blur stars one by one but this is really inefficient...

You can see below a static overview. The animated GIF was too big to upload ^_^

starfield20170708.png.126fbb4248c9536f4bfab9dbc7421d4b.png

From a performance point of view, instead of drawing and redrawing stars each frame, I turned them into sprites. This improved dramatically my FPS.

I've also added a quick and dirty GUI on the right side in order to be able to play along with various parameters. I've uploaded an online version here: http://yahiko.developpez.com/apps/Starfield/

For the time being, I hadn't got the time to implement comets, supernovae or gas clouds, but this is still in the roadmap. I'll let you know. :ph34r:

Share this post


Link to post
Share on other sites
taylorswift    7

I think you are approaching the star coloring the wrong way. In space (i.e., not from the atmosphere), all stars are white. You only see faint color tinges at the edges of the stars as they glow, see this hubble image:

m16_cfa.jpg.216f13b164f7640cc1d4548a5b8f3f8c.jpg

Since you said you’re using sprites, consider pre-rendering, say 256 stars that look like the ones in the picture varying along a heat gradient

Color_temperature_black_body_radiation_logarithmic_kelvins.svg.png.63e26f785c577e558549a35b9924a741.png

instead of just using round colored dots. The heat gradient is not gaussian, the true distribution is something astrophysicists have been measuring for god knows how long, but i’d be willing to bet that linear would look more realistic than gaussian.

Then rendering the stars is as easy as picking a random star from your 256 stars.

Morgan-Keenan_spectral_classification.thumb.png.c8a6edf6f121a3071c0edc1c60fa48b2.png

P.S., you’re confusing star distance with red shift. Closer stars aren’t any more prone to being yellow/red than more distant stars. Red shift comes from star velocity relative to the viewer; if anything more distant stars are slightly redder than nearer stars from universe expansion.

Edited by taylorswift

Share this post


Link to post
Share on other sites
JTippetts    12970

You haven't said much about your platform (and I don't know very much about HTML5 platforms in general) but if you have access to shader technology, you can often accomplish this kind of thing with quite decent performance. Just search at ShaderToy for star fields, and you can see stuff like this: https://www.shadertoy.com/view/XlfGRj

Granted, deciphering what's going on in some shaders is kinda tough, but you ought to be able to at least pull out some things you can use to your own benefit.

Share this post


Link to post
Share on other sites
yahiko00    287

I've used a fragment shader to blur each of my circles but it seemed quite inefficient.

Right now I am working on a simplex noise 2D fragment shader to generate gas clouds, but I am not an expert of shaders in general to be honest.

I've clicked on your link, and this is really, really impressive. I will definitely investigate the really short code of this visually astounding shader :)

You made my day!

Edited by yahiko00

Share this post


Link to post
Share on other sites
sergamer1    821
21 hours ago, yahiko00 said:

You can see below a static overview. The animated GIF was too big to upload ^_^

Yes, that seems like really nice progress :-) .  I have a few comments that maybe will help improve.  A comment above about stars appearing more white in space is partly true yes in the sense they have a broad spectrum so the 'redness' or 'blueness' is not so apparent.  So making them more white helps with the 'realism' (at least with the nearest stars; see my final comment below).

Second, it feels like there are too many stars in the nearest plane and you can see they all move at the same speed a little too clearly which breaks the illusion slightly.  I would perhaps reduce the density of stars here (although the distant ones seem fine for this).  

 

9 hours ago, taylorswift said:

P.S., you’re confusing star distance with red shift. Closer stars aren’t any more prone to being yellow/red than more distant stars. Red shift comes from star velocity relative to the viewer; if anything more distant stars are slightly redder than nearer stars from universe expansion.

Actually, I wanted to say something about this also.  This is incorrect but for the wrong reasons.  It's true that there is redshift due to the expansion of the Universe but we can't actually see stars in other galaxies with the naked eye so all visible stars are in our own Galaxy.  However, there is an effect known as interstellar reddening where gas/dust in the interstellar medium (ISM) absorbs preferentially blue light from distant stars making them appear redder.  And since more distant stars have more ISM between us and it, they appear redder.  This is a quite famous example OSC_Astro_20_03_B68IR.jpg

where you can see an obvious gas cloud making stars redder.  This is obviously a very discrete blob of gas, but this happens in many directions on large-scales so I would make the near stars white/yellow/blue (depending on mass) and the distant stars more and more red if you wish to mimic this kind of Galactic-fog effect :-)

Share this post


Link to post
Share on other sites
yahiko00    287

As a recall, I have implemented a GUI to let anyone play with parameters with the online demonstration of the star field generator.

starfield20170709-gui.png.aa07a7f14243d57f9634c7d789a06650.png

Feel free to play along with these parameters and tell me which ones produce good visual results. It is not possible at the moment to save and export parameters, but you can take screenshot you can share.

Thanks to that, it is already surely possible to choose more "realistic" colors for stars, or their numbers in each layer. Although any comments can be interesting... as long as it is said in polite form. ;)

Also, a very first version of comets has been implemented.

starfield20170709.gif.211580feb8fc05715eb6807377ba4b92.gif

It uses a particle system with 500 particles, which seems a good compromise between resolution and performance.

Now gas clouds...

Share this post


Link to post
Share on other sites
sergamer1    821
48 minutes ago, yahiko00 said:

Feel free to play along with these parameters and tell me which ones produce good visual results. It is not possible at the moment to save and export parameters, but you can take screenshot you can share.

Thanks to that, it is already surely possible to choose more "realistic" colors for stars, or their numbers in each layer. Although any comments can be interesting... as long as it is said in polite form. ;)

Yes, I just had a quick play around.  Not saying this is so incredibly realistic but should be a little more so :-)  Actually, it's perhaps a little 'boring' looking in a way since it's dominated by white, yellow and red stars but is closer to how it problably looks.  The massive blue stars are usually located in young stars clusters and normally they die quickly before they enter the Galactic background (either fizzling out or exploding as Supernova).  If you want to add other features like gas clouds and star clusters, then that is one thing to think about.  Anyway, you seem to be making good progress so look forward to seeing some gas clouds soon ;-)

StarfieldParameters.png

Share this post


Link to post
Share on other sites
sergamer1    821
6 minutes ago, yahiko00 said:

Just curious: on which hardware have you taken this screenshot? I'm wondering so because of the FPS which is quite low.

Just on my not-particularly powerful laptop (a cheapish Lenovo Thinkpad).  I also have more stars than you (800-odd) which might slow it down a little more I guess?

Share this post


Link to post
Share on other sites
yahiko00    287

Thanks for your reply :)

Since I got similar FPS on one of my GPU-less laptop too, I guess your Thinkpad has no GPU too.

Any FPS feedback on other devices would interest me as well :)

Share this post


Link to post
Share on other sites
taylorswift    7
9 hours ago, sergamer1 said:

Actually, I wanted to say something about this also.  This is incorrect but for the wrong reasons.  It's true that there is redshift due to the expansion of the Universe but we can't actually see stars in other galaxies with the naked eye so all visible stars are in our own Galaxy.  However, there is an effect known as interstellar reddening where gas/dust in the interstellar medium (ISM) absorbs preferentially blue light from distant stars making them appear redder.  And since more distant stars have more ISM between us and it, they appear redder.  This is a quite famous example

where you can see an obvious gas cloud making stars redder.  This is obviously a very discrete blob of gas, but this happens in many directions on large-scales so I would make the near stars white/yellow/blue (depending on mass) and the distant stars more and more red if you wish to mimic this kind of Galactic-fog effect :-)

That’s interesting i was not aware of this!

Share this post


Link to post
Share on other sites
taylorswift    7
On 7/3/2017 at 1:46 PM, sergamer1 said:

Okay, gas clouds are a whole other ball-game!  Their form is highly irregular and not described by some simple equation (unfortunately).  When astrophysicists try to generate such density fields, they usually try and produce some kind of fractal density field (i.e. with fractal dimension less than 3 so it has holes and other structures).   Maybe you should consider something like Perlin noise (https://en.wikipedia.org/wiki/Perlin_noise) since you'll presumably only be generating in 2d.  Many people generate irregular shaped profiles, such as mountain ranges or islands, using Perlin noise, and I think this the route to take.  I've seen other people try stuff like this (i.e. interstellar gas clouds) in the past, although I'm not sure what method they used.  If I find something that's useful, I'll post it here!  :-)

I wanted to add you can get very nice results by combining gradient noise with cell noise which gives you a lot more well-defined structure than gradient noise alone. The horizon zero dawn cloud thread has a lot of useful info on this technique. It tends to be heavy to compute but you might have luck prerendering it since the camera is only moving in one direction and gas clouds in space don’t change much in time.

Share this post


Link to post
Share on other sites
yahiko00    287

Some progresses have been made since the last time.

I've replaced the blur filter which cause an undesirable loss of brightness by a bloom filter which on the contrary, enhance stars' brightness, which is what I wanted.

More importantly, I have implemented a first attempt of a gas cloud based on the simplex noise shader --- inspired by the many examples available on shadertoy.com (thanks again @JTippetts).

If find the results quite convincing although there is room for improvement. This is not really possible for the moment to control the shape of the gas cloud, and I can hardly define the main color of it. I guess I need to dig more into the math of this shader... ^_^

starfield20170712.png.11a1369b6e840a485e39ac970febf474.png

starfield20170713.png.824ec1653f37a205eb2bd5e2ba38831f.png

Feel free to try it onlinehttp://yahiko.developpez.com/apps/Starfield/

To make it works, with the gas cloud and the bloom effect, your browser and your GPU (or integrated Intel Graphics) need to support WebGL.

Any feedback and suggestion are welcome to improve the overall aspect.

Cheers! :)

Edited by yahiko00

Share this post


Link to post
Share on other sites
taylorswift    7
On 7/13/2017 at 11:16 AM, yahiko00 said:

Some progresses have been made since the last time.

I've replaced the blur filter which cause an undesirable loss of brightness by a bloom filter which on the contrary, enhance stars' brightness, which is what I wanted.

More importantly, I have implemented a first attempt of a gas cloud based on the simplex noise shader --- inspired by the many examples available on shadertoy.com (thanks again @JTippetts).

If find the results quite convincing although there is room for improvement. This is not really possible for the moment to control the shape of the gas cloud, and I can hardly define the main color of it. I guess I need to dig more into the math of this shader... ^_^

starfield20170712.png.11a1369b6e840a485e39ac970febf474.png

starfield20170713.png.824ec1653f37a205eb2bd5e2ba38831f.png

Feel free to try it onlinehttp://yahiko.developpez.com/apps/Starfield/

To make it works, with the gas cloud and the bloom effect, your browser and your GPU (or integrated Intel Graphics) need to support WebGL.

Any feedback and suggestion are welcome to improve the overall aspect.

Cheers! :)

That looks so much nicer congratulations! If I had any suggestions I would add some more high frequency detail to the gas clouds and fix the star color selection because the big yellow stars in the front and the faint blue stars in the back look very weird to me. You have basically no red stars and way, way too many blue stars. Blue stars are actually less common compared to white, yellow, orange, and red stars.

Share this post


Link to post
Share on other sites
yahiko00    287

Thanks. Since I'm brand new in the world of shaders, my gas clouds are far from perfect, and I'm not sure to understand what you mean @taylorswift by "high frequencies" nor how to implement these. My background is not really CG, unfortunately.

Here is the fragment shader I use to generate my nebulae. Anyone who has suggestions to improve this shader both in terms of rendering aspect and/or performance is welcome.

// nebulae.frag.glsl
// inspired from: https://www.shadertoy.com/view/lslSDS

precision mediump float;

uniform vec2  iResolution;
uniform float iGlobalTime;
uniform float redPow;
uniform float greenPow;
uniform float bluePow;
uniform float noiseColor;

#define PI 3.141592653589793

// Simplex Noise by IQ
vec2 hash(vec2 p) {
	p = vec2(dot(p, vec2(127.1, 311.7)),
			 dot(p, vec2(269.5, 183.3)));

	return -1.0 + 2.0 * fract(sin(p) * 43758.5453123);
}

float noise(in vec2 p) {
    const float K1 = 0.366025404; // (sqrt(3) - 1) / 2;
    const float K2 = 0.211324865; // (3 - sqrt(3)) / 6;

	vec2 i = floor(p + K1 * (p.x + p.y));
	
    vec2 a = p - i + K2 * (i.x + i.y);
    vec2 o = (a.x > a.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); // vec2 of = 0.5 + 0.5 * vec2(sign(a.x - a.y), sign(a.y - a.x));
    vec2 b = a - o + K2;
	vec2 c = a - 1.0 + 2.0 * K2;

    vec3 h = max(0.5 - vec3(dot(a, a), dot(b, b), dot(c, c)), 0.0);

	vec3 n = h * h * h * h * vec3(dot(a, hash(i + 0.0)), dot(b, hash(i + o)), dot(c, hash(i + 1.0)));

    return dot(n, vec3(70.0));
}

const mat2 m = mat2(0.80, 0.60, -0.60, 0.80);

float fbm4(in vec2 p) {
    float f = 0.0;
    f += 0.5000 * noise(p); p = m * p * 2.02;
    f += 0.2500 * noise(p); p = m * p * 2.03;
    f += 0.1250 * noise(p); p = m * p * 2.01;
    f += 0.0625 * noise(p);
    return f;
}

float marble(in vec2 p) {
	return cos(p.x + fbm4(p));
}

float dowarp (in vec2 q, out vec2 a, out vec2 b) {
	float ang = 0.;
	ang = 1.2345 * sin(33.33); // 0.015 * iGlobalTime;
	mat2 m1 = mat2(cos(ang), -sin(ang), sin(ang), cos(ang));
	ang = 0.2345 * sin(66.66); // 0.021 * iGlobalTime;
	mat2 m2 = mat2(cos(ang), -sin(ang), sin(ang), cos(ang));

	a = vec2(marble(m1 * q), marble(m2 * q + vec2(1.12, 0.654)));

	ang = 0.543 * cos(13.33); // 0.011 * iGlobalTime;
	m1 = mat2(cos(ang), -sin(ang), sin(ang), cos(ang));
	ang = 1.128 * cos(53.33); // 0.018 * iGlobalTime;
	m2 = mat2(cos(ang), -sin(ang), sin(ang), cos(ang));

	b = vec2(marble(m2 * (q + a)), marble(m1 * (q + a)));

	return marble(q + b + vec2(0.32, 1.654));
}

void main() {
    vec2 uv = gl_FragCoord.xy / iResolution.xy;

	vec2 q = 2. * uv - 1.;
	q.y *= iResolution.y / iResolution.x;

	// camera	
	vec3 rd = normalize(vec3(q.x, q.y, 1.));

	// Nebulae Background
	q.x = 0.5 + atan(rd.z, rd.x) / (2. * PI);
	q.y = 0.5 - asin(rd.y) / PI + 0.512 + 0.0001 * iGlobalTime;
	q *= 2.34;

	vec2 wa = vec2(0.);
	vec2 wb = vec2(0.);
	float f = dowarp(q, wa, wb);
	f = 0.5 + 0.5 * f;

	// Colorization
	vec3 col = vec3(f);
	float wc = f;
	col = vec3(wc, wc * wc, wc * wc * wc);             // increase: R, G, B
	wc = abs(wa.x);
	col -= vec3(wc * wc, wc, wc * wc * wc);            // decrease: G, R, B
	wc = abs(wb.x);
	col += vec3(wc * wc * wc, wc * wc, wc);            // increase: B, G, R
	col *= 0.7;                                        // decrease all RGB components: more black, less white
	col.r = pow(col.r, redPow);                        // high pass filter for red
	col.g = pow(col.g, greenPow);                      // high pass filter for green
	col.b = pow(col.b, bluePow);                       // high pass filter for blue
	col = smoothstep(0., 1., col);                     // Smoothen color gradients
	//col = 0.5 - (1.4 * col - 0.7) * (1.4 * col - 0.7); // color translation
	col = 0.75 * sqrt(col);                            // increase all RGB components: less black, more white
	col *= 1. - noiseColor * fbm4(8. * q);             // add noise
	col = clamp(col, 0., 1.);

	// Vignetting
	// vec2 r = -1.0 + 2.0 * uv;
	// float vb = max(abs(r.x), abs(r.y));
	// col *= (0.15 + 0.85 * (1.0 - exp(-(1.0 - vb) * 30.0)));

	gl_FragColor = vec4(col, 1.0);
}

 

About star color selection, this is a parameter I can easily change through the GUI of my generator. But I agree, colors shown above are not realistic.

By now, I am working on (fast) planet generation. If anyone has some hints or ressources about this, I am obviously interested.

Cheers! :)

Share this post


Link to post
Share on other sites
taylorswift    7
On 7/15/2017 at 0:58 PM, yahiko00 said:

Thanks. Since I'm brand new in the world of shaders, my gas clouds are far from perfect, and I'm not sure to understand what you mean @taylorswift by "high frequencies" nor how to implement these. My background is not really CG, unfortunately.

Here is the fragment shader I use to generate my nebulae. Anyone who has suggestions to improve this shader both in terms of rendering aspect and/or performance is welcome.


// nebulae.frag.glsl
// inspired from: https://www.shadertoy.com/view/lslSDS

precision mediump float;

uniform vec2  iResolution;
uniform float iGlobalTime;
uniform float redPow;
uniform float greenPow;
uniform float bluePow;
uniform float noiseColor;

#define PI 3.141592653589793

// Simplex Noise by IQ
vec2 hash(vec2 p) {
	p = vec2(dot(p, vec2(127.1, 311.7)),
			 dot(p, vec2(269.5, 183.3)));

	return -1.0 + 2.0 * fract(sin(p) * 43758.5453123);
}

float noise(in vec2 p) {
    const float K1 = 0.366025404; // (sqrt(3) - 1) / 2;
    const float K2 = 0.211324865; // (3 - sqrt(3)) / 6;

	vec2 i = floor(p + K1 * (p.x + p.y));
	
    vec2 a = p - i + K2 * (i.x + i.y);
    vec2 o = (a.x > a.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); // vec2 of = 0.5 + 0.5 * vec2(sign(a.x - a.y), sign(a.y - a.x));
    vec2 b = a - o + K2;
	vec2 c = a - 1.0 + 2.0 * K2;

    vec3 h = max(0.5 - vec3(dot(a, a), dot(b, b), dot(c, c)), 0.0);

	vec3 n = h * h * h * h * vec3(dot(a, hash(i + 0.0)), dot(b, hash(i + o)), dot(c, hash(i + 1.0)));

    return dot(n, vec3(70.0));
}

const mat2 m = mat2(0.80, 0.60, -0.60, 0.80);

float fbm4(in vec2 p) {
    float f = 0.0;
    f += 0.5000 * noise(p); p = m * p * 2.02;
    f += 0.2500 * noise(p); p = m * p * 2.03;
    f += 0.1250 * noise(p); p = m * p * 2.01;
    f += 0.0625 * noise(p);
    return f;
}

float marble(in vec2 p) {
	return cos(p.x + fbm4(p));
}

float dowarp (in vec2 q, out vec2 a, out vec2 b) {
	float ang = 0.;
	ang = 1.2345 * sin(33.33); // 0.015 * iGlobalTime;
	mat2 m1 = mat2(cos(ang), -sin(ang), sin(ang), cos(ang));
	ang = 0.2345 * sin(66.66); // 0.021 * iGlobalTime;
	mat2 m2 = mat2(cos(ang), -sin(ang), sin(ang), cos(ang));

	a = vec2(marble(m1 * q), marble(m2 * q + vec2(1.12, 0.654)));

	ang = 0.543 * cos(13.33); // 0.011 * iGlobalTime;
	m1 = mat2(cos(ang), -sin(ang), sin(ang), cos(ang));
	ang = 1.128 * cos(53.33); // 0.018 * iGlobalTime;
	m2 = mat2(cos(ang), -sin(ang), sin(ang), cos(ang));

	b = vec2(marble(m2 * (q + a)), marble(m1 * (q + a)));

	return marble(q + b + vec2(0.32, 1.654));
}

void main() {
    vec2 uv = gl_FragCoord.xy / iResolution.xy;

	vec2 q = 2. * uv - 1.;
	q.y *= iResolution.y / iResolution.x;

	// camera	
	vec3 rd = normalize(vec3(q.x, q.y, 1.));

	// Nebulae Background
	q.x = 0.5 + atan(rd.z, rd.x) / (2. * PI);
	q.y = 0.5 - asin(rd.y) / PI + 0.512 + 0.0001 * iGlobalTime;
	q *= 2.34;

	vec2 wa = vec2(0.);
	vec2 wb = vec2(0.);
	float f = dowarp(q, wa, wb);
	f = 0.5 + 0.5 * f;

	// Colorization
	vec3 col = vec3(f);
	float wc = f;
	col = vec3(wc, wc * wc, wc * wc * wc);             // increase: R, G, B
	wc = abs(wa.x);
	col -= vec3(wc * wc, wc, wc * wc * wc);            // decrease: G, R, B
	wc = abs(wb.x);
	col += vec3(wc * wc * wc, wc * wc, wc);            // increase: B, G, R
	col *= 0.7;                                        // decrease all RGB components: more black, less white
	col.r = pow(col.r, redPow);                        // high pass filter for red
	col.g = pow(col.g, greenPow);                      // high pass filter for green
	col.b = pow(col.b, bluePow);                       // high pass filter for blue
	col = smoothstep(0., 1., col);                     // Smoothen color gradients
	//col = 0.5 - (1.4 * col - 0.7) * (1.4 * col - 0.7); // color translation
	col = 0.75 * sqrt(col);                            // increase all RGB components: less black, more white
	col *= 1. - noiseColor * fbm4(8. * q);             // add noise
	col = clamp(col, 0., 1.);

	// Vignetting
	// vec2 r = -1.0 + 2.0 * uv;
	// float vb = max(abs(r.x), abs(r.y));
	// col *= (0.15 + 0.85 * (1.0 - exp(-(1.0 - vb) * 30.0)));

	gl_FragColor = vec4(col, 1.0);
}

 

About star color selection, this is a parameter I can easily change through the GUI of my generator. But I agree, colors shown above are not realistic.

High frequency just means add more octaves of noise to your FBM. However I’d recommend storing your noise in a texture; generating it in the shader might be okay for one octave of perlin noise but when you get more complex its faster to prebake it.

By the way, I would steer clear of simplex-lattice additive gradient noise; it’s okay for two dimensions but when you scale it up to three or more dimensions the implementation gets very hairy. Take it from someone who maintains the Swift procedural noise library. Plus, a lot of popular noise recipes assume you’re working with a 3D classical gradient noise generator (3D cubic-lattice interpolated gradient noise). Contrary to the claims of CS theoreticians, classical gradient noise is much faster than simplex noise.

Quote

By now, I am working on (fast) planet generation. If anyone has some hints or ressources about this, I am obviously interested.

Cheers! :)

Welcome to my hell. Procedural planet generation is no small task, it’s one of the more challenging feats in the procedural generation world, and there are a lot of poor-quality tutorials that give ugly results. How much detail do you need? If you only need marble-sized renders, it’s relatively easy to get something that looks good. If you need to fly over them, get ready to spend a few months getting it right.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now