> ## Documentation Index
> Fetch the complete documentation index at: https://docs.spurdoverse.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Texture

> Load images from disk or memory for drawing on the overlay.

`Texture` loads an image file (`.png`, `.jpg`, etc.) or raw pixel data
into GPU memory so you can draw it with [Render.image](/api/render#image)
and [Render.imageRounded](/api/render#imagerounded).

<Note>
  Textures load **asynchronously** - they may not be ready on the same
  frame they're created. Always check `isReady` before drawing.
</Note>

## Overview

<CardGroup cols={2}>
  <Card title="Loading" icon="upload" href="#loading">
    From file path or raw RGBA pixel data.
  </Card>

  <Card title="Properties" icon="circle-info" href="#properties">
    Width, height, readiness, and file path.
  </Card>

  <Card title="Drawing" icon="paintbrush" href="#drawing">
    How to render loaded textures on screen.
  </Card>
</CardGroup>

***

## Loading

### Constructor

<br />

```ts theme={null}
new Texture(path: string, width?: number, height?: number): Texture
```

Loads an image from a file path. The texture starts loading immediately
but may not be ready until a later frame.

For **SVG** files you can optionally specify render dimensions.
PNG/JPG images always use the dimensions from the file itself — `width`
and `height` are ignored.

| Param | Type | |
| :- | :- | :- |
| `path` | `string` | Path to the image file |
| `width` | `number?` | Render width for SVG. `0` = auto (proportional to height) |
| `height` | `number?` | Render height for SVG. `0` = auto (proportional to width) |

<Tip>
  If neither `width` nor `height` is provided for an SVG, it renders at
  its intrinsic size × 4.
</Tip>

```ts theme={null}
const icon = new Texture("assets/icon.png");

// SVG — intrinsic size × 4
const svg1 = new Texture("icon.svg");

// SVG — exact size
const svg2 = new Texture("icon.svg", 128, 128);

// SVG — width 256, height proportional
const svg3 = new Texture("icon.svg", 256);

// SVG — height 64, width proportional
const svg4 = new Texture("icon.svg", 0, 64);
```

<Warning>
  Create textures **once** outside your render callback - not every
  frame. Repeated construction causes repeated disk reads and GPU
  uploads.
</Warning>

<Tabs>
  <Tab title="Correct">
    ```ts theme={null}
    // Create once at script start
    const icon = new Texture("assets/icon.png");

    // Draw every frame
    on("render", () => {
        if (icon.isReady) {
            Render.image(icon, pos, size, Color.white());
        }
    });
    ```
  </Tab>

  <Tab title="Wrong">
    ```ts theme={null}
    on("render", () => {
        // BAD: loads from disk every frame!
        const icon = new Texture("assets/icon.png");
        Render.image(icon, pos, size, Color.white());
    });
    ```
  </Tab>
</Tabs>

### Texture.fromMemory

<br />

```ts theme={null}
Texture.fromMemory(data: Uint8Array, width: number, height: number): Texture
```

Creates a texture from raw **RGBA** pixel data in memory. Each pixel
is 4 bytes (R, G, B, A). The buffer must contain exactly
`width × height × 4` bytes.

| Param | Type | |
| :- | :- | :- |
| `data` | `Uint8Array` | Raw RGBA pixel buffer |
| `width` | `number` | Image width in pixels |
| `height` | `number` | Image height in pixels |

```ts theme={null}
// Create a 2×2 checkerboard
const pixels = new Uint8Array([
    255, 0, 0, 255,    0, 0, 0, 255,     // row 1: red, black
      0, 0, 0, 255,  255, 0, 0, 255,     // row 2: black, red
]);

const checker = Texture.fromMemory(pixels, 2, 2);
```

<Tip>
  `fromMemory` is useful for procedurally generated textures - gradients,
  noise patterns, or dynamically composited images.
</Tip>

***

## Properties

All properties are **read-only**.

| Property | Type | |
| :- | :- | :- |
| `width` | `number` | Image width in pixels. `0` if not yet loaded |
| `height` | `number` | Image height in pixels. `0` if not yet loaded |
| `isReady` | `boolean` | `true` once the texture is uploaded to the GPU |
| `path` | `string` | File path (empty for `fromMemory` textures) |

```ts theme={null}
const tex = new Texture("assets/logo.png");

// Later:
if (tex.isReady) {
    console.log(tex.width, tex.height);  // e.g. 256, 256
    console.log(tex.path);               // "assets/logo.png"
}
```

### getSize

<br />

```ts theme={null}
texture.getSize(): { width: number, height: number }
```

Returns both dimensions as a plain object. Convenience method when you
need both at once.

```ts theme={null}
const { width, height } = tex.getSize();
const aspect = width / height;
```

### toString

<br />

```ts theme={null}
texture.toString(): string
```

Returns a debug string with dimensions, path, and ready state.

```ts theme={null}
const tex = new Texture("icon.png");
tex.toString();
// "Texture(64x64, path='icon.png', ready=true)"
```

***

## Drawing

Textures are drawn using the [render](/api/render) module:

```ts theme={null}
Render.image(texture, position, size, tintColor);
Render.imageRounded(texture, position, size, rounding, tintColor);
```

See [Render.image](/api/render#image) and
[Render.imageRounded](/api/render#imagerounded) for full parameter
documentation.

<Tabs>
  <Tab title="Basic image">
    ```ts theme={null}
    const icon = new Texture("assets/weapon.png");

    on("render", () => {
        if (!icon.isReady) return;

        const { success, screen } = Math.worldToScreen(pos);
        if (success) {
            Render.image(icon, screen, new Vector2(24, 24), Color.white());
        }
    });
    ```
  </Tab>

  <Tab title="Circular avatar">
    ```ts theme={null}
    const avatar = new Texture("assets/avatar.png");

    on("render", () => {
        if (!avatar.isReady) return;

        const size = new Vector2(48, 48);
        Render.imageRounded(avatar, hudPos, size, 24, Color.white());
        // rounding = half of width → perfect circle
    });
    ```
  </Tab>

  <Tab title="Tinted icon">
    ```ts theme={null}
    const icon = new Texture("assets/shield.png");

    on("render", () => {
        if (!icon.isReady) return;

        // Tint with team color
        const tint = isAlly ? Color.green() : Color.red();
        Render.image(icon, pos, new Vector2(32, 32), tint);
    });
    ```
  </Tab>

  <Tab title="Preserve aspect ratio">
    ```ts theme={null}
    const logo = new Texture("assets/logo.png");

    on("render", () => {
        if (!logo.isReady) return;

        const drawHeight = 64;
        const aspect = logo.width / logo.height;
        const drawWidth = drawHeight * aspect;

        Render.image(logo, pos, new Vector2(drawWidth, drawHeight), Color.white());
    });
    ```
  </Tab>
</Tabs>
