Thursday, December 24, 2009

Procedural Starfield Texture (First Go)

I decided to try my hand at a procedural starfield. I figured it’d be an easy enough shader to do (I’m still a total beginner) plus I’ll need to use the same techniques to generate cached images of planet patches (previous GPU noise posts were generated per-pixel every frame). So I started off with some blue fractal Brownian motion noise for the background:

stars_fBm

And added some code to make simple noise white if it were over a certain threshold. I thought these would appear as stars, but it was all blobby:

stars_fBmn

So then I scaled it by passing p*scale instead of p to inoise:

stars_fBmsn

Not bad… but the stars (little blobs) are too generic so I added in another layer of noise but at a second scale (bigger blobs) so it looks like brighter stars or clustering:

stars_fBmsnc

It looks ok… a bit lame though… The problems I see are that the stars have aliasing artefacts and the scene doesn’t … impress. Zoomed in the stars look crap, like Tetris blocks or something:

stars aliased unimpressive

I think it needs some effects like glow or bloom or MORE BLOOM! So I’ll look into that next.

Here’s the shader code so far, pretty simple stuff:

vertexOutput VS(vertexInput IN)
{
    vertexOutput OUT;
    OUT.hPosition = IN.position;
    OUT.texcoord  = IN.texcoord * noiseScale;
    OUT.wPosition = IN.position.xyz * noiseScale;
    return OUT;
}

float4 PS_test(vertexOutput IN): COLOR
{
  float3 p = IN.wPosition;
  float res = fBm(p, oct, lac, gain);
  float4 color = res;
  color.rg = 0; // make it blue
  color.a = 1;
  float star = inoise(p * speckleScale);
  if (star > speckle)
    color = lerp(color, star, 0.9);

  float starcluster = inoise(p * speckleScale2);
  if (starcluster > speckle2 + 0.1)
    color = lerp(color, starcluster, 0.9);
  return color;
}

technique test
{
    pass p0
    {
        VertexShader = compile vs_3_0 VS();
        PixelShader  = compile ps_3_0 PS_test();
    }
}

No comments: