Skip to content

Instantly share code, notes, and snippets.

@greggman
Last active March 30, 2025 03:38
Show Gist options
  • Save greggman/bf612ffc797e2402e614d2ec0312762d to your computer and use it in GitHub Desktop.
Save greggman/bf612ffc797e2402e614d2ec0312762d to your computer and use it in GitHub Desktop.
WebGL: TEXTURE_MIN_LOD < 0
html, body {
margin: 0;
height: 100%;
}
canvas {
width: 100%;
height: 100%;
display: block;
}
<canvas></canvas>
import * as twgl from 'https://twgljs.org/dist/5.x/twgl-full.module.js';
import GUI from 'https://muigui.org/dist/0.x/muigui.module.js';
const vs = `#version 300 es
out vec2 uv;
uniform float mult;
void main() {
vec2 points[6];
points[0] = vec2( -1, -1);
points[1] = vec2( 1, -1);
points[2] = vec2( -1, 1);
points[3] = vec2( 1, -1);
points[4] = vec2( -1, 1);
points[5] = vec2( 1, 1);
vec2 xy = points[gl_VertexID];
gl_Position = vec4(xy, 0, 1);
uv = (xy * 0.5 + 0.5) * mult;
}
`
const fs = `#version 300 es
precision highp float;
in vec2 uv;
out vec4 fragColor;
uniform vec2 resolution;
uniform sampler2D tex;
void main() {
fragColor = texture(tex, uv);
}
`
const hsl = (h, s, l) => `hsl(${h * 360 | 0}, ${s * 100}%, ${l * 100 | 0}%)`;
const hsla = (h, s, l, a) => `hsl(${h * 360 | 0}, ${s * 100}%, ${l * 100 | 0}%, ${a})`;
const rgb = (r, g, b) => `rgb(${r * 255 | 0}, ${g * 255 | 0}, ${b * 255 | 0})`;
const rgba = (r, g, b, a) => `rgba(${r * 255 | 0}, ${g * 255 | 0}, ${b * 255 | 0, a})`;
const cssColorToRGBA8 = (() => {
const canvas = new OffscreenCanvas(1, 1);
const ctx = canvas.getContext('2d', {willReadFrequently: true});
return cssColor => {
ctx.clearRect(0, 0, 1, 1);
ctx.fillStyle = cssColor;
ctx.fillRect(0, 0, 1, 1);
return Array.from(ctx.getImageData(0, 0, 1, 1).data);
};
})();
const cssColorToRGBA = cssColor => cssColorToRGBA8(cssColor).map(v => v / 255);
const hslToRGBA = (h, s, l) => cssColorToRGBA(hsl(h, s, l));
const range = (num, fn) => new Array(num).fill(0).map((_, i) => fn(i));
const settings = {
TEXTURE_MIN_LOD: -2,
mult: 1,
}
const gui = new GUI();
gui.onChange(render);
gui.add(settings, 'TEXTURE_MIN_LOD', -2, 2);
gui.add(settings, 'mult', 0, 4).name('uv mult');
const canvas = document.querySelector("canvas");
const gl = canvas.getContext('webgl2', {alpha: false});
const programInfo = twgl.createProgramInfo(gl, [vs, fs]);
const size = 4;
const texture = twgl.createTexture(gl, {
src: range(size * size, (i) => {
const x = i % size;
const y = i / size | 0;
return cssColorToRGBA8(rgb(x / size, y / size, (x + y) % 2 ? 0 : 1));
}).flat(),
max: gl.LINEAR,
min: gl.LINEAR_MIPMAP_LINEAR,
});
function render() {
twgl.resizeCanvasToDisplaySize(canvas);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_LOD, settings.TEXTURE_MIN_LOD);
gl.viewport(0, 0, canvas.width, canvas.height);
gl.useProgram(programInfo.program);
twgl.setUniforms(programInfo, {
mult: settings.mult,
});
gl.drawArrays(gl.TRIANGLES, 0, 6);
}
const observer = new ResizeObserver(render);
observer.observe(canvas);
{"name":"WebGL: TEXTURE_MIN_LOD < 0","settings":{},"filenames":["index.html","index.css","index.js"]}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment