Signatur
Beschreibung
Die Erweiterung OES_element_index_uint gehört zur WebGL API. Sie erlaubt den Typ gl.UNSIGNED_INT (32-Bit-Indizes) beim indizierten Zeichnen mit WebGLRenderingContext.drawElements(). Ohne diese Erweiterung sind in WebGL 1 nur gl.UNSIGNED_BYTE und gl.UNSIGNED_SHORT zulässig. Ein einzelner Draw-Call kann dann höchstens 65.536 verschiedene Vertices adressieren.
Man braucht sie vor allem für große Geometrien: hochaufgelöste Terrain-Meshes, eingescannte 3D-Modelle, Punktwolken mit Dreiecksnetz oder CAD-Daten. Ohne die Erweiterung müsste man solche Modelle in mehrere Teil-Meshes aufteilen.
Die Schnittstelle hat keine eigenen Methoden, Eigenschaften oder Konstanten. Es reicht, sie mit gl.getExtension("OES_element_index_uint") zu aktivieren. Danach ist die bereits vorhandene Konstante gl.UNSIGNED_INT (0x1405) als type-Argument in drawElements() gültig. Die Indexdaten übergibt man als Uint32Array an einen ELEMENT_ARRAY_BUFFER.
In WebGL 2 (WebGL2RenderingContext) ist diese Funktion fest eingebaut. Dort gibt es die Erweiterung nicht, und getExtension() liefert für diesen Namen null.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $name Pflicht | string | Argument von gl.getExtension(): exakt "OES_element_index_uint". |
Rückgabewert
gl.getExtension("OES_element_index_uint") gibt ein (leeres) Erweiterungsobjekt zurück. Ist die Erweiterung nicht verfügbar, etwa in einem WebGL-2-Kontext, lautet der Rückgabewert null.Beispiele
Erweiterung aktivieren und Unterstützung prüfen
const canvas = document.createElement("canvas");
const gl = canvas.getContext("webgl");
const ext = gl.getExtension("OES_element_index_uint");
if (ext) {
console.log("32-Bit-Indizes verfügbar");
} else {
console.log("Nur 16-Bit-Indizes – Mesh muss aufgeteilt werden");
}
Großes Gitter-Mesh mit Uint32Array-Indizes zeichnen
const gl = document.querySelector("canvas").getContext("webgl");
const hasUint = !!gl.getExtension("OES_element_index_uint");
// Gitter mit 400 × 400 = 160.000 Vertices (> 65.536)
const size = 400;
const positions = new Float32Array(size * size * 2);
for (let y = 0; y < size; y++) {
for (let x = 0; x < size; x++) {
const i = (y * size + x) * 2;
positions[i] = (x / (size - 1)) * 2 - 1;
positions[i + 1] = (y / (size - 1)) * 2 - 1;
}
}
const indices = [];
for (let y = 0; y < size - 1; y++) {
for (let x = 0; x < size - 1; x++) {
const a = y * size + x;
const b = a + 1;
const c = a + size;
const d = c + 1;
indices.push(a, b, c, b, d, c);
}
}
const vs = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vs, "attribute vec2 p; void main(){ gl_Position = vec4(p, 0.0, 1.0); }");
gl.compileShader(vs);
const fs = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fs, "precision mediump float; void main(){ gl_FragColor = vec4(0.2, 0.6, 1.0, 1.0); }");
gl.compileShader(fs);
const prog = gl.createProgram();
gl.attachShader(prog, vs);
gl.attachShader(prog, fs);
gl.linkProgram(prog);
gl.useProgram(prog);
const vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
const loc = gl.getAttribLocation(prog, "p");
gl.enableVertexAttribArray(loc);
gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);
if (hasUint) {
const ibo = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(indices), gl.STATIC_DRAW);
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_INT, 0);
console.log("Gezeichnet:", indices.length / 3, "Dreiecke");
}
Passenden Indextyp für WebGL 1 und WebGL 2 wählen
const getIndexSetup = (gl, vertexCount) => {
const isWebGL2 = typeof WebGL2RenderingContext !== "undefined" &&
gl instanceof WebGL2RenderingContext;
const uintOk = isWebGL2 || !!gl.getExtension("OES_element_index_uint");
if (vertexCount <= 65536) {
return { ArrayType: Uint16Array, glType: gl.UNSIGNED_SHORT };
}
if (uintOk) {
return { ArrayType: Uint32Array, glType: gl.UNSIGNED_INT };
}
throw new Error("Mesh zu groß für 16-Bit-Indizes – bitte aufteilen");
};
const gl = document.createElement("canvas").getContext("webgl");
const { ArrayType, glType } = getIndexSetup(gl, 100000);
console.log(ArrayType.name, glType === gl.UNSIGNED_INT);
// Wichtig · Fallstricke
- WebGL 2: Hier ist
gl.UNSIGNED_INTimmer erlaubt.getExtension("OES_element_index_uint")liefertnull. Einnullbedeutet dort also nicht, dass die Funktion fehlt. - Aktivierung ist Pflicht: Rufst du in WebGL 1
drawElements(..., gl.UNSIGNED_INT, ...)auf, ohne vorhergetExtension()aufzurufen, erzeugt das den Fehlergl.INVALID_ENUMund es wird nichts gezeichnet. Das Vorhandensein der Konstantegl.UNSIGNED_INTsagt nichts über die Unterstützung aus. - Offset-Ausrichtung: Der
offset-Parameter vondrawElements()muss beiUNSIGNED_INTein Vielfaches von 4 sein, sonst gibt esINVALID_OPERATION. - Speicher und Leistung: 32-Bit-Indizes brauchen doppelt so viel Speicher wie 16-Bit-Indizes. Nutze sie deshalb nur, wenn ein Mesh wirklich mehr als 65.536 Vertices hat.
- Kompatibilität: Die Erweiterung wird von praktisch allen Desktop- und Mobilbrowsern mit WebGL 1 unterstützt. Auf sehr alten mobilen GPUs kann sie fehlen, deshalb immer auf
nullprüfen. - Nach einem Kontextverlust (
webglcontextlost) muss die Erweiterung neu angefordert werden.