Texturen

Texturen

Dokumentation Alle Texturen liegen als GIF-Dateien (Graphics Interchange Format) vor. Sie werden mit dem Converter eingelesen und unkomprimiert in einer eigenen Datenstruktur abgelegt. Das GIF-Format ist ein guter Kompromiss zwischen Dateigröße, Farbumfang und Zugriffsgeschwindigkeit.

Jedes Pixel wird durch einen Bytewert repräsentiert. Dieser zeigt auf einen Eintrag in einer Farbtabelle:

Image mit Farbpalette

Die Palette besteht aus 256 Zeilen mit je einem Byte für die Farbanteile Rot, Grün und Blau. Damit kann ein GIF-Bild maximal 256 Farben beinhalten.
Ausserdem kann ein Indexwert als transparent gekennzeichnet werden. Alle Pixel die diesen Transparenzindex haben, werden dann einfach nicht gezeichntet.

Programmatisch sind die Indexwerte in einem simplen byte- bzw. unsigned char-Array abgelegt: indexArrax = new BYTE[width * height]

Ebenso die Farbpalette: BYTE rgbLUT[256*3]

Der Zugriff auf einen Pixelindex erfolgt über die Funktion:
pixelIndex(u,v) = indexArray[v << shiftval + u]

Wobei shiftval eine vorberechnete Konstante ist:

Width/Height shiftval
32 5
64 6
128 7
256 8
512 9

Mit diesem Trick spart man sich die Multiplikation die prinzipiell immer langsamer ist als die binäre Shiftoperation. Nachteil: Die Texturgröße ist immer eine Zweierpotenz. Diese Restriktion gilt übrigens auch für moderne 3D-Graphikkarten. Einige können sogar nur mit quadratischen Texturen umgehen.

Die Farbwerte werden anschließend wie folgt ermittelt:

lutIndex = (pixelIndex << 2) + pixelIndex

Damit gilt:

R=rgbLUT[lutIndex]
G=rgbLUT[lutIndex+1]
B=rgbLUT[lutIndex+2]

Eigentlich sollte man meinen: Alles viel zu kompliziert. Wieso die Ablage in einem einfachem Wertevektor, wo doch ein zweidimensionales Array nahezu ideal wäre? Nun, der Knackpunkt ist die Performanz. Der Zugriff auf die Elemente eines einfachen Array ist schneller. Ausserdem ist das Erzeugen den Datenstrukturen wesentlich einfacher, als der Aufbau von n-dimensionalen Array mit dynamischer Größe.

Sprites

Dokumentation Im Gegensatz zu Texturen werden Sprites als Truecolor Images plus Alphakanal gespeichert. Ursprünglich sollte das PNG-Format verwendet werden, doch leider konnte Java zu dem Zeitpunkt das Format nicht importieren. Also habe ich mich für das Windows Bitmap Format entschieden, was seit Version 4 auch einen Alphakanal unterstützt.

Die Bildinformationen liegen prinzipiell als RGBA-Werte vor. Für jedes Pixel werden also vier Bytes benötigt. Damit lassen sich ca. 16 Millionen Farben darstellen. Ausserdem kann für jedes Pixel die Transparenz nahezu stufenlos (0 bis 255) eingestellt werden.

RGBA-Image

Auch hier werden die Pixelinformationen in einem byte- bzw. unsigned char-Array abgelegt: pixelArray = new BYTE[width * height * 4]

Der Zugriff auf ein einzelnes Pixel erfolgt über die Funktion:
pixelIndex(u,v) = pixelArray[v << shiftval + u]

Wobei die einzelnen Farbkomponenten so ermittelt werden:

R=pixelArray[pixelIndex]
G=pixelArray[pixelIndex+1]
B=pixelArray[pixelIndex+2]
A=pixelArray[pixelIndex+3]