4
\$\begingroup\$

I found a cool kickstarter project called "Skywanders". It's an minecraft like space game with a lego like building system and pretty cool graphics.

One thing I noticed are the "nebula clouds". They are procedurally generated 3D Objects and they look amazing.

enter image description here

How do I generate such nebulas? I bet there's a way to do that. And is it possible to convert a 2D nebula into a 3D one? I didn't found any algorithm yet or other sources.

\$\endgroup\$
6
  • 2
    \$\begingroup\$ We'll need to know more about your setup and needs. What tools are you using? Do you just need to look at the nebulas from a distance, or fly through them (much harder)? What's your rendering budget like — are these nebulas the main attraction, or do they need to be cheap enough to also render a pile of other content at the same time? On what target platform? \$\endgroup\$
    – DMGregory
    Aug 30, 2017 at 13:59
  • 2
    \$\begingroup\$ What exactly do you mean by 3D? Do you have any video footage of moving through or around them? My experience is that these sorts of things are 2D textures pasted into a skybox. I'm not saying you couldn't do them in full 3D, but we need to know more about what exactly you want. \$\endgroup\$
    – Pikalek
    Aug 31, 2017 at 2:57
  • \$\begingroup\$ @DMGregory Im using unity. But i dont wanna a full tutorial here how to do that in unity :D . I just asked how something like that could be generated ? I guess there is an algorithm for that. You can actually fly through them. They are huge, i bet nearly as huge as they are in real life. They arent the main attraction and they are rendered with spaceships or stations or even asteroids at the same time. Pc i guess :D \$\endgroup\$
    – genaray
    Aug 31, 2017 at 19:41
  • \$\begingroup\$ @ A nebula in 3D actually like in space, where you can fly through and stuff like that. Those nebulas i posted arent skyboxes. The developer gave some interviews and said that they are procedually generated and i saw him flying through them. \$\endgroup\$
    – genaray
    Aug 31, 2017 at 19:43
  • 2
    \$\begingroup\$ @genaray If there's video of what it looks like to move through them & that's what you're after visually, please edit your question & add a link to show us what you're trying to achieve. If you're linking Youtube content, sent the link to jump to the time where the relevant stuff happens. \$\endgroup\$
    – Pikalek
    Aug 31, 2017 at 20:59

3 Answers 3

4
\$\begingroup\$

I've done something similar in the past through glsl's Fragment Shaders:

Nebula with Stars

https://www.shadertoy.com/view/lsyfWy

And a Processing version:

https://github.com/felipunky/Stars

It is basically a Fractional Brownian Motion or several layers of noise at different frequencies and amplitudes stacked together:

#define HASHSCALE .1031
// We create the pseudo-random number generator.
// https://www.shadertoy.com/view/4djSRW
float hash(float p)
{

    vec3 p3  = fract(vec3(p) * HASHSCALE);
    p3 += dot(p3, p3.yzx + 19.19);
    return fract((p3.x + p3.y) * p3.z);

}

// This function is by @Inigo Quilez.
// We create the 3D noise by generating pseudo-random numbers in the x, y and z directions and then interpolating between them.
float noise( in vec3 x )
{

    vec3 p = floor( x );
    vec3 k = fract( x );

    k *= k * k * ( 3.0 - 2.0 * k );

    float n = p.x + p.y * 57.0 + p.z * 113.0; 

    float a = hash( n );
    float b = hash( n + 1.0 );
    float c = hash( n + 57.0 );
    float d = hash( n + 58.0 );

    float e = hash( n + 113.0 );
    float f = hash( n + 114.0 );
    float g = hash( n + 170.0 );
    float h = hash( n + 171.0 );

    float res = mix( mix( mix ( a, b, k.x ), mix( c, d, k.x ), k.y ),
                 mix( mix ( e, f, k.x ), mix( g, h, k.x ), k.y ),
                 k.z
                 );

    return res;

}

// Here we do the stacking of noise at different octaves.
float fbm( in vec3 p )
{

    float f = 0.0;
    f += 0.5000 * noise( p ); p *= 2.02; p -= iTime * 0.5;
    f += 0.2500 * noise( p ); p *= 2.03; p += iTime * 0.4;
    f += 0.1250 * noise( p ); p *= 2.01; p -= iTime * 0.5;
    f += 0.0625 * noise( p );
    f += 0.0125 * noise( p );
    return f / 0.9375;

}

I find this fbm function more readable and easier to tweak:

float fbm( in vec3 p )
{

    float res = 0.0, fre = 1.0, amp = 1.0, div = 0.0;

    for( int i = 0; i < 5; ++i )
    {

        res += amp * noise( p * fre );
        div += amp;
        amp *= 0.7;
        fre *= 1.7;

    }

    res /= div;

    return res;

}

Rendered through a Sphere Tracing Algorithm that accumulates for a volumetric look:

// This is our ray marching algorithm.
float ray( vec3 ro, vec3 rd, out float den )
{

    float t = 0.0, maxD = 0.0, d = 1.0; den = 0.0;

    // The more STEPS the more accurate the marching.
    for( int i = 0; i < STEPS; ++i )
    {

        // Here we compute our Position p by the formula RayOrigin + RayDirection * our RayMarchStep.
        vec3 p = ro + rd * t;

        // This is our density, it is simply calling the Fractional Brownian Motion fbm function.
        den = fbm( p );

        // This allows us to put a limit in our accumulation of density.
        maxD = maxD < den ? den : maxD;

        // Here we bail on our marching according to MaximumDensity or our FAR threshold.
        if( maxD > 1.0 || t > FAR ) break;

       // We increment our RayMarchingSteps.
        t += 0.05;

    }

    den = maxD;

    return t;

}
\$\endgroup\$
0
2
\$\begingroup\$

You could use noise generation (Perlin, Value or Gradient are amongst the most popular). Either that or use techniques such as this: Procedurally Generated Nebulae in Unity3D

Otherwise using billboard rendered objects or something similar is probably your best bet. Especially when you want them to be 3D. You could potentially look into Z depth techniques (volumetric rendering), but this is an expensive process. So as far as entire nebula's go... Anyway, this should get you started.

\$\endgroup\$
1
\$\begingroup\$

So in general, you have two basic components to a nebula (from the visual side).

A: The silhouette:

To generate a random silhouette, I'd look into cellular automata. This process is often used to generate "natural" random structures (think caves).

Here's a decent series on how that can be done. It's in unity, but the principles are the same everywhere else. https://www.youtube.com/watch?v=v7yyZZjF1z4

B: The texture:

You can probably "get away" with using several layers of perlin noise with various blend modes to get the right amount of color variation.


Putting it all together:

Once you have your shape and noise maps, it's fairly straightforward to assign colors to regions and intensities using color ramp textures.


Bringing it to 3d Good news is that each of the processing can be extended into 3D. The rules get a little more complex, but it's pretty straightforward.

Resource for 3D noise generation: https://en.wikipedia.org/wiki/Simplex_noise http://catlikecoding.com/unity/tutorials/simplex-noise/ (unity, but universally applicable) https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch01.html (speifically section 1.3.3)

3D cellular automata is very straightforward, the rules don't change, you just add more neighbors to consider.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .