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