Appearance
@carrot/engine-textures ​
ts
GPU texture abstractions for WebGL2 - image textures, raw data textures, 3D volumes, cubemaps, render targets, and procedural texture builders.
Installation ​
bash
npm install @carrot/engine-texturesArchitecture / How It Works ​
Texture hierarchy ​
All texture types extend the abstract Texture base class, which manages the WebGL handle lifecycle:
Texture (abstract)
├── Texture2D - loaded from AssetImage (PNG, JPG, etc.)
├── DataTexture - loaded from raw typed arrays (Float32Array, Uint8Array, etc.)
├── Texture3D - volumetric data (TEXTURE_3D)
├── TextureCube - 6-face cubemap (TEXTURE_CUBE_MAP)
└── RenderTexture - framebuffer-backed render targetThe base class handles:
- Handle creation -
createHandle()allocates the GL texture and applies filter/wrap parameters from theTextureDescriptor. - Bind/unbind - binds to a numbered texture unit for shader sampling.
- Dispose - deletes the GPU handle.
- Mipmap generation -
applyMipmaps()called after upload ifdescriptor.generateMipmapsis true.
Each subclass implements upload() with its specific data source.
TextureDescriptor ​
Immutable configuration object controlling format, filtering, wrapping, and mipmap generation. Three presets are provided: defaultTextureDescriptor, defaultRenderTextureDescriptor, and pixelArtTextureDescriptor.
TextureFormat ​
Maps to WebGL2 internalFormat + format + type combinations. Covers standard 8-bit colour, 16-bit and 32-bit float (for HDR, deferred, volumetric), and depth/stencil formats.
Procedural builders ​
TextureBuilder2D and TextureBuilder3D provide a fluent API for composing procedural textures from noise functions, curves, and blend operations. They output DataTexture and Texture3D respectively, auto-uploaded as R32F.
Noise helpers ​
noiseTexture2D and noiseTexture3D are convenience factories that take a noise function and produce an uploaded R32F texture in one call.
Dependencies ​
| Package | Used For |
|---|---|
@carrot/assets | AssetImage type used by Texture2D |
@carrot/maths | NoiseFn2, NoiseFn3 types used by noise texture factories |
Build ​
bash
npm run build # runs tscUsage Guide ​
GPU texture abstractions for WebGL2 - load images, upload raw data, build procedural textures, render to texture.
Import ​
ts
import {
Texture2D, DataTexture, Texture3D, TextureCube, RenderTexture,
TextureFormat, TextureFilter, TextureWrap,
TextureBuilder2D, TextureBuilder3D,
noiseTexture2D, noiseTexture3D,
defaultTextureDescriptor, pixelArtTextureDescriptor,
} from '@carrot/engine-textures';Common Patterns ​
1. Loading a 2D image texture ​
ts
const tex = new Texture2D(gl, assetImage, {
format: TextureFormat.RGBA8,
minFilter: TextureFilter.LinearMipmapLinear,
generateMipmaps: true,
});
tex.upload();
tex.bind(0); // bind to texture unit 02. Pixel-art texture (nearest filtering) ​
ts
import { pixelArtTextureDescriptor } from '@carrot/engine-textures';
const sprite = new Texture2D(gl, spriteImage, pixelArtTextureDescriptor);
sprite.upload();3. Raw data texture (noise, LUT, SDF) ​
ts
const data = new Float32Array(256 * 256);
// ... fill with data ...
const tex = new DataTexture(gl, 256, 256, data, {
format: TextureFormat.R32F,
});
tex.upload();4. Updating a data texture ​
ts
const newData = new Float32Array(256 * 256);
tex.setData(newData); // marks as not uploaded
tex.upload(); // re-uploads to GPU5. 3D volumetric texture ​
ts
const volume = new Float32Array(64 * 64 * 64);
// ... fill with density data ...
const tex = new Texture3D(gl, 64, 64, 64, volume, {
format: TextureFormat.R32F,
});
tex.upload();6. Cubemap texture ​
ts
import { TextureCube, CubeFace } from '@carrot/engine-textures';
const cube = new TextureCube(gl, 512);
cube.setFace(CubeFace.PositiveX, rightImage);
cube.setFace(CubeFace.NegativeX, leftImage);
cube.setFace(CubeFace.PositiveY, topImage);
cube.setFace(CubeFace.NegativeY, bottomImage);
cube.setFace(CubeFace.PositiveZ, frontImage);
cube.setFace(CubeFace.NegativeZ, backImage);
cube.upload();7. Render-to-texture ​
ts
const rt = new RenderTexture(gl, 1024, 768);
rt.upload();
// Render into it
rt.bindAsTarget();
// ... draw calls ...
rt.unbindTarget();
// Sample from it in a later pass
rt.bind(0);
// Resize on window change
rt.resize(newWidth, newHeight);8. Procedural texture with builder ​
ts
const heightMap = TextureBuilder2D.create(gl, 512, 512)
.set((x, y) => simplex2(x * 8, y * 8))
.add((x, y) => simplex2(x * 16, y * 16), 0.5)
.remap(-1, 1, 0, 1)
.curve((v) => v * v)
.clamp(0, 1)
.build();9. Procedural 3D volume ​
ts
const fogVolume = TextureBuilder3D.create(gl, 64, 64, 64)
.set((x, y, z) => perlin3(x * 4, y * 4, z * 4))
.multiply((_x, _y, z) => 1 - z) // fade out with height
.normalise()
.build();10. Quick noise texture (one-liner) ​
ts
const noiseTex = noiseTexture2D(gl, 256, 256, simplex2, 8);
const noiseVol = noiseTexture3D(gl, 64, 64, 64, perlin3, 4);11. Cleanup ​
ts
tex.dispose(); // deletes GPU texture handle
rt.dispose(); // deletes framebuffer, depth buffer, and texture handle