The second argument of getContext() holds context attributes, fixed for the canvas's lifetime and reported by gl.getContextAttributes(). On by default: alpha, premultipliedAlpha (Premultiplied Alpha), depth (24 bits here) and antialias (4 samples). Off: stencil, preserveDrawingBuffer, desynchronized, xrCompatible and failIfMajorPerformanceCaveat (null rather than a slow software context). powerPreference ('low-power', 'high-performance') picks a GPU on dual-GPU laptops, but it is a hint: here 'low-power' still got the GTX
The listing draws one tilted cover into three tiny canvases, enlarged, over a striped page:
<div id="row" style="display:flex;gap:12px;font:13px Arial;text-align:center;
background:repeating-linear-gradient(45deg,#ece8de 0 8px,#d6cdbb 8px 16px)"></div>
<script src="webgl-helper.js"></script>
<script>
for (const attributes of [{}, { antialias: false }, { alpha: false }]) {
const box = document.getElementById('row').appendChild(document.createElement('div'));
const canvas = Object.assign(box.appendChild(document.createElement('canvas')),
{ width: 60, height: 40, style: 'display:block;width:210px;image-rendering:pixelated' });
box.append(JSON.stringify(attributes));
const gl = canvas.getContext('webgl2', attributes);
gl.useProgram(GLH.program(gl, `#version 300 es
void main() { // a tilted cover from gl_VertexID
vec2 p = vec2(gl_VertexID & 1, gl_VertexID >> 1) * 2.0 - 1.0;
p = mat2(0.94, 0.34, -0.34, 0.94) * (p * vec2(0.45, 0.7));
gl_Position = vec4(p.x / 1.5, p.y, 0.0, 1.0); }`, // 60 x 40 pixels: aspect 1.5
`#version 300 es
precision mediump float; out vec4 c; void main() { c = vec4(0.71, 0.27, 0.18, 1); }`));
gl.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); // transparent black
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
}
window.__done = true;
</script>
With the defaults ({}), the stripes show through and edges are blended; antialias: false leaves staircases; alpha: false turns the transparent clear black but spares the compositor a blend. Set preserveDrawingBuffer when a screenshot button calls toDataURL() in a later task, after the buffer has been cleared.
<!doctype html>
<style>
body { margin: 0; font: 11px system-ui, sans-serif; background: #f7f4ee; color: #333; }
#row { display: flex; gap: 12px; max-width: 600px; padding: 8px; box-sizing: border-box; text-align: center;
background: repeating-linear-gradient(45deg, #ece8de 0 8px, #d6cdbb 8px 16px); }
#row > div { flex: 1; }
canvas { display: block; width: 100%; image-rendering: pixelated; }
code { display: block; background: rgba(255,255,255,0.8); margin-top: 4px; font-size: 10px; }
</style>
<div id="row"></div>
<script>
for (const attributes of [{}, { antialias: false }, { alpha: false, powerPreference: 'low-power' }]) {
const box = document.getElementById('row').appendChild(document.createElement('div'));
const canvas = Object.assign(box.appendChild(document.createElement('canvas')), { width: 60, height: 40 });
const gl = canvas.getContext('webgl2', attributes); // attributes: first call only, fixed for life
const program = gl.createProgram();
for (const [type, src] of [[gl.VERTEX_SHADER, `#version 300 es
void main() { // a tilted cover from gl_VertexID
vec2 p = vec2(gl_VertexID & 1, gl_VertexID >> 1) * 2.0 - 1.0;
p = mat2(0.94, 0.34, -0.34, 0.94) * (p * vec2(0.45, 0.7));
gl_Position = vec4(p.x / 1.5, p.y, 0.0, 1.0); }`, // 60 x 40 pixels: aspect 1.5
], [gl.FRAGMENT_SHADER, `#version 300 es
precision mediump float; out vec4 c; void main() { c = vec4(0.71, 0.27, 0.18, 1); }`]]) {
const s = gl.createShader(type); gl.shaderSource(s, src); gl.compileShader(s); gl.attachShader(program, s);
}
gl.linkProgram(program); gl.useProgram(program);
gl.bindVertexArray(gl.createVertexArray());
gl.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); // transparent black
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
const got = gl.getContextAttributes();
box.insertAdjacentHTML('beforeend', `<code>${JSON.stringify(attributes)}<br>alpha ${got.alpha}, antialias ${got.antialias}, ` +
`depth ${got.depth}, stencil ${got.stencil}, SAMPLES ${gl.getParameter(gl.SAMPLES)}</code>`);
}
</script>