Procedure SwapY(Var Pixels : pBytes; xSize,ySize : Integer);
Type
TRGB = record
R,G,B,A : Byte;
end;
Var
Temp : array of array of TRGB;
x,y,c : integer;
begin
SetLength(Temp,xSize,ySize);
c := -1;
for x := 0 to xSize-1 do
for y := 1 to ySize do
begin
Inc(c);
Temp[x,ySize-y].R := Pixels[c];
Inc(c);
Temp[x,ySize-y].G := Pixels[c];
Inc(c);
Temp[x,ySize-y].B := Pixels[c];
Inc(c);
Temp[x,ySize-y].A := Pixels[c];
end;
c := -1;
for x := 0 to xSize-1 do
for y := 0 to ySize-1 do
begin
Inc(c);
Pixels[c] := Temp[x,y].R;
Inc(c);
Pixels[c] := Temp[x,y].G;
Inc(c);
Pixels[c] := Temp[x,y].B;
Inc(c);
Pixels[c] := Temp[x,y].A;
end;
SetLength(Temp,0,0);
end;
function LoadDDS(Stream: TStream; Var Texture : Cardinal; Const NoPicMip : Boolean; Var Width,Height : Integer): boolean;
var
hdr: TDDSHeader;
mipMapCount, x, y, xSize, ySize: Cardinal;
li: ^TDDSLoadInfo;
data,pixels: PBytes;
unpacked: PGLuints;
size, ix, zz: Cardinal;
palette: array[0..255] of Cardinal;
begin
result := false;
// DDS is so simple to read, too
Stream.Read(hdr, sizeof(hdr));
if (hdr.dwMagic<>DDS_MAGIC) or (hdr.dwSize<>124) or
((hdr.dwFlags and DDSD_PIXELFORMAT)=0) or ((hdr.dwFlags and DDSD_CAPS)=0) then exit;
if (addr(glTexParameteri)=NIL) or
(addr(glCompressedTexImage2D)=NIL) or
(addr(glPixelStorei)=NIL) then exit;
xSize := hdr.dwWidth;
ySize := hdr.dwHeight;
if (PF_IS_DXT1(hdr.PixelFormat)) then li := @loadInfoDXT1 else
if (PF_IS_DXT3(hdr.PixelFormat)) then li := @loadInfoDXT3 else
if (PF_IS_DXT5(hdr.PixelFormat)) then li := @loadInfoDXT5 else
if (PF_IS_BGRA8(hdr.PixelFormat)) then li := @loadInfoBGRA8 else
if (PF_IS_BGR8(hdr.PixelFormat)) then li := @loadInfoBGR8 else
if (PF_IS_BGR5A1(hdr.PixelFormat)) then li := @loadInfoBGR5A1 else
if (PF_IS_BGR565(hdr.PixelFormat)) then li := @loadInfoBGR565 else
if (PF_IS_INDEX8(hdr.PixelFormat)) then li := @loadInfoIndex8 else
exit;
x := xSize;
y := ySize;
Width := x;
Height := y;
GetMem(pixels, xSize*ySize*4);
glGenTextures(1, @Texture);
glBindTexture(GL_TEXTURE_2D, Texture);
glEnable(GL_TEXTURE_2D);
// glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); {Texture blends with object background}
if NoPicMip then begin
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
end
else begin
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
end;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
{$IFDEF GL_14}
if GL_14 then
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
{$ENDIF}
if hdr.dwFlags and DDSD_MIPMAPCOUNT<>0 then mipMapCount := hdr.dwMipMapCount else mipMapCount := 1;
if li.compressed then begin
size := max(li.divSize, x ) div li.divSize * max(li.divSize, y) div li.divSize * li.blockBytes;
GetMem(data, size);
for ix:=0 to mipMapCount-1 do begin
Stream.Read(data^, size);
glCompressedTexImage2D(GL_TEXTURE_2D, ix, li.internalFormat, x, y, 0, size, data);
glGetTexImage(GL_TEXTURE_2D, ix, GL_RGBA, GL_BYTE, pixels);
SwapY(pixels,xSize,ySize);
glTexImage2D(GL_TEXTURE_2D, ix, GL_RGBA, xsize, ysize, 0, GL_RGBA, GL_BYTE, pixels);
x := (x+1) shr 1;
y := (y+1) shr 1;
size := max(li.divSize, x ) div li.divSize * max(li.divSize, y ) div li.divSize * li.blockBytes;
end;
FreeMem(data);
end
else if li.palette then begin
size := hdr.dwPitchOrLinearSize * ySize;
GetMem(data, size);
GetMem(unpacked, size * sizeof(cardinal));
Stream.Read(palette, 1024);
for ix:=0 to mipMapCount-1 do begin
Stream.Read(data^, size);
for zz:=0 to size-1 do
unpacked[zz] := palette[data[zz]];
glPixelStorei(GL_UNPACK_ROW_LENGTH, y);
glTexImage2D(GL_TEXTURE_2D, ix, li.internalFormat, x, y, 0, li.externalFormat, li.typ, unpacked);
glGetTexImage(GL_TEXTURE_2D, ix, GL_RGBA, GL_BYTE, pixels);
SwapY(pixels,xSize,ySize);
glTexImage2D(GL_TEXTURE_2D, ix, GL_RGBA, xsize, ysize, 0, GL_RGBA, GL_BYTE, pixels);
x := (x+1) shr 1;
y := (y+1) shr 1;
size := x * y * li.blockBytes;
end;
FreeMem(data);
FreeMem(unpacked);
end
else begin
if li.swap then
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
size := x * y * li.blockBytes;
GetMem(data, size);
for ix:=0 to mipMapCount-1 do begin
Stream.Read(data^, size);
glPixelStorei(GL_UNPACK_ROW_LENGTH, y);
glTexImage2D(GL_TEXTURE_2D, ix, li.internalFormat, x, y, 0, li.externalFormat, li.typ, data);
glGetTexImage(GL_TEXTURE_2D, ix, GL_RGBA, GL_BYTE, pixels);
SwapY(pixels,xSize,ySize);
glTexImage2D(GL_TEXTURE_2D, ix, GL_RGBA, xsize, ysize, 0, GL_RGBA, GL_BYTE, pixels);
x := (x+1) shr 1;
y := (y+1) shr 1;
size := x * y * li.blockBytes;
end;
FreeMem(data);
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
end;
{$IFDEF GL_12}
if GL_12 then
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipMapCount-1);
{$ENDIF}
FreeMem(pixels);
result := true;
end;