12th December

Side tracked by this project: link

27th November

Found Jan Paul's DXT Compression paper which really opens the way for trying real-time compression again.

13th October

Precompressing to custom DXT format

Have some big updates from the work the last few days. I figured I'd try to precompress to a format that could easily be converted into DXT format and this has been a big success.

First I tried saving the two rgb colors in 6 bytes instead of 4. Thus allowing much better DCT compression without nearly as much loss of quality. Also I got rid of the overflow/underflow problem I had when packing parts of two colors in one byte. Still as seen in the screenshots below the quality of the Megatexture was too low. I tried to save the 4 bytes bitmap blocks in 16 bytes instead, one byte per texel, which had no big effect on quality. Then I thought what JC said about the Megatextures in Quake Wars, the compression is DCT + BTC. Hmm, BTC looks similar to how the 4 byte bitmaps are stored, in fact let's say what we got is block truncation coding here. If so, nothing else needs to be done with it as we know BTC needs to be done somewhere on a Megatexture tile and this is it. So I've arrived at a solution that is very acceptable.

The solution: for each tile put the 4 byte bitmaps into the first 4096 bytes and the DCT compressed rgb colors in the second part of the tile. During run-time read the bitmap array into one buffer, do inverse DCT and put the rgb color array into a second buffer. The conversion from "raw data" to the finished DXT texture tiles now simply involves stitching together two rgb colors and one 4 byte bitmap for each block in the DXT.

The speed increase over doing RGB->DXT compression which i did previously is huge.
On my Core 2 Duo @ 3Ghz:
Previously (RGB->DXT): 18,2MP/s (or 900us per tile)
Currently (Custom->DXT): 819,2MP/s (or 0.20us per tile)

When I first got this working it was at ~160MP/s. I've done three optimizations:
1. Replaced all the ftol()
2. The RGB888->RGB565 conversion is slow, now uses SIMD for a big improvement in speed.
3. Support for mmx/sse/sse2 in the decompression phase, uses jpeg62 lib (although won't affect Custom->DXT compression speed).

Even with the good speed it does struggle on any single core machine as the CPU is constantly at 100% regardless. Moving the ~500MB Megatexture to system memory does help quite a bit.

How far is this from what is being done in Quake Wars?
1. I do DCT on rgb's. Quake Wars Megatextures uses DCT.
2. The 4x4 pixel bitmap is similar to block truncation coding. John Carmack said you use BTC in an interview.
3. The 'raw data'->DXT conversion ratio is in the same ball park as in Quake Wars.
4. Can adjust the quality/size ratio. Same in Quake Wars.
5. Adjusting the quality/size ratio 400-500MB is expected. Quake Wars has ~500MB Megatextures.
6. Creating a Megatexture takes several hours after my latest changes. Quake Wars map shown at QuakeCon 06 took ~1,5 hours to create.
Looks similar, and hopefully it is.

Understanding the size/quality ratio. Each of these Megatextures took ~3,5 hours to complete.

Profiling all 3 threads in progam while randomly moving over terrain

A 32768x32768 Megatexture, only the 3 coarsest levels are in view.

Latest version of Megatexture Renderer. 1024x1024 Megatexture. Optimizations have brought the time for converting to DXT down to 20 micro seconds.

Looking at the level of detail in a 4096x4096 Megatexture.

Here we have split the tile in two; bitmap blocks and rgb colors, and doing DCT on rgb colors only. The black texels are alpha's, a bug later fixed where if the two color values were equal after decompression you had to set the bitmap block to point to first color (set whole bitmap block to 0). Except for that the quality is acceptable.

Using 3 bytes for rgb colors, DCT compression on whole tile. Noticeable problems with the bitmap blocks having too big error after decompression. Even using one byte per pixel for the bitmap block did not help (4 possible values in each byte).

4th October

Profiling the RGB->DXT compression thread which obviously is 10x as slow as it needs to be somehow...

I've discovered two important things:
1. Run-time DXT compression is too slow.
2. Run-time DCT decompression is fast enough.

Since we know Quake Wars uses DXT textures, somehow the Megatexture in Quake Wars is DXT tiles, compressed with something in some way to achieve ~500MB. Probably DCT/BTC in some form. From previous tests I've also found that doing DCT decompression during run-time is fast enough.

The first DXT Megatexture w/DCT compression, using quality level 100 which should be about lossless. The red/green squares happens because of lossless compression, as far as i can tell the bits get set at the upper values of red and green components of the two DXT colors.

Quality level 85, the overflow/underflow of bits in the red and green channels are unacceptable. This is the quality level I'd be interested in using after having figured out the solutions.

10th September

Currently using jpeg Megatexture compression, with YCC->RGBA conversion and inverse DCT on CPU. The RGBA->DXT conversion is handled by the CPU it seems (using D3DXLoadSurfaceFromSurface); using DXT video/cache textures results in stuttering when moving and is unacceptable currently. The YCC->RGBA and IDCT is quite CPU intensive, moving these operations onto the GPU should be possible and would be interesting to try out.

Using DXT textures results in ~150 more FPS compared to when RGBA textures is used. The major problem now is the conversion to DXT as I know it can be done efficiently (used in QW...). Might convert the program to OpenGL and try out the texture compression extension.

In the latest version of the jpeg Megatexture I'm using a single table instead of having one table for each tile, thus dropping the size of a 32768x32768 Q90 Megatexture from 492.8MB to 443.8MB, 10% reduction.

The original Megatexture size is 87.4MB, the DXT compressed Megatexture is 11MB and finally you see the different file sizes depending on the quality of the Megatexture with the jpeg copmression. I found the minimum acceptable quality setting was 75, 85 is probably what I'll use.

Both of the screenshots below are from a 16384x16384 Megatexture with quality setting 90. The Size on disk is 128.6MB.

26th August

Very early results from using jpeg compression to create final Megatexture
Diffuse + Normal map, each 5.6GB, is combined then compressed giving a final megatexture size of 289MB for a 32768x32768 Megatexutre. Finally compressing with winzip which I guess you'll be using for Quake Wars gives a final size of ~176MB, compression ratio of ~95% from original 5.6GB Megatexture. That is a pretty huge improvement in compression over my previous version which compressed to DXT (always ~700MB).

New local map for Megatexture

Previous local map for Megatexture

Earlier screens


Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 Unported License.