Monday, December 29, 2008

PSVSM Shadows And Texture Updates

It's been a while since my last post so a lot has happened - mostly Christmas related stuff, but some planet work as well.

I implemented a second LOD for the textures so that when you view the planet from just outside the atmosphere the textures don't look like they repeat so much and there isn't a mipmap problem with the texture tiling so much which makes the texture really grainy. I also added back a temporary water sphere surface with some specular and normal mapping, to look like water, but it won't really look like water till it is animated, and it has uv problems at the top and bottom. Eventually I plan on coming up with a way to always have the water mesh face the camera at point where the uv isn't stretched and then do a mini-quad tree on it so that I can actually animate the vertices when you're close to the surface (but I'm getting waaayyy ahead of myself there).

After implementing that stuff I got in over my head implementing shadows.

My first success was with Ogre's PSSM shadow demo, but that had a major drawback because the shadows had a gap between where the shadow started and the base of the shadow casting triangles. Also the shadows swam a lot when you moved the camera and they were very pixelated because of the large amount of terrain that was covered.

This image shows the shadow "beards" and uses 3 512x512 shadow maps.

Later I found that this was a typical problem for basic PSSM shadows, and I read that VSM shadows didn't seem to have this problem (although they have their own drawbacks - namely light bleeding, which sounds weird to say)

I posted my latest GLSL shader code for the shadow caster and shadow receiver materials as well as the Ogre material code - and my set up code too so hopefully it can be tweaked to make it perform and look better.

These images show PSVSM using 3 1024x1024 shadow maps. I'll probably have to scale back to 512x512, unless I can come up with a way to gain back fps dramatically.

I plan on tweaking the shadow, terrain texture and water texture code next before moving on to a basic atmosphere.

Sunday, November 30, 2008

Random Transitions and Tiling issues

The latest implementation had seems at the edges of each repeating texture tile possibly due to bilinear filtering. I tried to fix this by offsetting the uv by 1.0 and scaling the actual image down by 2 pixels but this makes the tiles not repeat exactly. Still it is much better than the obvious seams before. I also added a noise texture that I use to randomize transitions between tiles.

Currently my look up table (LUT) only has 5 entries based on altitude only. Eventually I will make one that also incorporates slope.

This is a screenshot of the terrain with the more random transitions. I have 16 texture slots to play with so I will probably mess around with the look up table next before moving on to things like fixing my GLSL normal shading.

Also, something I forgot to mention in my last post was that the height maps are now randomly generated use FBM noise. I create 6 1024x1024 height maps on start up and save them to disk for the next time I run the program because my height map generation algorithm isn't optimized yet and takes a good 10-20 seconds to complete, which adds up when you're adjusting and recompiling frequently. The height maps are named in such a way that they are specific to the seed used for the noise, the size of the map, and the face on the 3D cube.

Saturday, November 29, 2008

Finally got to a good stopping point so here are some pictures of the latest progress.

A textured and shaded planet.

A view from further away with updates frozen.

Wireframe view of planet with updates frozen.

What I've implemented was vertex position and normal sharing between different faces and levels of the quadtree because calculations would be slightly different and you would get seams at the edges of a cube face.

Next I spent some time investigating Ysaneya's subtiling textures using a single texture pack and a slope/altitude look up table

While getting making the Ogre material and glsl shader I happened upon ml278 the 3d Planetary Surveyor which is something very similar to what I'm trying to accomplish! The developer had implemented a version of Ysaneya's subtiling in a glsl and Ogre, so I started with the open source shader he had and tweaked it to make it work in this program.

I still have a small 1 pixel seam around the edges of each texture when they repeat so I have to determine where that's coming from. I also need to add some noise between levels so that the transition isn't so obvious. Then, maybe I'll work on the water and atmosphere, or on the annoying popping effects when the lod levels change.

And, of course, the texture tiling is obvious from far away so I'll need to implement some kind of blurring or dirt map to make it less so.

Sunday, November 9, 2008

Normals Appeased

I finally decided to use the standard mesh layout for height maps instead of the diamond pattern you see in ROAM implementations and the normals now look fine. Before switching to this standard triangle layout I tried several other normal calculation methods, but still got those ugly cross hatches that you see in my previous posts.

Here's what the normals look like fixed:

And the wireframe version:

I still need to cache the vertex normals and tangents for the edges of each mesh to make the transition from large meshes to smaller resolution meshes seamless. Right now there are seams that I had fixed in my previous version that used the diamond pattern mesh.

After I fix that I plan on moving from a static image that is loaded from disk to a random image generated by the program so that I can test different planets.

After getting that working I'll need to fix some issues that come up when calculating normals that are on the edges of two (or three) faces. I will probably do some kind of vertex normal/tangent sharing similar to how I will share edge normals between separate quad tree nodes on the same face.

Here's a cute screenshot I took when debuggin the normals:

Friday, October 17, 2008

One Lumpy Planet

I spent a long time with a pen and paper and a calculator (and a debugger) to get a heightmap imported as a material and as a, well heightmap for the mesh.

Here's where I've ended up so far:
lumpy planet

And this is a version with wireframe overlay:
wireframe lumps

The quality of the normals is not very good because I'm using this cheap cross calculation that I saw on GameDev whilst reading this informative article on normal calculation algorithms by Jeromy Walsh. It's a very simple algorithm, but it doesn't seem to work well for me and I think I will try the MWA method next.

For the heightmap I'm using a 1025x1025 pixel grayscale 8bit png (or similiar raw). I divide that up to get the heights for all the vertices. It did not occur to me at first that quadrants share vertices (duh) so I didn't have their heightmap bounds overlap at first and that threw everything out of wack. Once I fixed that though, I discovered I need to store the heights for the neighbor vertices to calculate normals correctly. That also took a while to get the algebra to where I wasn't causing memory access errors.

Before I got the neighbor heights in there for normal calculations I got this quilt effect:

I still don't have the calculations correct for getting the correct 3d positions of neighbors across faces, but that's on the list. First, however, I have to fix the normal quality and the problem I'm having with quadrants at different levels having higher resolutions for their normals and that causing a seem - ugh. Hopefully, improving the quality of the normals and always assuming there are no neighbors at the edges will work.

I also fixed a memory leak, but I think I still have some minor ones left somewhere - but that's for later.

It's great to be able to actually fly around a bumpy planet now, even if it does have crazy normals.

Wednesday, October 15, 2008

Project Refresh

My laptop got stolen argh. Fortunately I had backups and didn't lose anything, however, after re-installing everything on the new laptop I decided to start fresh. The reasons for that were that there was a new version of Ogre out and I ran across some posts on the Ogre forums about other developers doing the same thing with Ogre.

So this time I started with the OgrePlanet approach to creating a mesh from a movable and renderable derived object and used an index cache to store the 16 possible index orders (four sides of a square and each can be stitched or not). I also started out with my own neighbor and mesh creation algorithms just so I could really understand them and after I got them working, I realized that Sean O'Neil's algorithms were better thought out (he did spend years on the project), less crash prone, and more efficient.

So I re-implemented the quad tree node neighbors and then implemented the stitching and the index cache. Next up is normals and then either a simple texture job and/or heightmap building/importing.

Planet Mesh

This image shows what the planet mesh looks like when the camera is near the surface. It's hard to see in a small picture, but the mesh has no cracks. The tri count ranges from 3,000 to 20,000 currently.

Thursday, May 15, 2008

Super Blog

This is slightly off topic, but the company I'm working for (The Supergroup)has created a blog that you should check out when you're looking for something new and interesting:
The Super Blog