Signatur
Beschreibung
In WebGPU greifen Shader und Render-Passes nie direkt auf eine GPUTexture zu, sondern immer über eine Texture-View. createView() erzeugt diese View und legt fest, welcher Ausschnitt der Textur wie interpretiert wird: zum Beispiel nur ein Mip-Level, eine einzelne Ebene eines Texture-Arrays, eine Würfelkarte ("cube") aus sechs Array-Ebenen oder nur der Tiefenanteil einer Depth-Stencil-Textur.
Ruft man die Methode ohne Argument auf, bekommt man eine Standard-View, die die ganze Textur mit ihrem eigenen Format und ihrer Dimension abdeckt. Das ist der häufigste Fall, etwa für context.getCurrentTexture().createView() als Farbziel eines Render-Passes oder für eine Textur, die über eine Bind Group an einen Shader gebunden wird.
Explizite Deskriptoren braucht man vor allem für Mipmap-Erzeugung (jede Stufe als eigenes Render-Ziel), Cubemaps und Shadow-Maps (einzelne Layer als Ziel, Array-View zum Abtasten) und für Format-Uminterpretation, z. B. "rgba8unorm" als "rgba8unorm-srgb". Das ist nur erlaubt, wenn das Zielformat bei der Texturerstellung in viewFormats angegeben wurde.
Views sind leichtgewichtige Objekte. Für die Swap-Chain-Textur des Canvas muss man in jedem Frame eine neue View erzeugen, weil getCurrentTexture() jedes Mal eine andere Textur liefern kann. Views für dauerhafte Texturen legt man dagegen einmal an und verwendet sie wieder.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $descriptor | GPUTextureViewDescriptor | {} | Optionales Konfigurationsobjekt. Fehlende Felder werden aus der Textur abgeleitet. Mögliche Felder siehe unten. |
| $descriptor.label | string | "" | Name zur Fehlersuche. Er erscheint in Fehlermeldungen und Debugging-Werkzeugen. |
| $descriptor.format | GPUTextureFormat | Format der Textur | Format der View. Es muss dem Texturformat entsprechen oder in viewFormats der Textur aufgeführt sein. |
| $descriptor.dimension | "1d" | "2d" | "2d-array" | "cube" | "cube-array" | "3d" | abgeleitet aus Textur-Dimension und Layer-Anzahl | Wie die Daten interpretiert werden. "cube" braucht genau 6 Array-Layer, "cube-array" ein Vielfaches von 6. |
| $descriptor.usage | GPUTextureUsageFlags | 0 (= alle Usages der Textur) | Schränkt die erlaubten Verwendungen der View ein. Die Flags müssen eine Teilmenge der Textur-Usages sein. Neueres Feld, nicht überall unterstützt. |
| $descriptor.aspect | "all" | "depth-only" | "stencil-only" | "all" | Welcher Teil einer Depth-/Stencil-Textur sichtbar ist. Zum Abtasten einer kombinierten Depth-Stencil-Textur im Shader braucht man "depth-only" oder "stencil-only". |
| $descriptor.baseMipLevel | number | 0 | Erstes Mip-Level, das die View enthält. |
| $descriptor.mipLevelCount | number | mipLevelCount − baseMipLevel | Anzahl der Mip-Levels ab baseMipLevel. Für Render-Ziele muss der Wert 1 sein. |
| $descriptor.baseArrayLayer | number | 0 | Erste Array-Ebene der View. |
| $descriptor.arrayLayerCount | number | abhängig von dimension (1, 6 oder verbleibende Layer) | Anzahl der Array-Ebenen ab baseArrayLayer. |
Rückgabewert
GPUTextureView. Man kann sie als Farb- oder Tiefenanhang in beginRenderPass() oder als Ressource in einer Bind Group verwenden. Ist der Deskriptor ungültig, wird trotzdem ein Objekt zurückgegeben. Es ist dann aber ungültig, und ein Validierungsfehler wird auf dem Gerät gemeldet (keine Exception).Beispiele
Canvas-Textur als Render-Ziel (Standard-View pro Frame)
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
const canvas = document.querySelector('canvas');
const context = canvas.getContext('webgpu');
const format = navigator.gpu.getPreferredCanvasFormat();
context.configure({ device, format });
const frame = () => {
// Jedes Frame eine neue View erzeugen!
const view = context.getCurrentTexture().createView();
const encoder = device.createCommandEncoder();
const pass = encoder.beginRenderPass({
colorAttachments: [{
view,
clearValue: { r: 0.1, g: 0.2, b: 0.4, a: 1 },
loadOp: 'clear',
storeOp: 'store'
}]
});
pass.end();
device.queue.submit([encoder.finish()]);
requestAnimationFrame(frame);
};
requestAnimationFrame(frame);
Eine View pro Mip-Level für die Mipmap-Erzeugung
const texture = device.createTexture({
size: [512, 512],
format: 'rgba8unorm',
mipLevelCount: 10,
usage: GPUTextureUsage.TEXTURE_BINDING |
GPUTextureUsage.RENDER_ATTACHMENT |
GPUTextureUsage.COPY_DST
});
// Jedes Level einzeln ansprechen: Quelle = Level i-1, Ziel = Level i
const mipViews = Array.from({ length: texture.mipLevelCount }, (_, level) =>
texture.createView({
label: `mip ${level}`,
baseMipLevel: level,
mipLevelCount: 1
})
);
console.log(mipViews.length);
Cubemap und Tiefen-View für Shadow Mapping
// Skybox: 6 Layer als Würfelkarte interpretieren
const cubeTexture = device.createTexture({
size: [1024, 1024, 6],
format: 'rgba8unorm',
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST
});
const cubeView = cubeTexture.createView({ dimension: 'cube' });
// Depth-Stencil-Textur: nur den Tiefenanteil im Shader abtasten
const depthTexture = device.createTexture({
size: [2048, 2048],
format: 'depth24plus-stencil8',
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING
});
const depthOnlyView = depthTexture.createView({ aspect: 'depth-only' });
const sampler = device.createSampler({ magFilter: 'linear', minFilter: 'linear' });
// bindGroupLayout stammt aus der eigenen Pipeline
const bindGroup = device.createBindGroup({
layout: bindGroupLayout,
entries: [
{ binding: 0, resource: sampler },
{ binding: 1, resource: cubeView },
{ binding: 2, resource: depthOnlyView }
]
});
sRGB-Uminterpretation über viewFormats
const tex = device.createTexture({
size: [256, 256],
format: 'rgba8unorm',
viewFormats: ['rgba8unorm-srgb'], // nötig für die Uminterpretation
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT
});
const linearView = tex.createView();
const srgbView = tex.createView({ format: 'rgba8unorm-srgb' });
console.log(srgbView instanceof GPUTextureView);