.werkkzeug 3 exported texture format
.introduction
.ktx is size-optimized format for textures made in .werkkzeug 3. This files cannot be loaded back into .werkkzeug, it intended to be used with "Texture Generation Library", which is non-free software.
File can contain one or more textures. Each texture in file must have unique name.
Format description
struct wz3ktx { // Magic number, always 'TPWT' uint32 magic; // Format version saint15 version; // Number of textures saint15 ntextures; // Number of blocks saint15 nblocks; // Number of used opclasses saint15 nclasses; // Texture descriptors struct wz3texdesc[ntextures] textures; // OpclassID palette (see opclass list) saint15 cids[nclasses]; // Operators (inputs) struct wz3blockinput[nblocks] blockinputs; // Parameters (blocks is sorted by opclass) struct wz3blockpara[nblocks] parameters; // String parameters ?? // Binary large objects uint8[?] blobs; } struct wz3texdesc { // Root block (index in wz3ktx->blocks table) saint15 root; // Name asciiz name; } struct wz3blockinput { // CID (index in wz3ktx->cids table). If high-order bit of pcid is set, // "inputs" field does not exist, and previous operator is used as input. uint8 pcid; // Number of inputs (only presents if opclass is "Merge") optional saint15 ninputs; // Inputs (only presents if high-order bit of pcid is not set) optional saint15[?] inputs; } struct wz3blockpara { // Parameters (size and structure of this blob depends on CID) uint8[?] parameters; }
Smartass Data Types
Most of integers and floats in .ktx format are stored with distinct datatypes. I called it smartass. Using of this datatypes is way to conserve space.
- saint15 — smartass integer, 15 bit
- Variable stored in file may occupy 1 or 2 bytes. If high-order bit of the first byte is set, implementation must read the second byte and merge ones as following: value=(first-0x80)+second*128;. This datatype can be used to save numbers from 0 to 32767.
- safloatI — smartass float, variant I
- Variable stored in file occupies 2 bytes. It is signed little-endian word, and implementation must convert it to float as following: value=word/4096.
- safloatII — smartass float, variant II
- Variable stored in file occupies 2 bytes.
- safloatIII — smartass float, variant III
- Variable stored in file occupies 3 bytes.
- color — rgb color
- Variable stored in file occupies 3 bytes. First is red, second green, and third blue.
Operator classes
There follows structures of wz3blockpara for all known by ktx library opclasses.
// Flat parameters struct op_flat_para { unsigned char width; unsigned char height; uint32 color; } // Perlin parameters struct op_perlin_para { unsigned char width; unsigned char height; unsigned char freq; unsigned char octaves; safloatI fadeoff; unsigned char seed; unsigned char mode; safloatII amplitude; safloatII gamma; uint32 color01; uint32 color02; } // Color parameters struct op_color_para { unsigned char mode; uint32 color; } // Merge parameters struct op_merge_para { unsigned char mode; } // Format parameters struct op_format_para { unsigned char _; unsigned char _; unsigned char _; } // GlowRectOld parameters struct op_glowrect_para { safloatI _; safloatI _; safloatI _; safloatI _; safloatI _; safloatI _; uint32 _; safloatI _; safloatII _; unsigned char _; unsigned char _; } // Dots parameters struct op_dots_para { uint32 color01; uint32 color02; sint16 count; unsigned char seed; } // Blur parameters struct op_blur_para { unsigned char passes; safloatII blurx; safloatII blury; safloatII amplify; } // Mask parameters struct op_mask_para { unsigned char mode; } // HSCB parameters struct op_hscb_para { safloatII hue; safloatII saturation; safloatII contrast; safloatII brightness; } // Rotate parameters struct op_rotate_para { safloatI angle; safloatII zoomx; safloatII zoomy; safloatI scrollx; safloatI scrolly; unsigned char borderclamp; unsigned char newwidth; unsigned char newheight; } // Distort parameters struct op_distort_para { safloatI strength; unsigned char borderclamp; } // Normals parameters struct op_normals_para { safloatII strength; unsigned char mode; } // Light parameters struct op_light_para { unsigned char _; safloatII _; safloatII _; safloatII _; safloatI _; safloatI _; uint32 _; uint32 _; safloatI _; safloatII _; safloatI _; } // Bump parameters struct op_bump_para { unsigned char _; safloatII _; safloatII _; safloatII _; safloatI _; safloatI _; uint32 _; uint32 _; safloatI _; safloatII _; safloatI _; uint32 _; safloatII _; safloatI _; } // Text parameters (there are some doubts with this) struct op_text_para { safloatI posx; safloatI posy; safloatII size; safloatII leading; uint32 color; unsigned char centerx; unsigned char centery; safloatII _; safloatII _; } // Cell parameters struct op_cell_para { unsigned char width; unsigned char height; uint32 color01; uint32 color02; uint32 color03; unsigned char max; unsigned char seed; safloatII amplify; safloatII gamma; unsigned char aspect; safloatI _; unsigned char flags; safloatIII percentage; } // Gradient parameters struct op_gradient_para { unsigned char width; unsigned char height; uint32 color01; uint32 color02; safloatI position; safloatI angle; safloatI gwidth; unsigned char mode; } // Range parameters struct op_range_para { unsigned char mode; uint32 color01; uint32 color02; } // RotateMul parameters struct op_rotatemul_para { safloatI angle; safloatII zoomx; safloatII zoomy; safloatI scrollx; safloatI scrolly; unsigned char borderclamp; uint32 preadjust; unsigned char mode; unsigned char count; uint32 fadecolor; } // Twirl parameters struct op_twirl_para { safloatII strength; safloatII gamma; safloatI radiusx; safloatI radiusy; safloatI centerx; safloatI centery; unsigned char borderclamp; } // Sharpen parameters struct op_sharpen_para { unsigned char order; safloatI blurx; safloatI blury; safloatI amplify; } // GlowRect parameters struct op_glowrect_para { safloatI centerx; safloatI centery; safloatI radiusx; safloatI radiusy; safloatI sizex; safloatI sizey; uint32 color; safloatI blend; safloatII power; unsigned char wrapmode; unsigned char powermode; } // Import parameters struct op_import_para { } // ColorBalance parameters struct op_cbalance_para { safloatI[3] shadows; safloatI[3] midtones; safloatI[3] highlights; } // Unwrap parameters struct op_unwrap_para { unsigned char mode; unsigned char borderclamp; // ? } // Bricks parameters struct op_bricks_para { unsigned char width; unsigned char height; uint32 color01; uint32 color02; uint32 jointscolor; safloatIII jointsizex; safloatIII jointsizey; unsigned char _; unsigned char _; unsigned char _; unsigned char _; unsigned char _; safloatIII _; safloatIII _; } // Bulge parameters struct op_bulge_para { safloatII wrap; }
FAQ
- Q: How to determine size of wz3ktxblock->inputs?
- A: Number of inputs depends on opclass ID. For example, Flat has only one input, and Mask has three inputs. Merge has variable number of inputs.
- Q: What does contain field wz3blockinput->inputs?
- A: It contains relative indices of blocks. For example, if this field contains 0, previous operator will be used as input. If this field contains 3, i-1-3th operator will be used as input. If high-order bit of pcid is set, inputs does not present in file, and previous operator will be used as input.