Basically, from what I can tell, the possible mipmaps required for a given pixel (ignoring rotation of a triangle) is, in the best case, the same as trilinear filtering. That is, the highest res mipmap required is that which is required if the triangle was facing the viewer, and the lowest res would be if the triangle was edge on to the viewer-regardless of distance from the camera. So, this is a problem that I've got two possible solutions for, which I've described in the paragraph after next. Before I go in, I want to introduce some terminology that I'll be using.
The data that I want to store is essentially 4D; that is, a 2D layout of 2D images. The layout's axes I describe as primaries and secondaries. Essentially, a primary refers to data from the main, uncropped texture, and the nth primiary refers to data from the nth level (0-based) of the main texture. A secondary refers to a cropped chunk of the primary, and the nth secondary refers to a portion of data from the nth level (0-based) of the nth primary. So, the 0th secondary uses data directly from the 0th primary, and has the greatest detail of all of the secondaries. Lastly, level (again, 0-based) simply refers to the mipmap level of a secondary. So, the 0th level of the 0th secondary uses data from the 0th primary. Another example is that the 1st level of the 0th secondary uses data from the 1st primary. However, the 0th level of the 1st secondary uses data from the 1st primary as well. The difference is that the 1st level of the 0th secondary is 256x256 whereas the 0th level of the 1st secondary is 512x512, and hence covers a larger area than the 1st leve of the 0th secondary.
Now that that's out of the way, here's my problem:
How to take full advantage of anisotropic filtering while minimizing the amount of data is stored on the GPU and/or passed over the AGP bus.
Solution 1: Alpha testing, overdraw, and way too much of both.
This method requires only 4 levels on each secondary, and only the top 3 need updates. The four levels consist of the following data (only talking about the 0th secondary in this example, which actually has only 3 levels in total; I'll get to that later):
-0th level has data from the 0th primary, with an alpha value of 1.
-1st level has data from the 1th primary, with an alpha value of 1.
-2nd level is filled with unseen data, with an alpha value of 0.
What happens in this case, is that data from the 0th and 1st levels get linearly filtered between each other properly (due to the fact that each aniso tap is essentially a trilinear lookup). However, when data from the 1st and 2nd levels start blending, the 0th level has no more significance on the pixel. As a result, we want to stop drawing on that pixel. However, since the alpha value becomes non-one when the 2nd level starts influencing the image, we can simply cull the pixel by doing an alpha test, where pixels with non-one alpha values are dumped. When we render the next secondary, we only want data where the 1st level (same data as the 2nd level of the 0th secondary, remember) affects the image. So, we want to cull pixels where the 1st level has no effect: this is where only the -1th level and the 3rd level influence the image, so we repeat the same process as the first secondary with those pixels. Obviously though, we don't have a -1th level, so we have the drawing occur in reverse: the geometry is rendered with the last secondary drawn first, so that it replaces value that we don't want, and culls values we don't want affecting the rest of the image. IF you need a visual idea of this, here we go:
(image from Toms Hardware, as a part of their review of the X800 hardware)
Essentially, the 1st secondary covers data where there's any green close to the camera. The 0th secondary covers the first bit of non-coloured texture, and stops when a little bit of green exists.
Don't worry if you got lost along the way there, I probably won't be using that method, instead going with:
Solution 2) Just full up each secondaries mipmap chain, dammit!
Instead of just pussying out with only three relevant levels to each secondary (or two for the 0th secondary) and alpha culling the parts that would dare need other mipmap levels, the full mipmap chain for a secondary is stored and loaded, so that the geometry is drawn exactly as submitted, instead of some pixels being clipped away in the process, and rerendering those areas. Basically, a chunk of geometry is drawn, and the secondary where the 0th level mipmap would've been the primary's visible mipmap in that location in the best case is bound as the active texture. I was reluctant to approach this solution first since I was concerned about the extra updating required for each level of each secondary. However, as I reflected on it more, I can likely guess what mipmaps a piece of geometry will be using and only upload those part to the GPU by using data such as the angle between the triangle normal and the viewdirection and the distance together (wait, isn't this getting kind of close to memory virtualization?) instead of just updating all 10 levels of each secondary. That way, only some texture memory is wasted, instead of oodles of fill rate being lost because early z was turned off because alpha testing was turned on.
By the way, one thing that I may want to try out later is permanent decals. If the entire landscape can be theoretically unique the whole way, I wonder how practical it would be to update, say, the data of the primary level when an explosion or something occurs so that the terrain is permanently scarred. In theory, this could be used so that a person could, like, shoot a rocket from the ground on the other end of the map at a mountain far in the distance, then walk all of the way there blasting a ton of other crap in the process, and when he arrived, he'd see the damage he caused. I don't know about you guys, but I think the idea is cool enough to warrant a bit of research once I have RFBTextures fully working.