Thursday, December 24, 2009

Blooming Starfields

It took AGES to add bloom. I used an XNA tutorial for bloom and in order to do the various passes (pick the brightest spots, blur it, recombine with the original image) it called ResolveBackBuffer to copy the back buffer to a texture for the next pass. I don’t fully understand it yet but it seems this call would invalidate the back buffer and subsequent shaders would write as if they were the first. I’ll try to illustrate what I mean by showing the problems I had. My plan was to draw the stars & clusters first, bloom that, then add the nebula.

Here’s what the result was like without the bloom stage, the nebula is added to the background stars (no bloom) as expected:

starfield without bloom

And here with the bloom stage included in the middle, it seems to be overwritten by the nebula stage:

nebula overwrites starfield with bloom In the end, I did a ResolveBackBuffer to a ResoveTarget2D after the bloom stage and drew this to the back buffer before I call the fBm/nebula shader. This finally ended in what I was looking for.

starfield with bloom

I’m still not 100% happy with the results, I had imagined the bloomed background stars would really light up the nebula but they seem to actually be dimmer than the stars outside of the nebula. I might try to use the same fBm noise result to draw some stars so they are in place in the densest parts of the nebula.

The main thing I’m not happy with though is that the code is a total mess, I just kept hacking and hacking away until I got results. I’m sure a team of monkeys would have produced neater code in less time. It’ll be a while before I get these images into a skybox – so until then HAPPY CHRISTMAS!

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();
    }
}

Monday, December 21, 2009

GPU Perlin Noise

I updated my DirectX before starting and somehow my MDX project became all liney, like this:

Uhhh

Because of this, and because most of the online samples I find to plagiarize be inspired by are usually in XNA I decided to convert. Unfortunately there’s no automatic conversion tool so I had to open a new project, add my old files and try to fix up the errors. Some things were annoying, like the lack of absolute mouse movement and having to load a font from a file (size is fixed in the file) but overall the classes are better named and organised. Here’s my first shader on the planet in XNA, stripes:

stripey

So after a quick crash course on shaders, I found Perlin had published HLSL code for Improved Perlin noise in GPU Gems 2 – all of which is free online! I had real trouble getting it going however, every texture I generated was blank, and I didn’t know enough about HLSL to figure it out. There seemed to be a tutorial on ziggyware but it seems ziggyware’s been under attack from hackers so I couldn’t get it. I tried out some other projects like Drilian’s but again the XNA version I made the noise didn’t work. Eventually I found a post where someone had similar problems, which led me to the Google cache of the XNA GPU Perlin noise tutorial – by Patrick of recreationstudios (he’s made some amazing progress since I deserted this project 2 years ago). All I needed to do was initialise the textures all the noise functions use. Perlin had functions to do this in HLSL, but I hadn’t a clue how to call them, supposedly you can’t in XNA so I moved the HLSL code to C# then create the textures on the CPU and set the textures on the GPU. Patrick’s tutorial explains this much better (prize-winningly better apparently) so I won’t go into details.

So here are some screens of different types of Perlin noise on the planet:

Noise

NoiseRidgedMF

In these shots the noise is being calculated per-pixel each frame based on the geometry. Surprisingly, getting closer to the planet so the level of detail is higher (the 4 child patches are drawn instead of the parent patch) didn’t change the surface visibly. This had to do with the fact that there wasn’t much geometry difference between the parents and the children, when I changed the patch size from 33x33 to 5x5 there was definite popping in the textures.

Here’s a video of flying about a bit:

Update: shading every frame means I can animate!

Wednesday, December 9, 2009

Procedural LOD Planet Textures

I got a rough draft of procedural LOD planet textures working and thought I’d share some screenshots. The main difference between this and the last post is that this planet subdivides its patches and generates a new texture for each new patch as the camera gets closer and the planet in the last post was just static (it only generated vertices and textures at start up). Currently, all the textures are created in software so it’s hella slow, too slow to play really. Once a texture is generated and cached it’s very fast (capped at 60fps). On-the-fly however even with a texture size of only 17x17 pixels (same amount of vertices per patch) it’s jerky. Here are 6 levels of 256x256 textures zooming in on the one spot.

ProceduralTextureLevel0

ProceduralTextureLevel1

ProceduralTextureLevel2

ProceduralTextureLevel3

ProceduralTextureLevel4

ProceduralTextureLevel5

Next steps are to try to speed it up so it’s acceptable to play with, so I’ll probably do 2 things; use EQATEC to profile my app and do the image generation in hardware. But before I do that, I somehow messed up the geometry so it’s clockwise instead of anti-clockwise… or the other way around… whatever I did anyways I’ll try to undo.

Update: Here’s a video, fraps and windows movie maker seem to work well with youtube, my previous efforts at uploading video turned out horrible! I’m only running the textures at 17x17 so the video runs smoothly (i.e. I know it looks like a big steaming pile of sh!t).

Monday, December 7, 2009

Seams Like Years…

It’s been a while since I updated this… a really long while, but I’m going to try to get back into it again. My current problem is something I never really fixed the last time: seams. Here’s an example:

Seams

Weirdly enough if I save the textures I generate for the faces they line up fine with no seam (the darkish hole should line up with the pit above):

NoSeamsOnLeftBackAndRightTextures

So, having changed my texture generator around a bit I’m 100% sure it’s my texture code some sort of floating point error how MDX is texturing the faces. There must be a way to get MDX to just display the bitmap I give it & not mess up the edges…

Update 1: I had some mag & min filtering going on which was causing some (but not all of my seam problems. When I got rid of this code:

//    device.SamplerState[0].MinFilter = Direct3D.TextureFilter.Anisotropic;
// device.SamplerState[0].MagFilter = Direct3D.TextureFilter.Anisotropic;



It looks like this now (still a problem with top and bottom patches but going from front to left to back to right and back is seamless now):



FilterSeamsFixed





Not sure what’s causing it, but you can see from front to top to back to bottom the textures I’m generating seem to be slightly offset – the image on the right offsets them in the correct direction and they seem to match much better.



nooffset offset



Update 2: There were some errors in how I collated the heights from sub-patches, now top to bottom match up perfectly, and I have no seams!



NoSeams



NoSeamsTextures





Next back to the adaptive planet (the one that properly changes its patches depending on LOD) and an attempt at making the textures in hardware.