Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Do Mär 28, 2024 17:52

Foren-Übersicht » English » English Programming Forum
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 1 Beitrag ] 
Autor Nachricht
 Betreff des Beitrags: Valve Texture Format (VTF) Source
BeitragVerfasst: Sa Apr 03, 2010 15:58 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Jul 21, 2004 22:39
Beiträge: 360
Wohnort: UK, Scotland
Note: The unit only returns the first texture at MipMap Level 0 even if the file is animated. It wouldn't be hard to modify the code below so it loads every frame instead of skipping them.

function LoadVTFImage(var TexData : TRawTexture; RawData : Pointer; Size : Int64; EXT : PWideChar) : Boolean;
TexData stores the result.
RawData is the actual VTF file loaded into a Pointer.
Size is the size of the RawData.
EXT is the Extention of the image, this check could be removed.

GL_BGRA is the default format that is returned in the TexData.Data.

Code:
unit Unit_VTF;
{
VTF - Valve Texture Format
This unit is aimed at loading VTF files which are used by Source games (i.e HL2)

Its based on http://developer.valvesoftware.com/wiki/VTF

Composed by Stuart "Stucuk" Carey

This Unit uses parts of Martin Waldegger's DDS Unit for loading the actual textures
}

interface

type
TRawTexture = Record
  Data    : Pointer;
  BPP,
  Padding : Byte;
  Width,
  Height  : Word;
 end;

tagVTFHEADER = packed Record
Signature     : Array [0..3] of Char;     // File signature ("VTF\0").
Version       : Array [0..1] of Cardinal; // version[0].version[1] (currently 7.1).
Headersize    : Cardinal;                 // Size of the header struct (currently 64 bytes).
Width,                                    // Width of the largest mipmap in pixels. Must be a power of 2.
Height        : Word;                     // Height of the largest mipmap in pixels. Must be a power of 2.
Flags         : Cardinal;                 // VTF flags.
Frames,                                   // Number of frames, if animated (1 for no animation).
FirstFrame    : Word;                     // First frame in animation (0 based).
Padding0      : Array [0..3] of Byte;     // reflectivity padding (16 byte alignment).
Reflectivity  : Array [0..2] of Single;   // reflectivity vector.
Padding1      : Array [0..3] of Byte;     // reflectivity padding (8 byte packing).
BumpmapScale  : Single;                   // Bumpmap scale.
HighResFormat : Integer;                  // High resolution image format.
MipmapCount   : Byte;                     // Number of mipmaps.
LowResFormat  : integer;                  // Low resolution image format (always DXT1).
LowResWidth,                              // Low resolution image width.
LowResHeight  : Byte;                     // Low resolution image height.
B : Byte;                                 // Added to make it 64 bytes long.
end;

function LoadVTFImage(var TexData : TRawTexture; RawData : Pointer; Size : Int64; EXT : PWideChar) : Boolean;
procedure FreeVTFImage(var TexData : TRawTexture);

implementation

uses Windows,dglOpenGL,SysUtils,Math,Classes;

const
        GL_COMPRESSED_RGB_S3TC_DXT1                    = $83F0;
        GL_COMPRESSED_RGBA_S3TC_DXT1                   = $83F1;
        GL_COMPRESSED_RGBA_S3TC_DXT3                   = $83F2;
        GL_COMPRESSED_RGBA_S3TC_DXT5                   = $83F3;
        IMAGE_FORMAT_NONE = -1;
   IMAGE_FORMAT_RGBA8888 = 0;
   IMAGE_FORMAT_ABGR8888 = 1;
   IMAGE_FORMAT_RGB888   = 2;
   IMAGE_FORMAT_BGR888   = 3;
   IMAGE_FORMAT_RGB565   = 4;
   IMAGE_FORMAT_I8       = 5;
   IMAGE_FORMAT_IA88     = 6;
   IMAGE_FORMAT_P8       = 7;
   IMAGE_FORMAT_A8       = 8;
   IMAGE_FORMAT_RGB888_BLUESCREEN = 9;
   IMAGE_FORMAT_BGR888_BLUESCREEN = 10;
   IMAGE_FORMAT_ARGB8888 = 11;
   IMAGE_FORMAT_BGRA8888 = 12;
   IMAGE_FORMAT_DXT1     = 13;
   IMAGE_FORMAT_DXT3     = 14;
   IMAGE_FORMAT_DXT5     = 15;
   IMAGE_FORMAT_BGRX8888 = 16;
   IMAGE_FORMAT_BGR565   = 17;
   IMAGE_FORMAT_BGRX5551 = 18;
   IMAGE_FORMAT_BGRA4444 = 19;
   IMAGE_FORMAT_DXT1_ONEBITALPHA = 20;
   IMAGE_FORMAT_BGRA5551 = 21;
   IMAGE_FORMAT_UV88     = 22;
   IMAGE_FORMAT_UVWQ8888 = 23;
   IMAGE_FORMAT_RGBA16161616F = 24;
   IMAGE_FORMAT_RGBA16161616  = 25;
   IMAGE_FORMAT_UVLX8888      = 26;

        TEXTUREFLAGS_POINTSAMPLE = $00000001;
   TEXTUREFLAGS_TRILINEAR = $00000002;
   TEXTUREFLAGS_CLAMPS = $00000004;
   TEXTUREFLAGS_CLAMPT = $00000008;
   TEXTUREFLAGS_ANISOTROPIC = $00000010;
   TEXTUREFLAGS_HINT_DXT5 = $00000020;
   TEXTUREFLAGS_NOCOMPRESS = $00000040;
   TEXTUREFLAGS_NORMAL = $00000080;
   TEXTUREFLAGS_NOMIP = $00000100;
   TEXTUREFLAGS_NOLOD = $00000200;
   TEXTUREFLAGS_MINMIP = $00000400;
   TEXTUREFLAGS_PROCEDURAL = $00000800;
   TEXTUREFLAGS_ONEBITALPHA = $00001000;
   TEXTUREFLAGS_EIGHTBITALPHA = $00002000;
   TEXTUREFLAGS_ENVMAP = $00004000;
   TEXTUREFLAGS_RENDERTARGET = $00008000;
   TEXTUREFLAGS_DEPTHRENDERTARGET = $00010000;
   TEXTUREFLAGS_NODEBUGOVERRIDE = $00020000;
   TEXTUREFLAGS_SINGLECOPY = $00040000;
   TEXTUREFLAGS_ONEOVERMIPLEVELINALPHA = $00080000;
   TEXTUREFLAGS_PREMULTCOLORBYONEOVERMIPLEVEL = $00100000;
   TEXTUREFLAGS_NORMALTODUDV = $00200000;
   TEXTUREFLAGS_ALPHATESTMIPGENERATION = $00400000;
   TEXTUREFLAGS_NODEPTHBUFFER = $00800000;
   TEXTUREFLAGS_NICEFILTERED = $01000000;


type
  TDDSLoadInfo = record
    compressed: boolean;
    swap: boolean;
    palette: boolean;
    divSize: Cardinal;
    blockBytes: Cardinal;
    internalFormat: GLenum;
    externalFormat: GLenum;
    typ: GLenum;
  end;

var
  loadInfoDXT1 : TDDSLoadInfo =
  (compressed: true; swap: false; palette: false; divsize: 4; blockBytes: 8; internalFormat: GL_COMPRESSED_RGBA_S3TC_DXT1);

  loadInfoDXT3 : TDDSLoadInfo =
  (compressed: true; swap: false; palette: false; divsize: 4; blockBytes: 16; internalFormat: GL_COMPRESSED_RGBA_S3TC_DXT3);

  loadInfoDXT5 : TDDSLoadInfo =
  (compressed: true; swap: false; palette: false; divsize: 4; blockBytes: 16; internalFormat: GL_COMPRESSED_RGBA_S3TC_DXT5);

  loadInfoBGR8 : TDDSLoadInfo =
  (compressed: false; swap: false; palette: false; divsize: 1; blockBytes: 3; internalFormat: GL_RGB8; externalFormat: GL_BGR; typ: GL_UNSIGNED_BYTE);

  loadInfoBGRA8 : TDDSLoadInfo =
  (compressed: false; swap: false; palette: false; divsize: 1; blockBytes: 4; internalFormat: GL_RGBA8; externalFormat: GL_BGRA; typ: GL_UNSIGNED_BYTE);

  loadInfoBGR565 : TDDSLoadInfo =
  (compressed: false; swap: true; palette: false; divsize: 1; blockBytes: 2; internalFormat: GL_RGB5; externalFormat: GL_BGR; typ: GL_UNSIGNED_SHORT_5_6_5);


Procedure SwapY(Pixels: Pointer; xSize, ySize: Integer);
var x, y: integer;
    P1, P2: ^Cardinal;
    Temp: Cardinal;
begin
  for y:=0 to pred(ySize shr 1) do
    for x:=0 to pred(xSize) do begin
      P1 := Pointer(Cardinal(Pixels) + (y*xSize + x)*4);
      P2 := Pointer(Cardinal(Pixels) + ((ySize-y-1)*xSize + x)*4);
      Temp := P1^;
      P1^  := P2^;
      P2^  := Temp;
    end;
end;

Procedure LoadTexture(Var Stream : TMemoryStream; Var Texture : Cardinal; Const Width,Height,CurrMipMap,MipMapCount,TextureType : Integer; Skip : Boolean);
var
 li: ^TDDSLoadInfo;
 x,y,size : integer;
 data,pixels: PBytes;
begin

 case TextureType of
  IMAGE_FORMAT_DXT1     : li := @loadInfoDXT1;
  IMAGE_FORMAT_DXT3     : li := @loadInfoDXT3;
  IMAGE_FORMAT_DXT5     : li := @loadInfoDXT5;
  IMAGE_FORMAT_BGR888   : li := @loadInfoBGR8;
  IMAGE_FORMAT_BGR565   : li := @loadInfoBGR565;
  IMAGE_FORMAT_BGRA8888 : li := @loadInfoBGRA8;
 else
  Exit;
 end;

 x := Width;
 y := Height;

 if not Skip then
 GetMem(pixels, x*y*4);

 if not Skip then
 begin
  glBindTexture(GL_TEXTURE_2D, Texture);

  glEnable(GL_TEXTURE_2D);

  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
 end;

 x := Max(x shr CurrMipMap,1);
 y := Max(y shr CurrMipMap,1);

  if li.compressed then
  begin
    size := max(li.divSize, x ) div li.divSize * max(li.divSize, y) div li.divSize * li.blockBytes;

    if not Skip then
    begin
     GetMem(data, size);
     Stream.Read(Data^,Size);

     glCompressedTexImage2D(GL_TEXTURE_2D, CurrMipMap, li.internalFormat, x, y, 0, size, data);
     glGetTexImage(GL_TEXTURE_2D, CurrMipMap, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

     SwapY(pixels,x, y);
     glTexImage2D(GL_TEXTURE_2D, CurrMipMap, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);


     FreeMem(Data);
    end
    else
     Stream.Seek(Size,1);
  end
  else
  begin
    size := x * y * li.blockBytes;

    if not Skip then
    begin
     GetMem(data, size);
     Stream.Read(Data^,Size);

     if li.swap then
     glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
     glTexImage2D(GL_TEXTURE_2D, CurrMipMap, li.internalFormat, x, y, 0, li.externalFormat, li.typ, data);

     if li.swap then
     glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);

     glGetTexImage(GL_TEXTURE_2D, CurrMipMap, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
     SwapY(pixels,x, y);
     glTexImage2D(GL_TEXTURE_2D, CurrMipMap, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

     FreeMem(Data);
    end
    else
     Stream.Seek(Size,1);
  end;

  if not Skip then
  FreeMem(pixels);
end;

Function GetHasAlpha(Format : Integer) : Boolean;
begin
 case Format of
  0,1,8,11,
  12,13,14,
  15,19,20,
  21,24,25 : Result := True;
 else
  Result := False;
 end;

end;

//Note: While VTF's can be animated, for our purposes we just want the first image thats at MipMap 0
function LoadVTFImage(var TexData : TRawTexture; RawData : Pointer; Size : Int64; EXT : PWideChar) : Boolean;
var
 x,y,curmip : integer;
 MS          : TMemoryStream;
 Header      : tagVTFHEADER;
 TempTexture : Cardinal;
 Faces       : Integer;
begin
 Result := False;

 if not (Lowercase(WideString(EXT)) = '.vtf') then
  Exit;

 MS := TMemoryStream.Create;
 glGenTextures(1, @TempTexture);

 try 
 MS.Write(RawData^,Size);
 MS.Position := 0;
 MS.Read(Header,SizeOf(Header));

 //Future Compatible (Well as future proof as we can get)
 if Header.Headersize > 64 then
 MS.Seek(Header.Headersize-64,1);

 if ((Header.Flags and TEXTUREFLAGS_ENVMAP) = TEXTUREFLAGS_ENVMAP) or (Header.Flags = TEXTUREFLAGS_ENVMAP) then
 Faces := 6
 else
 Faces := 1;

// HasAlpha := GetHasAlpha(Header.HighResFormat);

 case Header.HighResFormat of
  IMAGE_FORMAT_DXT1     : ;
  IMAGE_FORMAT_DXT3     : ;
  IMAGE_FORMAT_DXT5     : ;
  IMAGE_FORMAT_BGR888   : ;
  IMAGE_FORMAT_BGR565   : ;
  IMAGE_FORMAT_BGRA8888 : ;
 else
   // Format not supported so create a blank texture
   TexData.Data   := Nil;
   TexData.Width  := Header.Width;
   TexData.Height := Header.Height;
   TexData.BPP    := 4;
   GetMem(TexData.Data, Header.Width*Header.Height*4);
   FillChar(TexData.Data^,Header.Width*Header.Height*4,0);
   Result := True;
   exit;
 end;

 LoadTexture(MS,TempTexture,Header.LowResWidth,Header.LowResHeight,0,1,Header.LowResFormat,True);

 for curmip := Header.MipmapCount-1 downto 0 do
 begin

  for x := 0 to Header.Frames-1 do
  for y := 0 to Faces-1 do
  begin
   LoadTexture(MS,TempTexture,Header.Width,Header.Height,curmip,Header.MipmapCount,Header.HighResFormat,not ((X = 0) and (Y = 0) and (curmip = 0)));

   if (X = 0) and (Y = 0) and (curmip = 0) then
   begin
    TexData.Data   := Nil;
    TexData.Width  := Header.Width;
    TexData.Height := Header.Height;
    TexData.BPP    := 4;
    GetMem(TexData.Data, Header.Width*Header.Height*4);

    glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, TexData.Data);
    Result := True;
    Break;
   end;
  end;
 end;

 finally
  glDeleteTextures(1, @TempTexture);
  MS.Free;
 end;
end;

procedure FreeVTFImage(var TexData : TRawTexture);
begin
 if Assigned(TexData.Data) then
 begin
  FreeMem(TexData.Data);
  TexData.Data := Nil;
 end;
end;

end.

_________________
Free Map Editor - Game Requirements - Stucuk.Net
-Stu


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 1 Beitrag ] 
Foren-Übersicht » English » English Programming Forum


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 5 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.061s | 17 Queries | GZIP : On ]