Textures
In a similar fashion to buffers, textures provide a way to store and manage data on the GPU. They allow for both read and write access from WGSL shaders, and can also be sampled in the case of sampled textures. The main advantage of using textures over buffers is their optimized memory layout for spatial data, which can lead to better performance in certain scenarios as well as additional functionality such as filtering and mipmapping.
TypeGPU textures serve as a wrapper that provides type safety and higher level utilities (such as automatic mipmap generation). They also allow - in a similar way to buffers - for fixed resource creation that can be used directly in shaders without the need for manual bind group management.
Let’s look at an example of creating and using a typed texture.
import { const tgpu: { const: typeof import("node_modules/typegpu/src/core/constant/tgpuConstant").constant; fn: typeof import("node_modules/typegpu/src/core/function/tgpuFn").fn; comptime: typeof import("node_modules/typegpu/src/core/function/comptime").comptime; resolve: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolve; resolveWithContext: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolveWithContext; init: typeof import("node_modules/typegpu/src/core/root/init").init; initFromDevice: typeof import("node_modules/typegpu/src/core/root/init").initFromDevice; slot: typeof import("node_modules/typegpu/src/core/slot/slot").slot; lazy: typeof import("node_modules/typegpu/src/core/slot/lazy").lazy; ... 10 more ...; '~unstable': typeof import("node_modules/typegpu/src/tgpuUnstable");}
tgpu } from 'typegpu';
const const root: TgpuRoot
root = await const tgpu: { const: typeof import("node_modules/typegpu/src/core/constant/tgpuConstant").constant; fn: typeof import("node_modules/typegpu/src/core/function/tgpuFn").fn; comptime: typeof import("node_modules/typegpu/src/core/function/comptime").comptime; resolve: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolve; resolveWithContext: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolveWithContext; init: typeof import("node_modules/typegpu/src/core/root/init").init; initFromDevice: typeof import("node_modules/typegpu/src/core/root/init").initFromDevice; slot: typeof import("node_modules/typegpu/src/core/slot/slot").slot; lazy: typeof import("node_modules/typegpu/src/core/slot/lazy").lazy; ... 10 more ...; '~unstable': typeof import("node_modules/typegpu/src/tgpuUnstable");}
tgpu.init: (options?: InitOptions) => Promise<TgpuRoot>
Requests a new GPU device and creates a root around it.
If a specific device should be used instead, use
init();
const const response: Response
response = await function fetch(input: string | URL | Request, init?: RequestInit): Promise<Response> (+1 overload)
fetch('path/to/image.png');const const blob: Blob
blob = await const response: Response
response.Body.blob(): Promise<Blob>
blob();const const imageBitmap: ImageBitmap
imageBitmap = await function createImageBitmap(image: ImageBitmapSource, options?: ImageBitmapOptions): Promise<ImageBitmap> (+1 overload)
createImageBitmap(const blob: Blob
blob);
const const texture: TgpuTexture<{ size: [number, number]; format: "rgba8unorm";}> & SampledFlag & RenderFlag
texture = const root: TgpuRoot
root.TgpuRoot.createTexture<number, number, number, [number, number], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[number, number], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<{ size: [number, number]; format: "rgba8unorm";}>
createTexture({ size: [number, number]
The width, height, and depth or layer count of the texture.
size: [const imageBitmap: ImageBitmap
imageBitmap.ImageBitmap.width: number
The ImageBitmap.width read-only property returns the ImageBitmap object's width in CSS pixels.
width, const imageBitmap: ImageBitmap
imageBitmap.ImageBitmap.height: number
The ImageBitmap.height read-only property returns the ImageBitmap object's height in CSS pixels.
height], format: "rgba8unorm"
The format of the texture.
format: 'rgba8unorm' as type const = "rgba8unorm"
const,}).TgpuTexture<{ size: [number, number]; format: "rgba8unorm"; }>.$usage<["sampled", "render"]>(usages_0: "sampled", usages_1: "render"): TgpuTexture<{ size: [number, number]; format: "rgba8unorm";}> & SampledFlag & RenderFlag
$usage('sampled', 'render');
// Uploading image data to the textureconst texture: TgpuTexture<{ size: [number, number]; format: "rgba8unorm";}> & SampledFlag & RenderFlag
texture.TgpuTexture<{ size: [number, number]; format: "rgba8unorm"; }>.write(source: GPUCopyExternalImageSource | GPUCopyExternalImageSource[], options?: TextureWriteOptions): void (+1 overload)
Writes image sources to the texture, one per array layer. Requires the 'render' usage flag
write(const imageBitmap: ImageBitmap
imageBitmap);
// Creating a view to use in shaderconst sampledView = const texture: TgpuTexture<{ size: [number, number]; format: "rgba8unorm";}> & SampledFlag & RenderFlag
texture.TgpuTexture<{ size: [number, number]; format: "rgba8unorm"; }>.createView(): TgpuTextureView<WgslTexture2d<F32>> (+3 overloads)
createView();const sampledView: TgpuTextureView<WgslTexture2d<F32>>
Creating a texture
Section titled “Creating a texture”Textures can be created using the root.createTexture method. It accepts a descriptor similar to vanilla GPUTextureDescriptor. If specified, the properties will be reflected in the created texture type - this will later help with static checks when creating views or binding the texture in a layout.
type TextureProps = { size: readonly number[]; format: GPUTextureFormat; viewFormats?: GPUTextureFormat[] | undefined; dimension?: GPUTextureDimension | undefined; mipLevelCount?: number | undefined; sampleCount?: number | undefined;};const texture = const root: TgpuRoot
root.TgpuRoot.createTexture<number, number, number, [512, 512, 128], "rgba8unorm", 4, number, GPUTextureFormat[], "3d">(props: CreateTextureOptions<[512, 512, 128], "rgba8unorm", 4, number, GPUTextureFormat[], "3d">): TgpuTexture<{ size: [512, 512, 128]; format: "rgba8unorm"; dimension: "3d"; mipLevelCount: 4;}>
createTexture({const texture: TgpuTexture<{ size: [512, 512, 128]; format: "rgba8unorm"; dimension: "3d"; mipLevelCount: 4;}>
size: [512, 512, 128]
The width, height, and depth or layer count of the texture.
size: [512, 512, 128], format: "rgba8unorm"
The format of the texture.
format: 'rgba8unorm', mipLevelCount?: 4 | undefined
The number of mip levels the texture will contain.
mipLevelCount: 4, dimension?: "3d" | undefined
Whether the texture is one-dimensional, an array of two-dimensional layers, or three-dimensional.
dimension: '3d',})Usage flags
Section titled “Usage flags”Similar to buffers, textures need usage flags to specify how they will be used. You can add usage flags using the .$usage(...) method.
const const texture: TgpuTexture<{ size: [256, 256]; format: "rgba8unorm";}> & SampledFlag & StorageFlag & RenderFlag
texture = const root: TgpuRoot
root.TgpuRoot.createTexture<number, number, number, [256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<{ size: [256, 256]; format: "rgba8unorm";}>
createTexture({ size: [256, 256]
The width, height, and depth or layer count of the texture.
size: [256, 256], format: "rgba8unorm"
The format of the texture.
format: 'rgba8unorm',}) .TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; }>.$usage<["sampled"]>(usages_0: "sampled"): TgpuTexture<{ size: [256, 256]; format: "rgba8unorm";}> & SampledFlag
$usage('sampled') // Can be sampled in shaders .TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; }>.$usage<["storage"]>(usages_0: "storage"): TgpuTexture<{ size: [256, 256]; format: "rgba8unorm";}> & SampledFlag & StorageFlag
$usage('storage') // Can be written or read to as storage texture .TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; }>.$usage<["render"]>(usages_0: "render"): TgpuTexture<{ size: [256, 256]; format: "rgba8unorm";}> & SampledFlag & StorageFlag & RenderFlag
$usage('render'); // Can be used as a render target or image upload targetYou can also add multiple flags at once:
const const texture: TgpuTexture<{ size: [256, 256]; format: "rgba8unorm";}> & SampledFlag & RenderFlag & StorageFlag
texture = const root: TgpuRoot
root.TgpuRoot.createTexture<number, number, number, [256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<{ size: [256, 256]; format: "rgba8unorm";}>
createTexture({ size: [256, 256]
The width, height, and depth or layer count of the texture.
size: [256, 256], format: "rgba8unorm"
The format of the texture.
format: 'rgba8unorm',}).TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; }>.$usage<["sampled", "storage", "render"]>(usages_0: "sampled", usages_1: "storage", usages_2: "render"): TgpuTexture<{ size: [256, 256]; format: "rgba8unorm";}> & SampledFlag & RenderFlag & StorageFlag
$usage('sampled', 'storage', 'render');For raw WebGPU usage flags, use .$overrideFlags(...):
const const texture: TgpuTexture<{ size: [256, 256]; format: "rgba8unorm";}> & StorageFlag & SampledFlag & RenderFlag
texture = const root: TgpuRoot
root .TgpuRoot.createTexture<number, number, number, [256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<{ size: [256, 256]; format: "rgba8unorm";}>
createTexture({ size: [256, 256]
The width, height, and depth or layer count of the texture.
size: [256, 256], format: "rgba8unorm"
The format of the texture.
format: 'rgba8unorm', }) .TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; }>.$overrideFlags(flags: GPUTextureUsageFlags): TgpuTexture<{ size: [256, 256]; format: "rgba8unorm";}> & StorageFlag & SampledFlag & RenderFlag
$overrideFlags(var GPUTextureUsage: GPUTextureUsage
GPUTextureUsage.GPUTextureUsage.RENDER_ATTACHMENT: number
RENDER_ATTACHMENT);Writing to a texture
Section titled “Writing to a texture”The .write() method accepts a variety of data sources. Here’s a quick overview of the available options:
| Source | Use when |
|---|---|
texture.write(imageBitmap) | You already have a decoded image that matches the texture size. |
texture.write(imageBitmap, { fit: 'stretch' }) | You want the image resampled to fit the texture. |
texture.write(imageBitmap, { fit: 'clip' }) | You want a 1:1 copy of the overlapping region. |
texture.writeAsync(blob, { ... }) | You have a fetched Blob and don’t need to keep the decoded bitmap around. |
texture.write([layer0, layer1]) | You want to fill a texture array or 3D texture one layer at a time. |
texture.write(bytes) | You already have raw texel bytes. |
texture.write(imageBitmap, { origin, size, ... }) | You need a crop or a destination region. |
common.writeChannels(texture, { ... }) | You want to pack image sources into individual channels. |
Writing image sources requires the 'render' usage flag (raw binary writes do not), and the source and destination sizes have to match unless you pick a mismatch behavior with the fit option.
Writing image data
Section titled “Writing image data”You can write various image sources to textures. If the image dimensions match the texture size, all it takes is a single .write() call:
const const texture: TgpuTexture<{ size: [number, number]; format: "rgba8unorm";}> & SampledFlag & RenderFlag
texture = const root: TgpuRoot
root.TgpuRoot.createTexture<number, number, number, [number, number], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[number, number], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<{ size: [number, number]; format: "rgba8unorm";}>
createTexture({ size: [number, number]
The width, height, and depth or layer count of the texture.
size: [const imageBitmap: ImageBitmap
imageBitmap.ImageBitmap.width: number
The ImageBitmap.width read-only property returns the ImageBitmap object's width in CSS pixels.
width, const imageBitmap: ImageBitmap
imageBitmap.ImageBitmap.height: number
The ImageBitmap.height read-only property returns the ImageBitmap object's height in CSS pixels.
height], format: "rgba8unorm"
The format of the texture.
format: 'rgba8unorm',}).TgpuTexture<{ size: [number, number]; format: "rgba8unorm"; }>.$usage<["sampled", "render"]>(usages_0: "sampled", usages_1: "render"): TgpuTexture<{ size: [number, number]; format: "rgba8unorm";}> & SampledFlag & RenderFlag
$usage('sampled', 'render');
const texture: TgpuTexture<{ size: [number, number]; format: "rgba8unorm";}> & SampledFlag & RenderFlag
texture.TgpuTexture<{ size: [number, number]; format: "rgba8unorm"; }>.write(source: GPUCopyExternalImageSource | GPUCopyExternalImageSource[], options?: TextureWriteOptions): void (+1 overload)
Writes image sources to the texture, one per array layer. Requires the 'render' usage flag
write(const imageBitmap: ImageBitmap
imageBitmap);Handling size mismatches
Section titled “Handling size mismatches”If the image dimensions don’t match the texture size, a plain .write() call throws. The fit option picks what happens instead: 'stretch' resamples the source to fill the target region, while 'clip' copies texels 1:1 and cuts off whatever doesn’t overlap.
const texture = root.createTexture({ size: [512, 512], format: 'rgba8unorm',}).$usage('sampled', 'render');
texture.write(imageBitmap, { fit: 'stretch' });
texture.write(imageBitmap, { sourceOrigin: [16, 16], sourceSize: [128, 128], size: [256, 256], fit: 'stretch',});
texture.write(tileBitmap, { origin: [128, 64], fit: 'clip' });Writing blobs
Section titled “Writing blobs”If you fetched an image and don’t need to keep the decoded ImageBitmap around, you can hand the Blob directly to writeAsync and let TypeGPU handle the decoding. With fit: 'stretch', the resize options are passed along to createImageBitmap before uploading.
const const texture: TgpuTexture<{ size: [512, 512]; format: "rgba8unorm";}> & SampledFlag & RenderFlag
texture = const root: TgpuRoot
root.TgpuRoot.createTexture<number, number, number, [512, 512], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[512, 512], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<{ size: [512, 512]; format: "rgba8unorm";}>
createTexture({ size: [512, 512]
The width, height, and depth or layer count of the texture.
size: [512, 512], format: "rgba8unorm"
The format of the texture.
format: 'rgba8unorm',}).TgpuTexture<{ size: [512, 512]; format: "rgba8unorm"; }>.$usage<["sampled", "render"]>(usages_0: "sampled", usages_1: "render"): TgpuTexture<{ size: [512, 512]; format: "rgba8unorm";}> & SampledFlag & RenderFlag
$usage('sampled', 'render');
const const blob: Blob
blob = await (await function fetch(input: string | URL | Request, init?: RequestInit): Promise<Response> (+1 overload)
fetch('path/to/image.png')).Body.blob(): Promise<Blob>
blob();
await const texture: TgpuTexture<{ size: [512, 512]; format: "rgba8unorm";}> & SampledFlag & RenderFlag
texture.TgpuTexture<{ size: [512, 512]; format: "rgba8unorm"; }>.writeAsync(source: Blob, options?: TextureBlobWriteOptions): Promise<void>
Decodes an image blob and writes it to the texture. Requires the 'render' usage flag
writeAsync(const blob: Blob
blob, { fit?: TextureWriteFit | undefined
fit: 'stretch' });If you don’t specify a size, it defaults to the size of the written region - the target mip level minus the origin offset. Keep in mind that the decoded bitmap is still written as an image source, so the texture needs the 'render' usage flag.
Writing arrays of images
Section titled “Writing arrays of images”For texture arrays, you can write multiple images at once - one per layer:
const const texture: TgpuTexture<{ size: [256, 256, 3]; format: "rgba8unorm";}> & SampledFlag & RenderFlag
texture = const root: TgpuRoot
root.TgpuRoot.createTexture<number, number, number, [256, 256, 3], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[256, 256, 3], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<{ size: [256, 256, 3]; format: "rgba8unorm";}>
createTexture({ size: [256, 256, 3]
The width, height, and depth or layer count of the texture.
size: [256, 256, 3], format: "rgba8unorm"
The format of the texture.
format: 'rgba8unorm',}).TgpuTexture<{ size: [256, 256, 3]; format: "rgba8unorm"; }>.$usage<["sampled", "render"]>(usages_0: "sampled", usages_1: "render"): TgpuTexture<{ size: [256, 256, 3]; format: "rgba8unorm";}> & SampledFlag & RenderFlag
$usage('sampled', 'render');
const texture: TgpuTexture<{ size: [256, 256, 3]; format: "rgba8unorm";}> & SampledFlag & RenderFlag
texture.TgpuTexture<{ size: [256, 256, 3]; format: "rgba8unorm"; }>.write(source: GPUCopyExternalImageSource | GPUCopyExternalImageSource[], options?: TextureWriteOptions): void (+1 overload)
Writes image sources to the texture, one per array layer. Requires the 'render' usage flag
write([const layer0: ImageBitmap
layer0, const layer1: ImageBitmap
layer1, const layer2: ImageBitmap
layer2]);Each image has to match the layer size, unless you pass a fit mode.
The same form works for 3D textures (created with dimension: '3d') - each image in the array fills one depth slice:
const const texture3d: TgpuTexture<{ size: [256, 256, 3]; format: "rgba8unorm"; dimension: "3d";}> & SampledFlag & RenderFlag
texture3d = const root: TgpuRoot
root.TgpuRoot.createTexture<number, number, number, [256, 256, 3], "rgba8unorm", number, number, GPUTextureFormat[], "3d">(props: CreateTextureOptions<[256, 256, 3], "rgba8unorm", number, number, GPUTextureFormat[], "3d">): TgpuTexture<{ size: [256, 256, 3]; format: "rgba8unorm"; dimension: "3d";}>
createTexture({ size: [256, 256, 3]
The width, height, and depth or layer count of the texture.
size: [256, 256, 3], format: "rgba8unorm"
The format of the texture.
format: 'rgba8unorm', dimension?: "3d" | undefined
Whether the texture is one-dimensional, an array of two-dimensional layers, or three-dimensional.
dimension: '3d',}).TgpuTexture<{ size: [256, 256, 3]; format: "rgba8unorm"; dimension: "3d"; }>.$usage<["sampled", "render"]>(usages_0: "sampled", usages_1: "render"): TgpuTexture<{ size: [256, 256, 3]; format: "rgba8unorm"; dimension: "3d";}> & SampledFlag & RenderFlag
$usage('sampled', 'render');
const texture3d: TgpuTexture<{ size: [256, 256, 3]; format: "rgba8unorm"; dimension: "3d";}> & SampledFlag & RenderFlag
texture3d.TgpuTexture<{ size: [256, 256, 3]; format: "rgba8unorm"; dimension: "3d"; }>.write(source: GPUCopyExternalImageSource | GPUCopyExternalImageSource[], options?: TextureWriteOptions): void (+1 overload)
Writes image sources to the texture, one per array layer. Requires the 'render' usage flag
write([const slice0: ImageBitmap
slice0, const slice1: ImageBitmap
slice1, const slice2: ImageBitmap
slice2]);Writing raw binary data
Section titled “Writing raw binary data”You can write raw binary data directly to textures using ArrayBuffer, typed arrays, or DataView:
const const texture: TgpuTexture<{ size: [2, 2]; format: "rgba8unorm"; mipLevelCount: 2;}> & SampledFlag
texture = const root: TgpuRoot
root.TgpuRoot.createTexture<number, number, number, [2, 2], "rgba8unorm", 2, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[2, 2], "rgba8unorm", 2, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<{ size: [2, 2]; format: "rgba8unorm"; mipLevelCount: 2;}>
createTexture({ size: [2, 2]
The width, height, and depth or layer count of the texture.
size: [2, 2], format: "rgba8unorm"
The format of the texture.
format: 'rgba8unorm', mipLevelCount?: 2 | undefined
The number of mip levels the texture will contain.
mipLevelCount: 2,}).TgpuTexture<{ size: [2, 2]; format: "rgba8unorm"; mipLevelCount: 2; }>.$usage<["sampled"]>(usages_0: "sampled"): TgpuTexture<{ size: [2, 2]; format: "rgba8unorm"; mipLevelCount: 2;}> & SampledFlag
$usage('sampled');
// Using Uint8Array for RGBA data (4 pixels, 4 bytes each)const const data: Uint8Array<ArrayBuffer>
data = new var Uint8Array: Uint8ArrayConstructornew (elements: Iterable<number>) => Uint8Array<ArrayBuffer> (+6 overloads)
Uint8Array([ 255, 0, 0, 255, // Red pixel 0, 255, 0, 255, // Green pixel 0, 0, 255, 255, // Blue pixel 255, 255, 0, 255, // Yellow pixel]);const texture: TgpuTexture<{ size: [2, 2]; format: "rgba8unorm"; mipLevelCount: 2;}> & SampledFlag
texture.TgpuTexture<{ size: [2, 2]; format: "rgba8unorm"; mipLevelCount: 2; }>.write(source: ArrayBuffer | TypedArray | DataView, options?: number | TextureRawWriteOptions): void (+1 overload)
Writes raw texel data to the texture
write(const data: Uint8Array<ArrayBuffer>
data);
// Write to a specific mip levelconst const mipData: Uint8Array<ArrayBuffer>
mipData = new var Uint8Array: Uint8ArrayConstructornew (length: number) => Uint8Array<ArrayBuffer> (+6 overloads)
Uint8Array(4); // Data for 1 pixelconst texture: TgpuTexture<{ size: [2, 2]; format: "rgba8unorm"; mipLevelCount: 2;}> & SampledFlag
texture.TgpuTexture<{ size: [2, 2]; format: "rgba8unorm"; mipLevelCount: 2; }>.write(source: ArrayBuffer | TypedArray | DataView, options?: number | TextureRawWriteOptions): void (+1 overload)
Writes raw texel data to the texture
write(const mipData: Uint8Array<ArrayBuffer>
mipData, 1); // Write to mip level 1
// Update just a regionconst const regionData: Uint8Array<ArrayBuffer>
regionData = new var Uint8Array: Uint8ArrayConstructornew (length: number) => Uint8Array<ArrayBuffer> (+6 overloads)
Uint8Array(4); // Data for 1 pixelconst texture: TgpuTexture<{ size: [2, 2]; format: "rgba8unorm"; mipLevelCount: 2;}> & SampledFlag
texture.TgpuTexture<{ size: [2, 2]; format: "rgba8unorm"; mipLevelCount: 2; }>.write(source: ArrayBuffer | TypedArray | DataView, options?: number | TextureRawWriteOptions): void (+1 overload)
Writes raw texel data to the texture
write(const regionData: Uint8Array<ArrayBuffer>
regionData, { origin?: readonly [x: number, y: number, z?: number | undefined] | undefined
origin: [1, 1], size?: readonly [width: number, height: number, depthOrArrayLayers?: number | undefined] | undefined
size: [1, 1] });Writing raw data doesn’t require the 'render' usage flag, but the byte length has to exactly match the written region for the given texture format.
Regions and channel writes
Section titled “Regions and channel writes”If you only want to update a part of the texture, or copy just a fragment of the source image, you can pass options with source and destination regions. The options also let you flip the source vertically (flipY), premultiply alpha (premultipliedAlpha), or convert to a specific color space (colorSpace).
const const texture: TgpuTexture<{ size: [512, 512]; format: "rgba8unorm";}> & SampledFlag & RenderFlag
texture = const root: TgpuRoot
root.TgpuRoot.createTexture<number, number, number, [512, 512], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[512, 512], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<{ size: [512, 512]; format: "rgba8unorm";}>
createTexture({ size: [512, 512]
The width, height, and depth or layer count of the texture.
size: [512, 512], format: "rgba8unorm"
The format of the texture.
format: 'rgba8unorm',}).TgpuTexture<{ size: [512, 512]; format: "rgba8unorm"; }>.$usage<["sampled", "render"]>(usages_0: "sampled", usages_1: "render"): TgpuTexture<{ size: [512, 512]; format: "rgba8unorm";}> & SampledFlag & RenderFlag
$usage('sampled', 'render');
const texture: TgpuTexture<{ size: [512, 512]; format: "rgba8unorm";}> & SampledFlag & RenderFlag
texture.TgpuTexture<{ size: [512, 512]; format: "rgba8unorm"; }>.write(source: GPUCopyExternalImageSource | GPUCopyExternalImageSource[], options?: TextureWriteOptions): void (+1 overload)
Writes image sources to the texture, one per array layer. Requires the 'render' usage flag
write(const imageBitmap: ImageBitmap
imageBitmap, { sourceOrigin?: readonly [x: number, y: number] | undefined
sourceOrigin: [16, 16], sourceSize?: readonly [width: number, height: number] | undefined
sourceSize: [128, 128], origin?: readonly [x: number, y: number, z?: number | undefined] | undefined
origin: [128, 64], size?: readonly [width: number, height: number] | undefined
size: [128, 128],});Sometimes you’ll want to pack multiple grayscale maps into a single texture - for example combining separate roughness, metalness, and mask maps into one material texture. The common.writeChannels utility does exactly that. Each entry writes a single channel of the texture, with from selecting which channel of the source to read. Entries set to undefined are skipped.
const const texture: TgpuTexture<{ size: [512, 512]; format: "rgba8unorm";}> & SampledFlag & RenderFlag
texture = const root: TgpuRoot
root.TgpuRoot.createTexture<number, number, number, [512, 512], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[512, 512], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<{ size: [512, 512]; format: "rgba8unorm";}>
createTexture({ size: [512, 512]
The width, height, and depth or layer count of the texture.
size: [512, 512], format: "rgba8unorm"
The format of the texture.
format: 'rgba8unorm',}).TgpuTexture<{ size: [512, 512]; format: "rgba8unorm"; }>.$usage<["sampled", "render"]>(usages_0: "sampled", usages_1: "render"): TgpuTexture<{ size: [512, 512]; format: "rgba8unorm";}> & SampledFlag & RenderFlag
$usage('sampled', 'render');
import common
common.function writeChannels(texture: TgpuTexture & RenderFlag, channels: TextureChannels, options?: TextureWriteOptions): voidexport writeChannels
Writes image sources into individual channels of texture. Each entry
writes a single channel, with from selecting which channel of the
source to read. Omitted channels are left untouched.
Requires the 'render' usage flag on the texture.
writeChannels(const texture: TgpuTexture<{ size: [512, 512]; format: "rgba8unorm";}> & SampledFlag & RenderFlag
texture, { r?: TextureChannelSource | undefined
r: { source: GPUCopyExternalImageSource
source: const roughnessMap: ImageBitmap
roughnessMap, from: TextureChannel
from: 'r' }, g?: TextureChannelSource | undefined
g: { source: GPUCopyExternalImageSource
source: const metalnessMap: ImageBitmap
metalnessMap, from: TextureChannel
from: 'r' }, a?: TextureChannelSource | undefined
a: { source: GPUCopyExternalImageSource
source: const maskMap: ImageBitmap
maskMap, from: TextureChannel
from: 'r' },});Region and channel writes follow the same rules as other image writes - they require the 'render' usage flag, and sizes have to match unless you pass a fit mode.
Mipmaps
Section titled “Mipmaps”TypeGPU provides automatic mipmap generation for textures:
const const texture: TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; mipLevelCount: 9;}> & SampledFlag & RenderFlag
texture = const root: TgpuRoot
root.TgpuRoot.createTexture<number, number, number, [256, 256], "rgba8unorm", 9, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[256, 256], "rgba8unorm", 9, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; mipLevelCount: 9;}>
createTexture({ size: [256, 256]
The width, height, and depth or layer count of the texture.
size: [256, 256], format: "rgba8unorm"
The format of the texture.
format: 'rgba8unorm', mipLevelCount?: 9 | undefined
The number of mip levels the texture will contain.
mipLevelCount: 9, // log2(256) + 1}).TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; mipLevelCount: 9; }>.$usage<["sampled", "render"]>(usages_0: "sampled", usages_1: "render"): TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; mipLevelCount: 9;}> & SampledFlag & RenderFlag
$usage('sampled', 'render');
const texture: TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; mipLevelCount: 9;}> & SampledFlag & RenderFlag
texture.TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; mipLevelCount: 9; }>.write(source: GPUCopyExternalImageSource | GPUCopyExternalImageSource[], options?: TextureWriteOptions): void (+1 overload)
Writes image sources to the texture, one per array layer. Requires the 'render' usage flag
write(const imageBitmap: ImageBitmap
imageBitmap, { fit?: TextureWriteFit | undefined
fit: 'stretch' });const texture: TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; mipLevelCount: 9;}> & SampledFlag & RenderFlag
texture.TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; mipLevelCount: 9; }>.generateMipmaps(baseMipLevel?: number, mipLevels?: number): void
generateMipmaps(); // Generate all mip levels automaticallyCopying and clearing
Section titled “Copying and clearing”You can also copy data from another texture. If both textures have the same size and format, a plain targetTexture.copyFrom(sourceTexture) is all you need. To copy a region, target a specific mip level, or copy between differently sized textures, pass copy options:
const targetTexture: TgpuTexture<{ size: [512, 512]; format: "rgba8unorm";}>
targetTexture.TgpuTexture<{ size: [512, 512]; format: "rgba8unorm"; }>.copyFrom<TgpuTexture<{ size: [64, 64]; format: "rgba8unorm";}>>(source: TgpuTexture<{ size: [64, 64]; format: "rgba8unorm";}>, options: TextureCopyOptions): void (+1 overload)
Copies a region between textures of the same format
copyFrom(const sourceTexture: TgpuTexture<{ size: [64, 64]; format: "rgba8unorm";}>
sourceTexture, { sourceOrigin?: readonly [x: number, y: number, z?: number | undefined] | undefined
sourceOrigin: [16, 16], origin?: readonly [x: number, y: number, z?: number | undefined] | undefined
origin: [128, 64], size?: readonly [width: number, height: number, depthOrArrayLayers?: number | undefined] | undefined
size: [32, 32],});To wipe a texture clean, use texture.clear(), which fills every mip level with zeros, or pass a mip level to clear only that level. You can also pass an rgba color to fill the texture with instead (this requires the 'render' usage flag):
const texture: TgpuTexture<{ size: [512, 512]; format: "rgba8unorm";}> & RenderFlag
texture.TgpuTexture<{ size: [512, 512]; format: "rgba8unorm"; }>.clear(color: readonly [number, number, number, number], mipLevel?: number | "all"): void (+1 overload)
Clears the texture to color. Requires the 'render' usage flag
clear([0, 0.5, 0, 1]);Call .destroy() when the texture is no longer needed. This releases the underlying GPUTexture; subsequent operations on the TypeGPU texture are invalid.
Texture views
Section titled “Texture views”To create a view - which will also serve as fixed texture usage - you can use one of the available texture schemas. You can pass it to the .createView method of the texture.
const const texture: TgpuTexture<{ size: [512, 512]; format: "rgba8unorm";}> & SampledFlag
texture = const root: TgpuRoot
root.TgpuRoot.createTexture<number, number, number, [512, 512], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[512, 512], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<{ size: [512, 512]; format: "rgba8unorm";}>
createTexture({ size: [512, 512]
The width, height, and depth or layer count of the texture.
size: [512, 512], format: "rgba8unorm"
The format of the texture.
format: 'rgba8unorm',}).TgpuTexture<{ size: [512, 512]; format: "rgba8unorm"; }>.$usage<["sampled"]>(usages_0: "sampled"): TgpuTexture<{ size: [512, 512]; format: "rgba8unorm";}> & SampledFlag
$usage('sampled');
const const sampledView: TgpuTextureView<d.WgslTexture2d<d.F32>>
sampledView = const texture: TgpuTexture<{ size: [512, 512]; format: "rgba8unorm";}> & SampledFlag
texture.TgpuTexture<{ size: [512, 512]; format: "rgba8unorm"; }>.createView<d.WgslTexture2d<d.F32>>(schema: d.WgslTexture2d<d.F32>, viewDescriptor?: (TgpuTextureViewDescriptor & { sampleType?: "float" | "unfilterable-float" | undefined;}) | undefined): TgpuTextureView<d.WgslTexture2d<d.F32>> (+3 overloads)
createView(import d
d.texture2d<d.F32>(sampleType: d.F32): d.WgslTexture2d<d.F32> (+1 overload)export texture2d
texture2d(import d
d.const f32: d.F32export f32
A schema that represents a 32-bit float value. (equivalent to f32 in WGSL)
Can also be called to cast a value to an f32.
f32));// in this case the same as:// - texture.createView(d.texture2d()); (defaults to f32)// - texture.createView(); (defaults to texture2d<f32>)Samplers
Section titled “Samplers”To sample textures in shaders, you’ll often need a sampler that defines how the texture should be filtered and addressed. The createSampler method accepts the same descriptor as the vanilla WebGPU GPUSamplerDescriptor:
const const sampler: TgpuFixedSampler
sampler = const root: TgpuRoot
root.TgpuRoot.createSampler(props: WgslSamplerProps): TgpuFixedSampler
createSampler({ WgslSamplerProps.magFilter?: GPUFilterMode | undefined
Specifies the sampling behavior when the sample footprint is smaller than or equal to one
texel.
magFilter: 'linear', WgslSamplerProps.minFilter?: GPUFilterMode | undefined
Specifies the sampling behavior when the sample footprint is larger than one texel.
minFilter: 'linear', WgslSamplerProps.mipmapFilter?: GPUMipmapFilterMode | undefined
Specifies behavior for sampling between mipmap levels.
mipmapFilter: 'linear', WgslSamplerProps.addressModeU?: GPUAddressMode | undefined
addressModeU: 'repeat', WgslSamplerProps.addressModeV?: GPUAddressMode | undefined
addressModeV: 'repeat',});The returned sampler object can be used like a fixed resource directly in shaders, or bound in a bind group for manual binding.
Comparison samplers
Section titled “Comparison samplers”Depth comparisons use a distinct sampler type.
Create one with root.createComparisonSampler, then pass it to std.textureSampleCompare with a depth texture:
const const shadowMap: TgpuTexture<{ size: [1024, 1024]; format: "depth24plus";}> & SampledFlag
shadowMap = const root: TgpuRoot
root.TgpuRoot.createTexture<number, number, number, [1024, 1024], "depth24plus", number, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[1024, 1024], "depth24plus", number, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<{ size: [1024, 1024]; format: "depth24plus";}>
createTexture({ size: [1024, 1024]
The width, height, and depth or layer count of the texture.
size: [1024, 1024], format: "depth24plus"
The format of the texture.
format: 'depth24plus',}).TgpuTexture<{ size: [1024, 1024]; format: "depth24plus"; }>.$usage<["sampled"]>(usages_0: "sampled"): TgpuTexture<{ size: [1024, 1024]; format: "depth24plus";}> & SampledFlag
$usage('sampled');
const const shadowView: TgpuTextureView<d.WgslTextureDepth2d>
shadowView = const shadowMap: TgpuTexture<{ size: [1024, 1024]; format: "depth24plus";}> & SampledFlag
shadowMap.TgpuTexture<{ size: [1024, 1024]; format: "depth24plus"; }>.createView<d.WgslTextureDepth2d>(schema: d.WgslTextureDepth2d, viewDescriptor?: (TgpuTextureViewDescriptor & { sampleType?: "float" | "unfilterable-float" | undefined;}) | undefined): TgpuTextureView<d.WgslTextureDepth2d> (+3 overloads)
createView(import d
d.function textureDepth2d(): d.WgslTextureDepth2dexport textureDepth2d
textureDepth2d());const const shadowSampler: TgpuFixedComparisonSampler
shadowSampler = const root: TgpuRoot
root.TgpuRoot.createComparisonSampler(props: WgslComparisonSamplerProps): TgpuFixedComparisonSampler
createComparisonSampler({ WgslComparisonSamplerProps.compare: GPUCompareFunction
compare: 'less-equal', WgslComparisonSamplerProps.magFilter?: GPUFilterMode | undefined
Specifies the sampling behavior when the sample footprint is smaller than or equal to one
texel.
magFilter: 'linear', WgslComparisonSamplerProps.minFilter?: GPUFilterMode | undefined
Specifies the sampling behavior when the sample footprint is larger than one texel.
minFilter: 'linear',});
const const sampleShadow: TgpuFn<(uv: d.Vec2f, depth: d.F32) => d.F32>
sampleShadow = const tgpu: { const: typeof import("node_modules/typegpu/src/core/constant/tgpuConstant").constant; fn: typeof import("node_modules/typegpu/src/core/function/tgpuFn").fn; comptime: typeof import("node_modules/typegpu/src/core/function/comptime").comptime; resolve: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolve; resolveWithContext: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolveWithContext; init: typeof import("node_modules/typegpu/src/core/root/init").init; initFromDevice: typeof import("node_modules/typegpu/src/core/root/init").initFromDevice; slot: typeof import("node_modules/typegpu/src/core/slot/slot").slot; lazy: typeof import("node_modules/typegpu/src/core/slot/lazy").lazy; ... 10 more ...; '~unstable': typeof import("node_modules/typegpu/src/tgpuUnstable");}
tgpu.fn: <[d.Vec2f, d.F32], d.F32>(argTypes: [d.Vec2f, d.F32], returnType: d.F32) => TgpuFnShell<[d.Vec2f, d.F32], d.F32> (+2 overloads)
fn([import d
d.const vec2f: d.Vec2f
vec2f, import d
d.const f32: d.F32export f32
A schema that represents a 32-bit float value. (equivalent to f32 in WGSL)
Can also be called to cast a value to an f32.
f32], import d
d.const f32: d.F32export f32
A schema that represents a 32-bit float value. (equivalent to f32 in WGSL)
Can also be called to cast a value to an f32.
f32)((uv: d.v2f
uv, depth: number
depth) => { 'use gpu'; return import std
std.textureSampleCompare<d.textureDepth2d>(texture: d.textureDepth2d, sampler: d.comparisonSampler, coords: d.v2f, depthRef: number): number (+5 overloads)export textureSampleCompare
textureSampleCompare(const shadowView: TgpuTextureView<d.WgslTextureDepth2d>
shadowView.TgpuTextureView<WgslTextureDepth2d>.$: d.textureDepth2d
$, const shadowSampler: TgpuFixedComparisonSampler
shadowSampler.TgpuComparisonSampler.$: d.comparisonSampler
$, uv: d.v2f
uv, depth: number
depth);});For manual binding, pair d.comparisonSampler() with a comparison layout entry:
const layout = tgpu.bindGroupLayout({ shadowMap: { texture: d.textureDepth2d() }, shadowSampler: { sampler: 'comparison' },});Regular samplers created with createSampler use d.sampler() and a 'filtering' or 'non-filtering' layout entry instead.
Binding textures
Section titled “Binding textures”Textures can be used in shaders through bind groups or as fixed resources, similar to buffers.
Manual binding
Section titled “Manual binding”const const texture: TgpuTexture<{ size: [256, 256]; format: "rgba8unorm";}> & SampledFlag
texture = const root: TgpuRoot
root.TgpuRoot.createTexture<number, number, number, [256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<{ size: [256, 256]; format: "rgba8unorm";}>
createTexture({ size: [256, 256]
The width, height, and depth or layer count of the texture.
size: [256, 256], format: "rgba8unorm"
The format of the texture.
format: 'rgba8unorm',}).TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; }>.$usage<["sampled"]>(usages_0: "sampled"): TgpuTexture<{ size: [256, 256]; format: "rgba8unorm";}> & SampledFlag
$usage('sampled');
const const sampler: TgpuFixedSampler
sampler = const root: TgpuRoot
root.TgpuRoot.createSampler(props: WgslSamplerProps): TgpuFixedSampler
createSampler({ WgslSamplerProps.magFilter?: GPUFilterMode | undefined
Specifies the sampling behavior when the sample footprint is smaller than or equal to one
texel.
magFilter: 'linear', WgslSamplerProps.minFilter?: GPUFilterMode | undefined
Specifies the sampling behavior when the sample footprint is larger than one texel.
minFilter: 'linear',});
const const bindGroupLayout: TgpuBindGroupLayout<{ myTexture: { texture: d.WgslTexture2d<d.F32>; }; mySampler: { sampler: "filtering"; };}>
bindGroupLayout = const tgpu: { const: typeof import("node_modules/typegpu/src/core/constant/tgpuConstant").constant; fn: typeof import("node_modules/typegpu/src/core/function/tgpuFn").fn; comptime: typeof import("node_modules/typegpu/src/core/function/comptime").comptime; resolve: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolve; resolveWithContext: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolveWithContext; init: typeof import("node_modules/typegpu/src/core/root/init").init; initFromDevice: typeof import("node_modules/typegpu/src/core/root/init").initFromDevice; slot: typeof import("node_modules/typegpu/src/core/slot/slot").slot; lazy: typeof import("node_modules/typegpu/src/core/slot/lazy").lazy; ... 10 more ...; '~unstable': typeof import("node_modules/typegpu/src/tgpuUnstable");}
tgpu.bindGroupLayout: <{ myTexture: { texture: d.WgslTexture2d<d.F32>; }; mySampler: { sampler: "filtering"; };}>(entries: { myTexture: { texture: d.WgslTexture2d<d.F32>; }; mySampler: { sampler: "filtering"; };}) => TgpuBindGroupLayout<{ myTexture: { texture: d.WgslTexture2d<d.F32>; }; mySampler: { sampler: "filtering"; };}>
bindGroupLayout({ myTexture: { texture: d.WgslTexture2d<d.F32>;}
myTexture: { texture: d.WgslTexture2d<d.F32>
texture: import d
d.function texture2d(): d.WgslTexture2d<d.F32> (+1 overload)export texture2d
texture2d() }, mySampler: { sampler: "filtering";}
mySampler: { sampler: "filtering"
sampler: 'filtering' },});
const const bindGroup: TgpuBindGroup<{ myTexture: { texture: d.WgslTexture2d<d.F32>; }; mySampler: { sampler: "filtering"; };}>
bindGroup = const root: TgpuRoot
root.TgpuRoot.createBindGroup<{ myTexture: { texture: d.WgslTexture2d<d.F32>; }; mySampler: { sampler: "filtering"; };}>(layout: TgpuBindGroupLayout<{ myTexture: { texture: d.WgslTexture2d<d.F32>; }; mySampler: { sampler: "filtering"; };}>, entries: ExtractBindGroupInputFromLayout<{ myTexture: { texture: d.WgslTexture2d<d.F32>; }; mySampler: { sampler: "filtering"; };}>): TgpuBindGroup<{ myTexture: { texture: d.WgslTexture2d<d.F32>; }; mySampler: { sampler: "filtering"; };}>
Creates a group of resources that can be bound to a shader based on a specified layout.
createBindGroup(const bindGroupLayout: TgpuBindGroupLayout<{ myTexture: { texture: d.WgslTexture2d<d.F32>; }; mySampler: { sampler: "filtering"; };}>
bindGroupLayout, { myTexture: GPUTextureView | GPUTexture | (SampledFlag & TgpuTexture<{ size: readonly number[]; format: GPUTextureFormat; dimension?: "2d" | undefined; sampleCount?: 1 | undefined;}>) | TgpuTextureView<d.WgslTexture<WgslTextureProps>>
myTexture: const texture: TgpuTexture<{ size: [256, 256]; format: "rgba8unorm";}> & SampledFlag
texture, // views can also be used - as long as the schema matches // myTexture: texture.createView(), mySampler: TgpuSampler | GPUSampler
mySampler: const sampler: TgpuFixedSampler
sampler,});Using fixed resources
Section titled “Using fixed resources”For textures that remain consistent across operations, you can create fixed texture views:
const const texture: TgpuTexture<{ size: [256, 256]; format: "rgba8unorm";}> & SampledFlag
texture = const root: TgpuRoot
root.TgpuRoot.createTexture<number, number, number, [256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<{ size: [256, 256]; format: "rgba8unorm";}>
createTexture({ size: [256, 256]
The width, height, and depth or layer count of the texture.
size: [256, 256], format: "rgba8unorm"
The format of the texture.
format: 'rgba8unorm',}).TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; }>.$usage<["sampled"]>(usages_0: "sampled"): TgpuTexture<{ size: [256, 256]; format: "rgba8unorm";}> & SampledFlag
$usage('sampled');
// Create a fixed sampled viewconst const sampledView: TgpuTextureView<d.WgslTexture2d<d.F32>>
sampledView = const texture: TgpuTexture<{ size: [256, 256]; format: "rgba8unorm";}> & SampledFlag
texture.TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; }>.createView(): TgpuTextureView<d.WgslTexture2d<d.F32>> (+3 overloads)
createView();
const const sampler: TgpuFixedSampler
sampler = const root: TgpuRoot
root.TgpuRoot.createSampler(props: WgslSamplerProps): TgpuFixedSampler
createSampler({ WgslSamplerProps.magFilter?: GPUFilterMode | undefined
Specifies the sampling behavior when the sample footprint is smaller than or equal to one
texel.
magFilter: 'linear', WgslSamplerProps.minFilter?: GPUFilterMode | undefined
Specifies the sampling behavior when the sample footprint is larger than one texel.
minFilter: 'linear',});
const const myShader: TgpuFn<(uv: d.Vec2f) => d.Vec4f>
myShader = const tgpu: { const: typeof import("node_modules/typegpu/src/core/constant/tgpuConstant").constant; fn: typeof import("node_modules/typegpu/src/core/function/tgpuFn").fn; comptime: typeof import("node_modules/typegpu/src/core/function/comptime").comptime; resolve: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolve; resolveWithContext: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolveWithContext; init: typeof import("node_modules/typegpu/src/core/root/init").init; initFromDevice: typeof import("node_modules/typegpu/src/core/root/init").initFromDevice; slot: typeof import("node_modules/typegpu/src/core/slot/slot").slot; lazy: typeof import("node_modules/typegpu/src/core/slot/lazy").lazy; ... 10 more ...; '~unstable': typeof import("node_modules/typegpu/src/tgpuUnstable");}
tgpu.fn: <[d.Vec2f], d.Vec4f>(argTypes: [d.Vec2f], returnType: d.Vec4f) => TgpuFnShell<[d.Vec2f], d.Vec4f> (+2 overloads)
fn([import d
d.const vec2f: d.Vec2f
vec2f], import d
d.const vec4f: d.Vec4f
vec4f)((uv: d.v2f
uv) => { 'use gpu'; // Use the fixed texture view directly return import std
std.textureSample<d.texture2d<d.F32>>(texture: d.texture2d<d.F32>, sampler: d.sampler, coords: d.v2f, offset?: d.v2i): d.v4f (+8 overloads)export textureSample
textureSample(const sampledView: TgpuTextureView<d.WgslTexture2d<d.F32>>
sampledView.TgpuTextureView<WgslTexture2d<F32>>.$: d.texture2d<d.F32>
$, const sampler: TgpuFixedSampler
sampler.TgpuSampler.$: d.sampler
$, uv: d.v2f
uv);});© Software Mansion 2026. All trademarks and copyrights belong to their respective owners. Read about our Privacy Policy.