Okay, this is a direct loader for HL2 textures. It will load each mipmap level onto the graphics card with compression (if present), without generating an intermediate pixmap. It's pretty much just like DDS.
Thanks to Ryan Greg at Nem's Tools making VTFLib. This does not use his lib, but I learned a lot from it:
Thanks to Ryan Greg at Nem's Tools making VTFLib. This does not use his lib, but I learned a lot from it:
Rem bbdoc: Leadwerks.VTFLoader EndRem Module leadwerks.vtfloader Import leadwerks.texture Private Type TTextureLoaderVTF Extends TTextureLoader Method LoadTexture:TTexture( stream:TStream ) Return LoadTextureVTF( stream ) End Method End Type New TTextureLoaderVTF Public Rem bbdoc: EndRem Function LoadTextureVTF:TTexture(url:Object) Const VTF_IMAGE_FORMAT_RGBA8888=0 Const VTF_IMAGE_FORMAT_ABGR8888=1 Const VTF_IMAGE_FORMAT_ARGB8888=11 Const VTF_IMAGE_FORMAT_BGRA8888=12 Const IMAGE_FORMAT_RGBA8888 = 0 '< = Red, Green, Blue, Alpha - 32 bpp Const IMAGE_FORMAT_ABGR8888=1 '< = Alpha, Blue, Green, Red - 32 bpp Const IMAGE_FORMAT_RGB888=2 '< = Red, Green, Blue - 24 bpp Const IMAGE_FORMAT_BGR888=3 '< = Blue, Green, Red - 24 bpp Const IMAGE_FORMAT_RGB565=4 '< = Red, Green, Blue - 16 bpp Const IMAGE_FORMAT_I8=5 '< = Luminance - 8 bpp Const IMAGE_FORMAT_IA88=6 '< = Luminance, Alpha - 16 bpp Const IMAGE_FORMAT_P8=7 '< = Paletted - 8 bpp Const IMAGE_FORMAT_A8=8 '< = Alpha- 8 bpp Const IMAGE_FORMAT_RGB888_BLUESCREEN=9 '< = Red, Green, Blue, "BlueScreen" Alpha - 24 bpp Const IMAGE_FORMAT_BGR888_BLUESCREEN=10 '< = Red, Green, Blue, "BlueScreen" Alpha - 24 bpp Const IMAGE_FORMAT_ARGB8888=11 '< = Alpha, Red, Green, Blue - 32 bpp Const IMAGE_FORMAT_BGRA8888=12 '< = Blue, Green, Red, Alpha - 32 bpp Const IMAGE_FORMAT_DXT1=13 '< = DXT1 compressed format - 4 bpp Const IMAGE_FORMAT_DXT3=14 '< = DXT3 compressed format - 8 bpp Const IMAGE_FORMAT_DXT5=15 '< = DXT5 compressed format - 8 bpp Const IMAGE_FORMAT_BGRX8888=16 '< = Blue, Green, Red, Unused - 32 bpp Const IMAGE_FORMAT_BGR565=17 '< = Blue, Green, Red - 16 bpp Const IMAGE_FORMAT_BGRX5551=18 '< = Blue, Green, Red, Unused - 16 bpp Const IMAGE_FORMAT_BGRA4444=19 '< = Red, Green, Blue, Alpha - 16 bpp Const IMAGE_FORMAT_DXT1_ONEBITALPHA=20 '< = DXT1 compressed format with 1-bit Alpha - 4 bpp Const IMAGE_FORMAT_BGRA5551=21 '< = Blue, Green, Red, Alpha - 16 bpp Const IMAGE_FORMAT_UV88=22 '< = 2 channel format For DuDv/Normal maps - 16 bpp Const IMAGE_FORMAT_UVWQ8888=23 '< = 4 channel format For DuDv/Normal maps - 32 bpp Const IMAGE_FORMAT_RGBA16161616F=24 '< = Red, Green, Blue, Alpha - 64 bpp Const IMAGE_FORMAT_RGBA16161616=25 '< = Red, Green, Blue, Alpha signed with mantissa - 64 bpp Const IMAGE_FORMAT_UVLX8888=26 '< = 4 channel format For DuDv/Normal maps - 32 bpp Const IMAGE_FORMAT_I32F=27 '< = Luminance - 32 bpp Const IMAGE_FORMAT_RGB323232F=28 '< = Red, Green, Blue - 96 bpp Const IMAGE_FORMAT_RGBA32323232F=29 '< = Red, Green, Blue, Alpha - 128 bpp Const IMAGE_FORMAT_COUNT=30 Const IMAGE_FORMAT_NONE = -1 Const TEXTUREFLAGS_POINTSAMPLE = $00000001 Const TEXTUREFLAGS_TRILINEAR = $00000002 Const TEXTUREFLAGS_CLAMPS = $00000004 Const TEXTUREFLAGS_CLAMPT = $00000008 Const TEXTUREFLAGS_ANISOTROPIC = $00000010 Const TEXTUREFLAGS_HINT_DXT5 = $00000020 Const TEXTUREFLAGS_NOCOMPRESS = $00000040 Const TEXTUREFLAGS_NORMAL = $00000080 Const TEXTUREFLAGS_NOMIP = $00000100 Const TEXTUREFLAGS_NOLOD = $00000200 Const TEXTUREFLAGS_MINMIP = $00000400 Const TEXTUREFLAGS_PROCEDURAL = $00000800 Const TEXTUREFLAGS_ONEBITALPHA = $00001000 Const TEXTUREFLAGS_EIGHTBITALPHA = $00002000 Const TEXTUREFLAGS_ENVMAP = $00004000 Const TEXTUREFLAGS_RENDERTARGET = $00008000 Const TEXTUREFLAGS_DEPTHRENDERTARGET = $00010000 Const TEXTUREFLAGS_NODEBUGOVERRIDE = $00020000 Const TEXTUREFLAGS_SINGLECOPY = $00040000 Const TEXTUREFLAGS_ONEOVERMIPLEVELINALPHA = $00080000 Const TEXTUREFLAGS_PREMULTCOLORBYONEOVERMIPLEVEL = $00100000 Const TEXTUREFLAGS_NORMALTODUDV = $00200000 Const TEXTUREFLAGS_ALPHATESTMIPGENERATION = $00400000 Const TEXTUREFLAGS_NODEPTHBUFFER = $00800000 Const TEXTUREFLAGS_NICEFILTERED = $01000000 Const TEXTUREFLAGS_CLAMPU = $02000000 stream:TStream=ReadStream(url) If Not stream Return 'VTF file format specs: 'http://developer.valvesoftware.com/wiki/VTF#VTF_Layout Rem typedef struct tagVTFHEADER { char signature[4]; // File signature ("VTF\0"). unsigned Int version[2]; // version[0].version[1] (currently 7.2). unsigned Int headerSize; // Size of the header struct (16 Byte aligned; currently 80 bytes). unsigned Short width; // Width of the largest mipmap in pixels. Must be a power of 2. unsigned Short height; // Height of the largest mipmap in pixels. Must be a power of 2. unsigned Int flags; // VTF flags. unsigned Short frames; // Number of frames, If animated (1 For no animation). unsigned Short firstFrame; // First frame in animation (0 based). unsigned char padding0[4]; // reflectivity padding (16 Byte alignment). Float reflectivity[3]; // reflectivity vector. unsigned char padding1[4]; // reflectivity padding (8 Byte packing). Float bumpmapScale; // Bumpmap scale. unsigned Int highResImageFormat; // High resolution image format. unsigned char mipmapCount; // Number of mipmaps. unsigned Int lowResImageFormat; // Low resolution image format (always DXT1). unsigned char lowResImageWidth; // Low resolution image width. unsigned char lowResImageHeight; // Low resolution image height. unsigned Short depth; // Depth of the largest mipmap in pixels. Must be a power of 2. Can be 0 Or 1 For a 2D texture. v7.2 only. } VTFHEADER; EndRem 'VTF Header If stream.readstring(3)<>"VTF" Return stream.readbyte() majorversion=stream.readint() minorversion=stream.readint() headerSize=stream.readint() headerstart=stream.pos() width=stream.readshort() height=stream.readshort() flags=stream.readint() frames=stream.readshort() firstFrame=stream.readshort() Local padding:Byte[2,4] padding[0,0]=stream.readbyte() padding[0,1]=stream.readbyte() padding[0,2]=stream.readbyte() padding[0,3]=stream.readbyte() Local reflectivity#[3] reflectivity[0]=stream.readfloat() reflectivity[1]=stream.readfloat() reflectivity[2]=stream.readfloat() padding[1,0]=stream.readbyte() padding[1,1]=stream.readbyte() padding[1,2]=stream.readbyte() padding[1,3]=stream.readbyte() bumpmapScale#=stream.readfloat() highResImageFormat=stream.readint() mipmapCount=stream.readbyte() lowResImageFormat=stream.readint() lowResImageWidth=stream.readbyte() lowResImageheight=stream.readbyte() If majorversion>=7 And minorversion>1 depth=stream.readshort() stream.seek headerSize'+1 'Low-res image format is always DXTC1 (4 bpp) blocksize=((lowResImageWidth+3)/4)*((lowResImageHeight+3)/4)*8 stream.seek stream.pos()+blocksize 'stream.seek stream.pos()+1 w=width h=height For n=0 To mipmapCount-2 w:/2 ; h:/2 Next Select highResImageFormat Case IMAGE_FORMAT_RGBA8888 bpp=32 srcformat=GL_RGBA dstformat=GL_RGBA 'Case IMAGE_FORMAT_ABGR8888 bpp=32 Case IMAGE_FORMAT_RGB888 srcformat=GL_RGB dstformat=GL_RGB bpp=24 Case IMAGE_FORMAT_BGR888 bpp=24 srcformat=GL_BGR_EXT dstformat=GL_RGB 'Case IMAGE_FORMAT_RGB565 bpp=16 Case IMAGE_FORMAT_I8 bpp=8 srcformat=GL_LUMINANCE8 dstformat=GL_LUMINANCE8 Case IMAGE_FORMAT_IA88 bpp=16 srcformat=GL_LUMINANCE8_ALPHA8 dstformat=GL_LUMINANCE8_ALPHA8 'Case IMAGE_FORMAT_P8 bpp=8 Case IMAGE_FORMAT_A8 bpp=8 srcformat=GL_ALPHA8 dstformat=GL_ALPHA8 'Case IMAGE_FORMAT_RGB888_BLUESCREEN bpp=24 'Case IMAGE_FORMAT_BGR888_BLUESCREEN bpp=24 'Case IMAGE_FORMAT_ARGB8888 bpp=32 Case IMAGE_FORMAT_BGRA8888,IMAGE_FORMAT_BGRX8888 bpp=32 srcformat=GL_BGRA_EXT dstformat=GL_RGBA Case IMAGE_FORMAT_DXT1 bpp=8 srcformat=GL_COMPRESSED_RGBA_S3TC_DXT1_EXT compressed=1 Case IMAGE_FORMAT_DXT3 bpp=16 srcformat=GL_COMPRESSED_RGBA_S3TC_DXT3_EXT compressed=1 Case IMAGE_FORMAT_DXT5 bpp=16 srcformat=GL_COMPRESSED_RGBA_S3TC_DXT5_EXT compressed=1 'Case IMAGE_FORMAT_BGR565 bpp=16 'Case IMAGE_FORMAT_BGRX5551 bpp=16 'Case IMAGE_FORMAT_BGRA4444 bpp=16 'Case IMAGE_FORMAT_DXT1_ONEBITALPHA bpp=4 ''Case IMAGE_FORMAT_BGRA5551 bpp=16 'Case IMAGE_FORMAT_UV88 bpp=16 'Case IMAGE_FORMAT_UVWQ8888 bpp=32 'Case IMAGE_FORMAT_RGBA16161616F bpp=64 'Case IMAGE_FORMAT_RGBA16161616 bpp=64 'Case IMAGE_FORMAT_UVLX8888 bpp=32 'Case IMAGE_FORMAT_I32F bpp=32 'Case IMAGE_FORMAT_RGB323232F bpp=96 'Case IMAGE_FORMAT_RGBA32323232F bpp=128 'Case IMAGE_FORMAT_NONE Return Null Default Return Null EndSelect tex:TTexture=New TTexture tex.bind() gltexparameteri tex.target(),GL_TEXTURE_BASE_LEVEL,0 gltexparameteri tex.target(),GL_TEXTURE_MAX_LEVEL,mipmapCount-1 'Print bpp+" bits per pixel" For n=0 To mipmapCount-1 blocksize=((w+3)/4)*((h+3)/4)*bpp Local block:Byte[blocksize] stream.readbytes(Varptr block[0],blocksize) miplevel=mipmapCount-n-1 If compressed glCompressedTexImage2D(tex.target(),miplevel,srcformat,w,h,0,blocksize,Varptr block[0]) Else glTexImage2D(tex.target(),miplevel,dstformat,w,h,0,srcformat,GL_UNSIGNED_BYTE,Varptr block[0]) EndIf 'Print miplevel + " - " +w+" x "+h+" : "+tex.width(miplevel)+" x "+tex.height(miplevel)+" - "+blocksize w:*2 ; h:*2 Next Return tex EndFunction