JLI Spieleprogrammierung Foren-Übersicht JLI Spieleprogrammierung

 
 FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen 
 medals.php?sid=6f70606967e523d95656fce8f76b7852Medaillen   RegistrierenRegistrieren   ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin 

DDS File Format und S3TC

 
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Tutorials
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
David
Super JLI'ler


Alter: 39
Anmeldedatum: 13.10.2005
Beiträge: 315

Medaillen: Keine

BeitragVerfasst am: 13.11.2005, 13:16    Titel: DDS File Format und S3TC Antworten mit Zitat

Hi!

Ich will heute ein wenig über den S3 Texture Kompression (S3TC) Algorithmus erzählen. Außerdem gibts einen kurzen Überblick auf das DDS Dateiformat, welches DXTn (oder S3TC) als Kompressionsalgo unterstützt.

Das DDS Dateiformat

Bei DDS, oder auch Direct Draw Surfaces, handelt es sich um ein Dateiformat welches das Speichern von Texturen, Cubemaps und Volumetrischen Texturen plus der dazugehörigen Mipmaps erlaubt.

Der Grundlegende Aufbau einer DDS Datei

Arrow DDS Header
Arrow Hauptdatenblock
Arrow Angehängter Datenblock

DDS Header

CPP:
struct DDSHeader
{
   DWORD   Magic;

   DWORD   Size;
   DWORD   Flags;
   DWORD   Height;
   DWORD   Width;
   DWORD   PitchOrLinearSize;
   DWORD   Depth;
   DWORD   MipMapCount;
   DWORD   Reserved1[ 11 ];

   struct
   {
      DWORD   Size;
      DWORD   Flags;
      DWORD   FourCC;
      DWORD   RGBBitCount;
      DWORD   RBitMask;
      DWORD   GBitMask;
      DWORD   BBitMask;
      DWORD   RGBAlphaBitMask;
   } ddfpPixelFormat;

   struct
   {
      DWORD   Caps1;
      DWORD   Caps2;
      DWORD   Reserved[ 2 ];
   } ddsCaps;

   DWORD   Reserved2;
};


In den Kopfdaten stehen diverse Bildinformationen. Wie Breite, Höhe, Bittiefe, Kompression usw.

Arrow DWORD Magic;

Diese 4 Bytes geben dienen also Identifikation für DDS Dateien. Sinnigerweise ist dieser Wert festgelegt auf die Bytes 'D', 'D', 'S', ' '.

Arrow DWORD Size;

Dieser Wert enthält die Größe der gesammten Struktur. Er sollte also immer auf 124 gesetzt sein

Arrow DWORD Flags;

Hier können bestimmte Bits gesetzt sein um die angegebenen Werte zu Identifizieren. sollte hier Beispielsweise das Bit für DDS_WIDTH gesetzt sein, ist die Breite des Bildes angegeben. Allerdings gibt es eine Anzahl Bits welche immer gesetzt sein müssen, das sind: DDSD_CAPS, DDSD_PIXELFORMAT, DDSD_WIDTH, DDSD_HEIGHT.

Arrow DWORD Height;

Hier wird die Höhe der Haupttextur angegeben.

Arrow DWORD Width;

Hier wird die Breite der Haupttextur angegeben.

(Beide Angaben sind in Pixel. Die Dimensionen der MipMaps können berechnet werden, wenn man die Dimensionen des vorhergehenden MipMaps durch zwei teilt

Arrow DWORD PitchOrLinearSize;

Falls die Daten unkomprimiert vorliegen ist dies die Anzahl der Bytes pro Scanline. In diesem Fall sollte in den Flags DDS_PITCH gesetzt sein.
Falls die Bilddaten komprimiert sind, handelt es sich um die Anzahl der gesammten Bytes für die Bilddaten. Hier sollte DDS_LINEARSIZE gesetzt sein.

Arrow DWORD Depth;

Gibt die "Tiefe" für Volume Texturen an. Im dem Falle das es sich um eine Volume Textur handelt sollte DDS_DEPTH in den Flags gesetzt sein.

Arrow DWORD MipMapCount;

Dies gibt die Anzahl der Mipmaps an, welche in den "angehängten Datenblock" gespeichert wurden. Falls hier eine Angabe gemacht sein sollte, muss in den Flags das Bit für DDSD_MIPMAPCOUNT gesetzt sein.

Arrow DWORD Reserved1[ 11 ];

44 Bytes reserviert. Momentan noch ohne Funktion

Arrow ddfpPixelFormat.Size

Gibt die Größe der Struktur (ddfpPixelFormat) an. Hier sollte immer der Wert 32 stehen

Arrow ddfpPixelFormat.Flags

Wie in der Hauptstruktur werden auch hier diverse Flags gesetzt um mögliche Vorhandene Informationen zu identifizieren. Für unkomprimierte RGB Bilddaten sollte hier das Bit für DDPF_RGB gesetzt sein. Falls die Bilddaten Komprimiert sind ist hier DDPF_FOURCC gesetzt.

Arrow ddfpPixelFormat.RGBBitCount

Falls die Daten unkomprimiert sind, wird hier die Bittiefe derselben angegeben. Im normalfall 16, 24 oder 32.

Arrow ddfpPixelFormat.RBitMask
Arrow ddfpPixelFormat.GBitMask
Arrow ddfpPixelFormat.BBitMask

Dies gibt die Bitmasken für den Rot, Blau und Grünkanal an. Für 32 Bit Farbtiefe sind diese 0x00ff0000, 0x0000ff00, and 0x000000ff.

Arrow ddfpPixelFormat.RGBAlphaBitMask

Dies gibt die Bitmaske für den Alphakanal an. für 32 Bit Farbtiefe ist diese 0xff000000. Im Falle das hier eine Angabe steht sollte das Bit für DDPF_ALPHAPIXELS gesetzt sein.

Arrow ddsCaps.Caps1

Hier sollte immer das Flag DDSCAPS_TEXTURE gesetzt sein. Falls die Datei Mipmaps enthält ist hier zusätzlich DDSCAPS_MIPMAP gesetzt. Sollten irgendwelche Daten, auser einem einzelnen Surface, gespeichert sein, wird hier das Bit für DDSCAPS_COMPLEX gesetzt.

Arrow ddsCaps.Caps2

Falls es sich um eine Cubemap handelt, ist das Bit für DDSCAPS2_CUBEMAP gesetzt. Auserdem für jede Seite die entsprechenden Bits (DDSCAPS2_CUBEMAP_POSITIVEX, DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY, DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ).
Falls es sich um eine Volume Texture handelt ist hier DDSCAPS2_VOLUME gesetzt

Arrow ddsCaps.Reserved[ 2 ]

8 Byte bislang ungenutzer Platz

Arrow Reserved2

Ungenutzer Platz ohne momentane Funktion

Hauptdatenblock
Hier stehen die (komprimierten/unkomprimierten) Daten für das Hauptsurface

Angehängter Datenblock
Hier stehen die (komprimierten/unkomprimierten) Daten für die angehängten Surfaces

Flags

CPP:
#define DDSD_CAPS               0x00000001
#define DDSD_HEIGHT               0x00000002
#define DDSD_WIDTH               0x00000004
#define DDSD_PITCH               0x00000008
#define DDSD_PIXELFORMAT         0x00001000
#define DDSD_MIPMAPCOUNT         0x00020000
#define DDSD_LINEARSIZE            0x00080000
#define DDSD_DEPTH               0x00800000

#define DDPF_ALPHAPIXELS         0x00000001
#define DDPF_FOURCC               0x00000004
#define DDPF_RGB               0x00000040

#define DDSCAPS_COMPLEX            0x00000008
#define DDSCAPS_TEXTURE            0x00001000
#define DDSCAPS_MIPMAP            0x00400000

#define DDSCAPS2_CUBEMAP         0x00000200
#define DDSCAPS2_CUBEMAP_POSITIVEX   0x00000400
#define DDSCAPS2_CUBEMAP_NEGATIVEX   0x00000800
#define DDSCAPS2_CUBEMAP_POSITIVEY   0x00001000
#define DDSCAPS2_CUBEMAP_NEGATIVEY   0x00002000
#define DDSCAPS2_CUBEMAP_POSITIVEZ   0x00004000
#define DDSCAPS2_CUBEMAP_NEGATIVEZ   0x00008000
#define DDSCAPS2_VOLUME            0x00200000


Die Bedeutung der Flags ist jeweils in unter DDS Header zu finden.

Berechnen der gesammten Datengröße

Für unkomprimierte Bilddaten ist dies nicht weiter kompliziert. Der gesuchte Wert ist die Summe der einzelnen Größen für jedes Surface. Für ein Surface wird die Größe Breite*Höhe*Tiefe berechnet.

Für komprimierte Bilddaten sieht die Berchnung für ein einzelnes Surface etwas anderst aus. Hier wird die Breite mit ( Breite+3 ) >> 2 und die Höhe mit ( Höhe+3 ) >> 2 berechnet. Die Gesammtgröße ist dann dementsprechend:( ( Breite+3 ) >> 2 ) *( ( Höhe+2 ) >> 2 ).

S3TC

Die S3 Texture Kompression unterstützt verschiedene Kompressionsarten:

Arrow DXT1
Arrow DXT2
Arrow DXT3
Arrow DXT4
Arrow DXT5

DXT1

Dies ist die "kleinste" Variante. Hier werden 16 Pixel in 64 Bit Output gepresst. Dieser setzt sich zusammen aus zwei 16 Bit RGB565 Werten und einer 4x4 großen, 2 Bit, Lookuptabelle.

Sollte der erste Farbwert (C0) größer als der zweite Farbwert (C1) sein, werden die Farbwerte C2 und C3 folgendermasen berechnet:

Code:
C2 = ( 2*C0 + C1 ) / 3
C3 = ( C0 + 2*C1 ) / 3


Falls C0 kleiner oder gleich C1 sein sollte wird nur der Wert für C2 berechnet. C3 ist Transparent.

Code:
C2 = ( C0+C1 ) / 2
C3 = 0


Die Lookuptabelle enthält Werte zwischen 0 und 3 (2 Bit). Wobei 0 für den Farbwert 0 steht, 1 für den Farbwert 1 usw...

Was evtl noch wichtig ist zu wissen. Wie man aus 16 Bit RGB565 Werten ein 24 Bit R8G8B8 Wert bekommt.

Bei RGB565 werden die Farbwerte in 16 Bit gepackt. Wobei Rotkanal und Blaukanal jeweils 5 Bit belegen, der Grünkanal aber 6 Bits.

Code:
RRRRR GGGGGG BBBBB


Im R8G8B8 Format belegt jeder Kanal 8 Bits:

Code:
RRRRRRRR GGGGGGGG BBBBBBBB


Mit ein bisschen "Bitsumherschieben" kann man also ganz leicht den entsprechenden R8G8B8 Wert von einem RGB565 Wert berechnen.

CPP:
R = ( ( c1 >> 11 ) & 0x1f ) << 3;
G = ( ( c1 >> 5  ) & 0x3f ) << 2;
B = ( c1           & 0x1f ) << 3;


DXT2, DXT3
Bei DXT2/3 werden 16 Pixel in 128 Bits Output gespeichert. Dieser setzt sich zusammen aus einen 64 Bit Alphakanal und dem, von DXT1 bekannten, 64 Bit Farbblock. Bei DXT2 werden die Farbwerte mit den entsprechenden Alphawerten "Vormultipliziert".

DXT4,DXT5
Bei DXT4/5 werden 16 Pixel in 128 Bits Output gespeichert. Dieser setzt sich aus 64 Bit Alphakanal Daten (zwei 8 Bit Alphawerte (a0, a1) und eine 4x4 3 Bit Lookuptabelle) und dem aus DXT1 bekannten 64 Bit Farbblock zusammen.

Falls a0 größer als a1 ist, werden sechs weitere Alphawerte berechnet.

Code:
Ai = ( ( 8-i )*a0 + ( i-1 )*a1 + 3 ) / 7


Wobei i zwischen 2 und 7 liegt.

Falls a0 kleiner oder gleich a1 ist werden vier weitere Alphawerte berechnet.

Code:
Ai = ( ( 6-i )*a0 + ( i-1 )*a1 + 2 ) / 5


Wobei i zwischen 2 und 5 liegt. a6 ist in den Fall 0 und a7 ist 255.

Bei DXT4 werden die Farbwerte mit den entsprechenden Alphawerten vormultipliziert.

So, ich hoffe das einige nutzen aus dem Tutorial ziehen können, oder vielleicht sogar etwas neues dazugelernt haben.

grüße
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Tutorials Alle Zeiten sind GMT
Seite 1 von 1

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.


Powered by phpBB © 2001, 2005 phpBB Group
Deutsche Übersetzung von phpBB.de

Impressum