- 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;