Signatur
Beschreibung
GPUTexture ist ein zentrales Ressourcen-Objekt der WebGPU API. Eine Textur enthält formatierte Texel-Daten (z. B. rgba8unorm, depth24plus) und kann als Bildquelle für Shader, als Farb- oder Tiefenziel eines Render-Durchlaufs oder als Speicher-Textur (storage texture) in Compute-Shadern dienen. Du erstellst sie nicht mit einem Konstruktor, sondern über GPUDevice.createTexture(descriptor). Die Textur des Canvas bekommst du bei jedem Frame über GPUCanvasContext.getCurrentTexture().
Shader greifen nie direkt auf eine Textur zu, sondern immer über eine Ansicht (GPUTextureView), die du mit createView() erzeugst. Eine Ansicht kann einen Teilbereich auswählen (Mip-Level, Array-Layer, Aspekt) oder die Daten anders interpretieren, z. B. als cube- oder 2d-array-Ansicht.
Alle Eigenschaften sind schreibgeschützt und spiegeln den Deskriptor wider, mit dem die Textur erstellt wurde:
width,height,depthOrArrayLayers– Abmessungenformat– Texelformat (GPUTextureFormat)dimension–"1d","2d"oder"3d"mipLevelCount,sampleCount– Anzahl der Mip-Stufen bzw. Multisampling-Samplesusage– Bitmaske ausGPUTextureUsage-Flagslabel– frei wählbarer Name für Fehlermeldungen und Debugging (beschreibbar)
Methoden: createView(descriptor?) erzeugt eine GPUTextureView, destroy() gibt den GPU-Speicher sofort frei. Daten überträgst du mit GPUQueue.writeTexture(), GPUQueue.copyExternalImageToTexture() oder mit Kopierbefehlen des GPUCommandEncoder.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $descriptor.size Pflicht | GPUExtent3D ([w, h?, d?] | {width, height?, depthOrArrayLayers?}) | Abmessungen der Textur; wird an device.createTexture() übergeben. |
|
| $descriptor.format Pflicht | GPUTextureFormat | Texelformat, z. B. "rgba8unorm", "bgra8unorm", "depth24plus". |
|
| $descriptor.usage Pflicht | number (GPUTextureUsage-Flags) | Bitmaske aus COPY_SRC, COPY_DST, TEXTURE_BINDING, STORAGE_BINDING, RENDER_ATTACHMENT. |
|
| $descriptor.dimension | "1d" | "2d" | "3d" | "2d" | Dimensionalität der Textur. |
| $descriptor.mipLevelCount | number | 1 | Anzahl der Mip-Stufen. |
| $descriptor.sampleCount | number | 1 | Samples pro Texel; 4 für Multisampling (MSAA). |
| $descriptor.viewFormats | GPUTextureFormat[] | [] | Zusätzliche Formate, die für createView() erlaubt sind (z. B. die sRGB-Variante). |
| $descriptor.label | string | "" | Name für Debugging und Fehlermeldungen. |
Rückgabewert
device.createTexture(descriptor) gibt ein neues GPUTexture-Objekt zurück. Bei ungültigem Deskriptor entsteht ein ungültiges Objekt, und es wird ein Validierungsfehler gemeldet – es wird keine Ausnahme geworfen.Beispiele
Textur erstellen und Eigenschaften lesen
const adapter = await navigator.gpu?.requestAdapter();
if (!adapter) throw new Error('WebGPU nicht verfügbar');
const device = await adapter.requestDevice();
const texture = device.createTexture({
label: 'Sprite-Atlas',
size: [512, 256],
format: 'rgba8unorm',
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST
});
console.log(texture.width, texture.height, texture.format, texture.dimension);
console.log((texture.usage & GPUTextureUsage.COPY_DST) !== 0);
Bild in eine Textur laden und für Shader binden
const loadTexture = async (device, url) => {
const blob = await (await fetch(url)).blob();
const bitmap = await createImageBitmap(blob, { colorSpaceConversion: 'none' });
const texture = device.createTexture({
label: url,
size: [bitmap.width, bitmap.height],
format: 'rgba8unorm',
usage: GPUTextureUsage.TEXTURE_BINDING |
GPUTextureUsage.COPY_DST |
GPUTextureUsage.RENDER_ATTACHMENT // für copyExternalImageToTexture nötig
});
device.queue.copyExternalImageToTexture(
{ source: bitmap },
{ texture },
[bitmap.width, bitmap.height]
);
bitmap.close();
return texture;
};
const texture = await loadTexture(device, '/img/holz.png');
const sampler = device.createSampler({ magFilter: 'linear', minFilter: 'linear' });
// pipeline wurde vorher mit layout: 'auto' erstellt
const bindGroup = device.createBindGroup({
layout: pipeline.getBindGroupLayout(0),
entries: [
{ binding: 0, resource: sampler },
{ binding: 1, resource: texture.createView() }
]
});
Tiefenpuffer passend zum Canvas und Freigabe bei Größenänderung
const canvas = document.querySelector('canvas');
const context = canvas.getContext('webgpu');
context.configure({ device, format: navigator.gpu.getPreferredCanvasFormat() });
let depthTexture = null;
const ensureDepthTexture = () => {
if (depthTexture &&
depthTexture.width === canvas.width &&
depthTexture.height === canvas.height) return depthTexture;
depthTexture?.destroy(); // alten GPU-Speicher sofort freigeben
depthTexture = device.createTexture({
label: 'Tiefenpuffer',
size: [canvas.width, canvas.height],
format: 'depth24plus',
usage: GPUTextureUsage.RENDER_ATTACHMENT
});
return depthTexture;
};
const frame = () => {
const encoder = device.createCommandEncoder();
const pass = encoder.beginRenderPass({
colorAttachments: [{
view: context.getCurrentTexture().createView(),
clearValue: { r: 0.1, g: 0.1, b: 0.15, a: 1 },
loadOp: 'clear',
storeOp: 'store'
}],
depthStencilAttachment: {
view: ensureDepthTexture().createView(),
depthClearValue: 1,
depthLoadOp: 'clear',
depthStoreOp: 'store'
}
});
pass.end();
device.queue.submit([encoder.finish()]);
requestAnimationFrame(frame);
};
requestAnimationFrame(frame);