Signatur
Beschreibung
Ein GPUSampler gibt vor, wie ein Shader eine Textur ausliest: welcher Filter beim Vergrößern und Verkleinern greift (nearest oder linear), was mit Texturkoordinaten außerhalb von 0–1 passiert (clamp-to-edge, repeat, mirror-repeat), wie zwischen Mipmap-Stufen interpoliert wird und ob anisotrop gefiltert wird. Ein Sampler speichert selbst keine Bilddaten. Er ist ein kleines, unveränderliches Konfigurationsobjekt, das Sie mit beliebig vielen Texturen kombinieren können.
Einen Sampler legen Sie nie mit einem Konstruktor an, sondern immer über GPUDevice.createSampler(descriptor). Danach binden Sie ihn über eine GPUBindGroup an den Shader. In WGSL deklarieren Sie ihn als sampler (normales Filtern) oder als sampler_comparison (Vergleichs-Sampler, etwa für Shadow Mapping). Gelesen wird dann mit Funktionen wie textureSample() bzw. textureSampleCompare().
Die Schnittstelle hat außer label keine eigenen Eigenschaften oder Methoden. label ist ein frei wählbarer Name, der in Fehlermeldungen und Debug-Werkzeugen angezeigt wird. Alle Einstellungen stehen fest, sobald createSampler() aufgerufen wurde. Brauchen Sie ein anderes Verhalten, erzeugen Sie einen neuen Sampler.
Die folgenden Felder des Deskriptors für createSampler() bestimmen das Verhalten des Samplers.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $label | string | "" | Name für Debugging und Fehlermeldungen. Bleibt auch nach der Erstellung als Eigenschaft GPUSampler.label les- und schreibbar. |
| $addressModeU | "clamp-to-edge" | "repeat" | "mirror-repeat" | "clamp-to-edge" | Legt fest, wie Koordinaten außerhalb von 0–1 in horizontaler Richtung (U/Breite) behandelt werden. |
| $addressModeV | "clamp-to-edge" | "repeat" | "mirror-repeat" | "clamp-to-edge" | Wie addressModeU, aber für die vertikale Richtung (V/Höhe). |
| $addressModeW | "clamp-to-edge" | "repeat" | "mirror-repeat" | "clamp-to-edge" | Wie addressModeU, aber für die Tiefe (W) bei 3D-Texturen. |
| $magFilter | "nearest" | "linear" | "nearest" | Filter für den Fall, dass die Textur vergrößert dargestellt wird (ein Texel deckt mehr als ein Pixel ab). |
| $minFilter | "nearest" | "linear" | "nearest" | Filter für den Fall, dass die Textur verkleinert dargestellt wird. |
| $mipmapFilter | "nearest" | "linear" | "nearest" | Legt fest, wie zwischen Mipmap-Stufen interpoliert wird. linear ergibt zusammen mit linearem min-/magFilter trilineares Filtern. |
| $lodMinClamp | number | 0 | Unterste Detailstufe (LOD), auf die beim Samplen begrenzt wird. |
| $lodMaxClamp | number | 32 | Oberste Detailstufe (LOD), auf die beim Samplen begrenzt wird. Muss mindestens so groß wie lodMinClamp sein. |
| $compare | "never" | "less" | "equal" | "less-equal" | "greater" | "not-equal" | "greater-equal" | "always" | Ist das Feld gesetzt, entsteht ein Vergleichs-Sampler (WGSL: sampler_comparison). Er wird typischerweise für Tiefentexturen beim Shadow Mapping verwendet. |
|
| $maxAnisotropy | number | 1 | Höchster Grad der anisotropen Filterung, zulässig sind Werte von 1 bis 65535; die Implementierung begrenzt intern auf ihr Maximum (meist 16). Ein Wert über 1 setzt voraus, dass magFilter, minFilter und mipmapFilter alle auf linear stehen. |
Rückgabewert
GPUDevice.createSampler() gibt eine GPUSampler-Instanz zurück. Ihre einzige Eigenschaft ist label (string).Beispiele
Sampler erzeugen und label auslesen
const adapter = await navigator.gpu?.requestAdapter();
if (!adapter) throw new Error('WebGPU wird nicht unterstützt');
const device = await adapter.requestDevice();
// Linear filternder, kachelnder Sampler (z. B. für Bodentexturen)
const sampler = device.createSampler({
label: 'Boden-Sampler',
addressModeU: 'repeat',
addressModeV: 'repeat',
magFilter: 'linear',
minFilter: 'linear',
mipmapFilter: 'linear',
maxAnisotropy: 16,
});
console.log(sampler instanceof GPUSampler, sampler.label);
Sampler zusammen mit einer Textur über eine BindGroup binden
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
const shaderModule = device.createShaderModule({
code: `
@group(0) @binding(0) var mySampler: sampler;
@group(0) @binding(1) var myTexture: texture_2d<f32>;
@vertex fn vs(@builtin(vertex_index) i: u32) -> @builtin(position) vec4f {
var pos = array(vec2f(-1, -1), vec2f(3, -1), vec2f(-1, 3));
return vec4f(pos[i], 0, 1);
}
@fragment fn fs(@builtin(position) p: vec4f) -> @location(0) vec4f {
return textureSample(myTexture, mySampler, p.xy / 256.0);
}
`,
});
const texture = device.createTexture({
size: [256, 256],
format: 'rgba8unorm',
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,
});
// Pixel-Art-Look: keine Interpolation
const sampler = device.createSampler({ magFilter: 'nearest', minFilter: 'nearest' });
const pipeline = device.createRenderPipeline({
layout: 'auto',
vertex: { module: shaderModule, entryPoint: 'vs' },
fragment: {
module: shaderModule,
entryPoint: 'fs',
targets: [{ format: navigator.gpu.getPreferredCanvasFormat() }],
},
});
const bindGroup = device.createBindGroup({
layout: pipeline.getBindGroupLayout(0),
entries: [
{ binding: 0, resource: sampler },
{ binding: 1, resource: texture.createView() },
],
});
console.log('BindGroup bereit:', bindGroup instanceof GPUBindGroup);
Vergleichs-Sampler für Shadow Mapping
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
// Im WGSL-Shader als sampler_comparison deklarieren
// und mit textureSampleCompare() verwenden
const shadowSampler = device.createSampler({
label: 'Schatten-Sampler',
compare: 'less',
magFilter: 'linear', // weiche Kanten (PCF in Hardware)
minFilter: 'linear',
});
console.log(shadowSampler.label);