Quick update. I converted the planet to use the planet patches. It still looks really with absolutely no subdivisions. The first two images show the planet in medium quality (9 vertices per edge) and second two are at the highest quality (129 vertices per edge). The new system handles 524288 triangles with ease (131072 for planet, same for atmosphere and the second pass rendering of edges). Since the data stays on the card it's very optimal. I can probably pump it up a lot and it won't hitch. The other great thing is that this system is extremly fast at setting up the structure, the overall triangle structure is easier to deal with since I don't have to deal with situations where where a triangle is subdivided but it's points aren't updated yet.

One issue that you can notice a bit in the second picture is that the new system don't distribute the triangles as evenly around a sphere and the old system did. I'm not very worried about that since it shouldn't matter once the patches are subdivided a bit.

First win: I did some stress testing of the new patches. It seems to be almost 20% faster!! Before I could get just under 80 million Triangles per second and that was with one draw call per 131072 triangles. Now I'm getting around 95 million triangles and that's with around 32 draw calls per planet, each draw call is limited to 16384 triangles (max patch resolution). I do the testing by adding planets until the framerate begins to drop below 60 so these are the number of triangles while maintaining 60FPS, also they are textured, I haven't been able to figure out why it's rendering black.

Second win: Since the triangle hierarchy is a lot shallower the generation time for the triangles is incresed probably atleast a thousand fold. Before it would take around 10 minutes to generate a planet with a resolution of 131072 triangles. To do the same doesn't even affect framerate anymore.

Third win: The code is amazingly simpler. Before I had cases where a triangle's point may not all be updated which could cause cracking and I had to take a lot of special care to make sure everything subdivided smoothly. Now I just have to worry that no patch is more than 1 level of subdivision different than it's neighbours.

Finally: I was also able to see the cost of the atmoshperic shader. I can keep 60FPS at max resolution using 3 textured planets (1.5 million triangles total). At max resolution the proper planet and it's atmosphere will drop the framerate down to 30fps (1 million triangles). This approximately says that the Vertex shader I'm using is 3 times as expensive as the fixed pipeline (1.5mil at 60fps = 3 mil at 30fps) which actually doesn't sound that bad now that I think about it.

Quick picture description: First two are the planet at medium resolution (9x9x9), second two are at max resolution (128x128x128), The last two are the stress test, first without the shader, second with it.

So I've created a nice triangle patching system similar to the patches used in geomipmapping. By my calculations they are slightly less efficient since each vertex list will have duplicate edges along the edges. Also stripping won't be as easy. The good news is that overall I should be able achieve the same level of detail as geomipmapping with overall less triangles since I only have to subdivide half as much as a time. In the first picture you can see the patch, which is not very interesting itself but in thefollwing images you can see how it can sit side by side with neighbour paths of lower detail. This is good because I can have 7 static index buffers per detail level. The other big win by moving to patches is that I can generate the vertex buffer once and leave it on the video card wich will be a lot faster than the previous ROAM-like implementation. Enough talking, have some pictures:

Quick update. Threw together a quick triangle stress test. Flat colored planets, 131k triangles each. I can throw 10 of them at my ATI X1600 and it can still maintain 60FPS. This gives me a total triangle throughput of just under 80 Million per second, and it's a triangle list so unless they are caching results (which they can only do once per planet since each on is in a different position) that's a total vertex throughput of around 240 Million per second.

TPS = Triangles per second. stresstest.jpg

It looks more impressive than it is. I simply wrapped a texture around half the sphere. It repeats on the other side. Threw in a simple plasma generation for the texture. I gotta figure out how to properly texture this. I might have to move to Triangle Patches sooner than later (more on that if/when I do it).


I always read that T-Junctions were bad. I figured as long as the point causing the T-Junction was interpolated between the other two point it should look fine. Well... I was wrong. As seen in today's pictures the not only were they T-Junctions causing color problems they also cause seems on ATI cards (well atleast my ATI card).

The good thing was it was really easy to fix. There's only a maximum of 6 configurations the tesselation needs to be to fix up the T-Junctions so it was fairly simple to just add a few extra triangles to the list.

In other news I've modified the system to create a single vertex buffer from the unique point list so I can use index buffers. Also for this test I simply subdivided to a certain level of complexity instead of doing camera based subdivision so the index buffer isn't re-created every frame either. When I subdivide a lot I'm able to push 15 million triangles per second, and this is through a decently complex vertex buffer. Only when I render all 260k triangles (130k for planet, 130k for atmospher) twice (a second time for edges) does the frame rate dip a little below 60fps. This is also in C#, though since I have a static vertex and index buffers that shouldn't matter (keyword shouldn't). This is way beyond the worst case for the planet. The atmosphere should never have that many triangles.

I mentioned that the seems only appear on ATI cards, I have to systems that I develop on, one with a Geforce 6600GT and the other has an ATI X1600 Mobility. Go here for full specs. They're not the best but I'd prefer what I'm working on to be as backwards compatable as possible.

Enough ranting for today. Quick walkthrough the pretty pictures. Far left is simple the old version with the TJunctions. The next picture I just highlight the seem. Next is the Edge overlay to see the actual triangles. Then the T-Junctions are fixed and after I show the edges of the fix so you can see how it's patched up. The two images on the bottom row are the super tesselated versions with and without the edges shown.

It's hot. Working is a bit difficult. I'm playing around with different control schemes and trying to optimize the mesh representation (instead of creating a huge vertex buffer every frame). I've made a neat change that adjusts the camera orientation relative to your position on the planet (so whereever you are feels like up) while you're in the atmosphere. When you leave the atmosphere the camera orients to the plane of the solar system (currently 0, 1, 0). Hard to show that so no screenshots. It will be hot tomorrow too so likely not much advancement.

I'll update this with more info later. Short story: A comment I read on another site left me thinking while I was asleep: Prioritize triangle subdivision based on screen space movement. I simplified this to a sorted list based on movement perpendicular to the camera forward vector. Here's the results.


To explain a bit better. When a triangle subdivides without updating it's three edges are split in half. The new points created are just interpolated so the screen space movement should be 0. I then get the position if that point was updated and test the difference between the two vectors against the up and right vector of the camera. I add the two magnituded and the final output is what I use to sort the order of triangle subdivision. To narrow down the search I simply ignore backfacing triangles. This can be bad because there's a change that subdivided version may appear above the horizon. I'll worry about that later.

A quick explanation for the pictured. The first one is simply what the planet looks like from far away now. The second is what the back of the planet looks like, it's completly un-subdivided. The third picture is a view from the planet surface and the last is the same view from over head to see how the subdivision worked.

Well this is a pleasent surprise. I started tinkering with Sean O'neils sample code about atmospheric scattering [Edit 01/2008 - but his site has since gone away). His implementation was in GLSL and I'm working with DirectX (.NET FTW). I actually managed to copy and paste the shader and fix it up and it mostly works. It's amazing what some nice shaders can do to make things look nicer. I think this is pretty good for my first HLSL program ;)