Friday, April 25, 2008

Planet Optimisation... Vertex and Index Buffers

Not a very interesting post I'm afraid, all I did was optimise a bit (mainly moving all the vertices to a vertex buffer and creating one index buffer for each cube face). Now I can render the planet at a level of detail of 8 (about 750,000 polys) at a reasonable FPS of 50 - before at level 7 (about 200,000 polys) I was only getting 1 FPS!

planetLevel8 PlanetSeam

I still have a seam problem where the 2 cube faces meet (it's most visible in the bottom right of the second image above) and I think it has to do with the fact that the base textures I have don't wrap in every direction.

I'm not looking forward to implementing CLOD on this sort of sized terrain. I've had issues with Quadtree before where it just took up a load of memory and slowed everything down. I need a good way of aggregating the vertices in the patches I render - and I'm at a loss. Also, I need to be able to dispose of patches I don't use without effecting FPS - I tried this before but with little success.

Thursday, April 24, 2008

Planets 0.3 - Texture

I'm not sure why I didn't think of it before, but texturing the planet isn't difficult, each face of the original cube is square so I can just apply the same texturing technique as I did before. I just have to recursively get all the noise values to a certain level of detail, normalise it and use this as a height map. The first go at this wasn't so successful.

planetTextureBad2

I used parameters that would create a more asteroid-y looking planetoid just because it's easier to see where the problems are. In the above image I had set a texture coordinate wrong and this recursively led to the whole image looking really scrambled. After I got the coordinates sorted, the next problem appeared:

AsteroidTextureNormalisationProblem

Basically, because I generate a height map and a texture for each patch (cube face) independently, what might have been the highest height for one patch, isn't the highest for another. So although one patch shows snow for its highest point, the neighbouring patch has higher points than that so it won't use snow for a point of the same height. I probably made that even more confusing than it actually is. Anyways, all I had to do was normalise all the patches with respect to all the other patches. The texture is starting to look like it's covering the model well - but there's a little seam to stretch over...

AsteroidSeams

Now I've a textured planet! Unfortunately, I think the texture looks far too homogenous (looking the same all over) for an Earth-like planet.

homogenous planetTextured

However they seem like pretty good parameters for a moon or something like that, I just changed a few of the textures and got this moon.

moon

Oh no... why did I do a full moon??? Now I've got hair growing on the backs of my hands and.... oh no... not now... I've turned into Michael J Fox in Teen Wolf!!! AWOOOOOOOOOOOOOOOOOOOOOOOOOOO!!!!!!!!!!!!!!

Wednesday, April 23, 2008

Planets 0.2 - 3D Noise

Geekily enough I have to say adding 3D Perlin Noise to the planet was a lot of fun - it really wasn't a lot of work to move the 2D Perlin Noise code to 3D and I quickly got some visual results. It's frustrating sometimes working with graphics to toil away and have no big change to show for it. The same goes for any programming really, fixing some memory problem can often be a lot more work than creating something visual but the visual change is an obvious and immediate reward. Here's my first application of 3D noise to the procedural sphere:

3dNoiseWhoops

Not bad eh? It turns out a lot of geography/astronomy books have totally the wrong idea on how planets look, and it took a lot of origami to make the books mimic what my code produced. Then I thought of having to do all those folds to all those already published books to conform to my model, and I caved to making my model a little more like what the books say. Here are a few different levels of detail for the planetoid - you can see that the noise is always coherent at different levels of detail and doesn't change too much from the previous/next levels.

3dNoiseAsteroid2 3dNoiseAsteroid4 3dNoiseAsteroid6

Here are a few attempts at a less-asteroidy-more-planety model. The main changes were increasing the frequency parameter of the Perlin Noise and decreasing the height change that the noise would realise. The last one looks most realistic, but on a proper planet, you could barely see the mountains at a distance because the height-scale is so negligent compared to the scale of the planet.

3dNoiseLumpy 3dNoiseSpikey 3dNoiseOk

Here's a higher level of detail on the surface of the last planet, next I'll need to texture that landscape...

3dNoiseLandscape

Tuesday, April 22, 2008

Planets 0.1

It was really simple to get a little procedural sphere going from a cube, just keep subdividing each face into 4 smaller faces. After thinking about it, I don't think I needed to do anything special to create a planet model because if I texture it with 3 dimensional Perlin noise even a sphere model with a lot of pinching would be fine - anyways, texturing a sphere is for another day. Here are some of my results, FPS doesn't seem to get affected until I get to a level of detail of 5 and then it all goes pear-shaped fast.... well egg-shaped as you'll see...

planet0planet1 planet2 planet3 planet4 planet5

All bar the last run at 60 FPS (I have vsync on so we can safely assume that the actual FPS is more like 60,000,000 FPS). The last one runs about 30 FPS but this is all pure software, I haven't done anything yet to optimise. Level 6 runs about 7 FPS and level 7... What happened to level 7???

planet7egg

In my sheer brilliant-ness I must have implemented astrophysics while I wasn't really concentrating, this mass of matter is obviously collapsing on itself and probably would implode... and if it ran faster than 1 FPS I'm sure it would look fecking awesome, but I didn't stick around to find out.

So after optimising the sphere stuff a bit, next I'll try to create some textures with Perlin Noise. I get how it works, I'm just a little confused as to how to implement it efficiently. For 2D textures, I have an image that's stretched over the terrain and I give texture coordinates to each point so DirectX does the rest. I can visualise how a 3D Perlin Noise texture looks (like a solid cloud, any slice will create coherent texture and so would a sphere carved out of that material) - but I've no idea how to tell DX about it. I may have to go with colouring each vertex, and then stretching a detail map over it all, but that seems to me like it would look like all kinds of shittyness unless I go to a level of detail so high my planet turns into an egg.

Thursday, April 17, 2008

Perlin Noise And Fractals

I read up on Ken Perlin and wanted to try do some terrain using Fractal Brownian Motion. Ken's homepage has tons of little Java applications that each do something innovative with noise - it's good to play about with. Ken came up with a fast way of creating noise and used it to create natural looking textures. He even won an Oscar for this technique! I had a look at his code and to be honest it was very difficult to follow, sort of like it had been obfuscated. So I looked elsewhere for info but found a lot of people did a sort of hack on Perlin Noise - basically fill an array with random noise and smooth each pixel using the values of neighbouring pixels. I tried this technique out and I wasn't that impressed with the results. It doesn't look too bad but when on an actual terrain, I think it looks too artificial - like the mountains have a grid-like pattern (I tried to highlight this in red on the terrain).

 PerlinHeightMap perlinhack

So with the proper Perlin Noise/Fractal Brownian Motion implementation, I think the results are a lot better. To start I wrote a little app so I could quickly try out different combinations of the parameters, here's a screen of it, and some of the results:

perlinnoiseapp

O_7F_0.01A_1L_2P_0.4O_7F_0.015A_1L_2P_0.4  O_8F_0.025A_2L_2.4P_0.56 

Here's some terrain built with a Perlin/fBm height-map:

perlinterrain

Another cool thing about Perlin/fBm (if you're a geek I suppose) is that it can be applied to three dimensions too, so I should be able to use it for seamless planet height-maps and textures... but haven't worked it out yet. Often when applying a 2d texture to a sphere artifacts appear, like pinching at the poles, but Perlin/fBm should be fine - we'll see!

Next I really need to do some clean up on my code and after that I'll either look at:

  • making a sphere by recursively splitting a cube's face or...
  • generating the grass, snow and rock textures with Perlin noise

Wednesday, April 16, 2008

Adaptive Quadtree

I tried hard to optimise my code but in the end I just don't think a quadtree is suited to very large terrain. Here are some of the things I tried:

  • The quadtree is now adaptive meaning it only creates children if it needs them to render a more detail
  • I tried to Dispose() of unused resources on the fly but this really slowed down FPS
  • The quadtree now uses a shared vertex buffer reducing the number of calls to the device (before each patch would have its own vertex buffer and its own index buffer)
  • I tried using NProf to do some performance analysis on my code, but it didn't help me target anything in particular

I'm not 100% sure but I think the main problem is the number of objects needed to render a quadtree increases exponentially when the terrain size increases. With CLOD the number of objects is pretty low in comparison. For a terrain length 256, I use 16 CLOD patches but I would need over 20,000 quad patches. It's a shame, I think quad is neater in the same way that binary search trees are neat. Check out some comparison shots of a large (1024 * 1024 vertices) terrain:

1024QuadWire 1024CLODWire

1024Quad 1024CLOD

They look similar enough but for the quadtree I was getting about 4 FPS and for with CLOD I was getting between 20-30 FPS. I'll stick with CLOD for planets I think.

1024ClodLandscape

Thursday, April 10, 2008

Quadtree Holes Fixed

I got the holes fixed, it really really hurt my brain. You can see the results here compared to CLOD. There's nothing that different really, just the same terrain with no holes in it. The weird thing is that the quadtree renders a LOT less polys but the FPS is lower. Also, if I try to render a large terrain, quadtree crawls. I'll have to do some optimisation on it next.

quadnoholes clodnoholes

You can't see it in these pictures but sometime I have these intermittent tiny dots of yellow (so a tiny hole way smaller than a poly) on the quadtree and also tiny hairline cracks with both CLOD and the quadtree.

I think part of the problem is that I'm using my base object which allows an object hierarchy of children to be recursively attached. All this hierarchy does is move each attached child if the parent object moves, so for example, if you move your arm but don't move your hand relative to your arm, your hand should still be in a different position. This is neat for some applications but I think perhaps it's adding unnecessary overhead to the terrain: the patches are all statically fixed unlike joints in an arm. There are inevitable tiny floating point errors which with tons of children attached - like with the patches - is probably causing the hairline cracks. The matrix calculations are adding to the CPU cycles and may be why my quadtree appears to run slower than my CLOD while showing less polys.

So, reluctantly I'll have to overhaul some code and do some optimisation. I hate overhauls, there's little or no visual improvement for a lot of work, but as it stands I think it would take my engine longer to create a world scene than it took the world to be created (even in Creationist terms!) ... stupid Creationists.

Wednesday, April 9, 2008

Quad Tree Termites

It's taking a lot longer than I thought but the quadtree implementation is finally taking some shape. Real work (stuff that pays money) took over for a bit so that slowed things down a lot - I also had a holiday around Spain and over to Morocco which was good fun. I climbed a couple of mountains there and I must say God/Buddha/Allah/String theory/Ekpyrotic theory did a good job - no cracks, high detail, no obvious texture repeat and good continuous level of detail (although I wasn't moving very fast). I'd like to see it run on my laptop though.

So anyways, here's a comparison of splitting for CLOD vs. Quadtree in wireframe mode, you can see that the Quadtree is much more precise, the camera position causes a circle of split patches:

clodmesh quadmesh

The number of polygons rendered is much lower than CLOD, mainly because the frustum culling is much more precise due to the recursive nature of the quadtree implementation. However, I'll need to do a good bit of optimisation, despite the lower number of polygons rendered, the overall FPS is suffering because (I think) of all the recursion needed to draw all the low level polygons.

You might also be able to see all the holes around the circle - it's easier to see in this picture:

quadholes

Yes, yellow is the new black. All that pink was making my eyes sore, yellow works just as well to show up problems I think.