Current version: 0.16.x
»GeeXLab homepage

Current version: 1.19.0
»FurMark homepage
»FurMark 1.9.x Submissions

GPU Caps Viewer
Current version:
»GPU Caps Viewer homepage
»GPU DB Submissions

GPU Shark
Current version:
»GPU Shark homepage

»JeGX's HackLab

Geeks3D's Articles
»GPU Memory Speed Demystified

»Multi-Threading Programming Resources

»GeForce and Radeon OpenCL Overview

»How to Get your Multi-core CPU Busy at 100%

»How To Make a VGA Dummy Plug

»Night Vision Post Processing Filter

PhysX FluidMark
Current version: 1.5.2
»FluidMark homepage
»FluidMark 1.4.x Submissions

Current version: 0.3.0
»TessMark homepage

Current version: 0.3.0
»ShaderToyMark homepage
»ShaderToyMark Scores

Current Version: 1.23.0
»Libraries and Plugins
»Online Help - Reference Guide
»Codes Samples

3D Graphics Search Engine:

The Geeks Of 3D

Normal Map Compression
Swizzled DXT5 - ATI 3Dc

By Jerome Guinot aka 'JeGX' - jegx [at] ozone3d (dot) net

Initial draft: March 11, 2006
Update: March 16, 2006

[ Index ]

Introduction | Page 2 | Page 3 | Page 4 | Conclusion

5 - Conclusion

Thanks to the Swizzled DXT5 technique (injection of red channel into alpha channel and use of DXT5 compression), we get a normal-map that can be used in a wide range of situations and particularly in those where the specular highlights are small or their quality is not important. In all other cases where the normal-map compression must give good results, the use of ATI's 3Dc compression format is inevitable. The only drawback of this format is that only AT Radeon X800 and up are 3Dc-ready. So for more realism and even if graphics controllers embark more and more memory, use compression, it's worth while! (see S3TC Comparative Table for compression ratio).

6 - O3TC Format Structure and OpenGL Demo

The O3TC format is produced by the DXTViewer and is really simple to load. You will find below the O3TC file structure, a portion of code that shows you how to load compressed textures and a pure Win32 / OpenGL demo (complete Visual C++ 6.0 project) is provided. It shows how to load a texture in the S3TC/O3TC format (texture dims are 2048x2048, so I hope you have a decent graphics controller since I did not add all hardware checks...) and how to setup the texture trilinear filtering. It's sheer bliss!

DWORD o3tc_data_size;

// Magic number: Must be O3TC.
char magic_number[4];

// Must be filled with sizeof(O3TC_Header).
DWORD header_size;

// Version. Currently: 0x00000001.
DWORD version;

// Must be filled with sizeof(O3TC_Chunk_Header):
DWORD chunk_header_size;

// Reserved
DWORD reserved1;

// The size of the data chunk that follows this one.
DWORD size;

// Reserved
DWORD reserved2;

// Pixel format:
// - O3_TC_RGB_S3TC_DXT1 = 1
// - O3_TC_RGBA_S3TC_DXT5 = 4
// - O3_TC_ATI3DC_ATI2N = 16
DWORD internal_pixel_format;

// Texture width.
DWORD width;

// Texture height.
DWORD height;

// Texture depth.
DWORD depth;

// Number of mipmaps.
DWORD num_mipmaps;

// The texture name.
char texture_name[128];

// The texture id.
DWORD texture_id;

// raw array of BYTE: this represents the
// real compressed data.
BYTE *pCompressedPixmap;

The first 4 bytes (data_size) give the total size of the data (headers included) held in the O3TC file: o3tc_data_size = file_size - 4. These first four bytes can be skipped. Next, the file reading is quite simple:

1 - O3TC_Header reading in order to check the magic_number and file version.

2 - O3TC_Chunk_Header reading in order to retrieve texture dimensions (width and height), number of mipmaps and compression type (DXT1 ou DXT5).

Direct reading of compressed data chunk. The size of this chunk is given by O3TC_Chunk_Header.size. Next, this chunk has to be loaded into the graphics memory using the glCompressedTexImage2D() function. Normally, this chunk is identical to that held in a DDS file.

Here is, extracted from the OpenGL demo (see void cDemo::setQuadTexture()), the piece of code that loads the compressed data chunk:

offset = 0;
size = 0;
for( mip=0; mip<=numMipMaps && (width || height); mip++ )
	if (width == 0)
	  width = 1;
	if (height == 0)
	  height = 1;
		blockSize = 16;
		internal_format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
	else if(compression_type==O3_TC_RGB_S3TC_DXT1)
		blockSize = 8;
		internal_format = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;

	size = ((width+3)/4)*((height+3)/4) * blockSize;
	glCompressedTexImage2D( GL_TEXTURE_2D,
	width, 	height, 
	pCompressedPixmap + offset);

	offset += size;
	width >>= 1;
	height >>= 1;

7 - Further Resources

8 - Downloads

Download the accompanying project for Demoniak3D
Update: March 16, 2006

*** These source codes require Demoniak3D to work properly.
Demoniak3D is available here: [:: Demoniak3D Demo-System ::].

Visual C++ 6.0 Project - Pure Win32/OpenGL Demo - S3TC / O3TC
Update: March 7, 2006

[ Index ]

Introduction | Page 2 | Page 3 | Page 4 | Conclusion

GeeXLab demos

GLSL - Mesh exploder

PhysX 3 cloth demo

Normal visualizer with GS

Compute Shaders test on Radeon

Raymarching in GLSL

Geeks3D latest news

Geeks3D forum news

»Texture DataPack #1
»Asus Silent Knight CPU Cooler
Page generated in 0.0067880153656006 seconds.