npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

texforge

v0.1.3

Published

Forge textures for the GPU age. Convert PNG/JPG to KTX2 with blazing fast compression. 90% smaller files, hardware-accelerated loading for Phaser, Three.js, and Babylon.js.

Readme

texforge

Forge textures for the GPU age. Convert large images and texture atlases to GPU-optimized KTX2 format with automatic chunking and hardware-accelerated compression.

Features

  • Automatic Image Chunking: Split large maps into optimal chunks for streaming
  • GPU-Native Compression: Convert to KTX2 with ETC1S or UASTC compression
  • 90% Smaller Files: Dramatically reduce texture memory and load times
  • Phaser Integration: Drop-in loader for Phaser 3.70+
  • CLI and API: Use as command-line tool or Node.js library
  • Zero Configuration: Works out of the box with sensible defaults

Installation

npm install texforge

Requirements

texforge requires toktx from KTX-Software:

  • Windows: Download from KTX-Software releases
  • macOS: brew install ktx
  • Linux: Download from KTX-Software releases

Verify installation:

texforge check

Quick Start

One-Line Map Optimization

import { TexForge } from 'texforge';

const result = await TexForge.processMapToKTX2({
  input: './my-huge-map.png',
  outputDir: './public/maps',
  chunkSize: 1024,
  mode: 'etc1s'
});

console.log(`Saved ${result.totalSaved} bytes (${result.compressionRatio}% reduction)`);

CLI Usage

# Convert single image
texforge convert image.png -o output.ktx2

# Convert directory
texforge convert ./textures/ -o ./output/ --mode uastc

# Process large map with chunking
texforge convert huge-map.png -o ./chunks/ --chunk-size 1024

API Documentation

TexForge.processMapToKTX2(options)

Main method that chunks a large image and converts all chunks to KTX2.

interface ProcessOptions {
  input: string;              // Input image path
  outputDir: string;          // Output directory for chunks
  chunkSize?: number;         // Chunk size in pixels (default: 1024)
  mode?: 'etc1s' | 'uastc';  // Compression mode (default: 'etc1s')
  quality?: number;           // Quality 1-255 (default: 128)
  compressionLevel?: number;  // Level 0-5 (default: 2)
  mipmaps?: boolean;          // Generate mipmaps (default: false)
}

Returns: ProcessResult with metadata, conversion stats, and file sizes.

ImageChunker

Split large images into chunks for streaming:

import { ImageChunker } from 'texforge';

const chunker = new ImageChunker({
  chunkSize: 1024,
  outputDir: './chunks',
  format: 'png'
});

const metadata = await chunker.chunkImage('./large-map.png');

TextureForge

Convert individual images to KTX2:

import { TextureForge } from 'texforge';

const forge = new TextureForge({
  mode: 'etc1s',
  quality: 128,
  compressionLevel: 2
});

const result = await forge.convertFile('./texture.png', './texture.ktx2');

Phaser Integration

Load chunked KTX2 maps in Phaser:

import { PhaserKTX2Loader } from 'texforge';

class GameScene extends Phaser.Scene {
  private loader: PhaserKTX2Loader;

  async create() {
    this.loader = new PhaserKTX2Loader(this, '/maps/chunks/');
    
    await this.loader.loadMetadata('/maps/chunks/metadata.json');
    
    // Load chunks around player position
    this.loader.loadChunksInArea(playerX, playerY, 2);
  }

  update() {
    // Dynamically load chunks as player moves
    this.loader.loadChunksInArea(player.x, player.y, 2);
  }
}

Compression Modes

ETC1S (Recommended)

  • Best compression ratio: 70-90% smaller than PNG
  • Universal support: Works on all devices
  • Use for: Large texture atlases, background images, UI textures
mode: 'etc1s',
quality: 128,           // Higher = better quality (1-255)
compressionLevel: 2     // Higher = smaller file (0-5)

UASTC

  • Higher quality: Better visual fidelity
  • Faster transcoding: Hardware decode on GPU
  • Use for: Normal maps, detail textures, hero assets
mode: 'uastc',
quality: 2              // Quality level for UASTC

Performance Benchmarks

Real-world results from a 12000x8000px game map:

| Format | Size | Load Time | Memory | |--------|------|-----------|--------| | PNG | 45 MB | 2.3s | 384 MB | | KTX2 (etc1s) | 4.2 MB | 0.3s | 48 MB | | Improvement | 90% smaller | 87% faster | 87% less |

Complete Example: Dhaniverse Integration

// Step 1: Process your map during build
import { TexForge } from 'texforge';

await TexForge.processMapToKTX2({
  input: './assets/world-map.png',
  outputDir: './public/maps',
  chunkSize: 1024,
  mode: 'etc1s',
  quality: 128
});

// Step 2: Load in Phaser
import { PhaserKTX2Loader } from 'texforge';

export class MainScene extends Phaser.Scene {
  private mapLoader: PhaserKTX2Loader;

  async preload() {
    this.mapLoader = new PhaserKTX2Loader(this);
    const metadata = await this.mapLoader.loadMetadata('/maps/metadata.json');
    
    console.log(`Map size: ${metadata.totalWidth}x${metadata.totalHeight}`);
    console.log(`Chunks: ${metadata.chunksX}x${metadata.chunksY}`);
  }

  create() {
    // Load initial visible chunks
    const player = this.add.sprite(100, 100, 'player');
    this.mapLoader.loadChunksInArea(player.x, player.y, 3);
  }

  update() {
    // Stream chunks as player moves
    const player = this.physics.world.bounds;
    this.mapLoader.loadChunksInArea(player.centerX, player.centerY, 2);
  }
}

CLI Reference

# Convert with custom quality
texforge convert input.png --quality 200 --compression 4

# UASTC mode for high-quality textures
texforge convert normal-map.png --mode uastc --normal-map

# Generate mipmaps
texforge convert texture.png --mipmaps

# Batch convert directory
texforge convert ./textures/ -o ./output/

# Check installation
texforge check

TypeScript Support

Full TypeScript definitions included:

import type {
  ChunkMetadata,
  ChunkedMapMetadata,
  ConversionOptions,
  ConversionResult
} from 'texforge';

License

MIT - Gursimran Singh

Credits

Built with:

Contributing

Issues and PRs welcome at github.com/dhaniverse/texforge