Skip to content

Instantly share code, notes, and snippets.

@greggman
Last active May 22, 2024 02:13
Show Gist options
  • Save greggman/ec4441fd538cdda23c27f266a0016a1a to your computer and use it in GitHub Desktop.
Save greggman/ec4441fd538cdda23c27f266a0016a1a to your computer and use it in GitHub Desktop.
WebGL: Test textureGrad vs texture
html, body {
margin: 0;
font-family: monospace;
height: 100%;
background-color: #333;
}
canvas {
margin: 5px;
border: 1px solid #888;
display: inline-block;
width: 32px;
height: 32px;
}
/*bug-in-github-api-content-can-not-be-empty*/
import * as twgl from 'https://twgljs.org/dist/5.x/twgl-full.module.js';
const vs = `#version 300 es
uniform mat3 u_texMat;
out vec2 v_texCoord;
const vec2 position[6] = vec2[6](
vec2(0, 0),
vec2(1, 0),
vec2(0, 1),
vec2(0, 1),
vec2(1, 0),
vec2(1, 1));
void main() {
vec2 p = position[gl_VertexID];
v_texCoord = (u_texMat * vec3(p, 1)).xy;
gl_Position = vec4(p * 2.0 - 1.0, 0, 1);
}
`;
const fsTex = `#version 300 es
precision highp float;
in vec2 v_texCoord;
uniform sampler2D u_tex;
out vec4 outColor;
void main() {
outColor = texture(u_tex, v_texCoord);
}
`;
const fsTexGrad = `#version 300 es
precision highp float;
in vec2 v_texCoord;
uniform sampler2D u_tex;
uniform vec2 ddx;
uniform vec2 ddy;
out vec4 outColor;
void main() {
outColor = textureGrad(u_tex, v_texCoord, ddx, ddy);
}
`;
const colors = [
'#F00', // 128
'#FF0', // 64
'#0F0', // 32
'#0FF', // 16
'#00F', // 8
'#F0F', // 4
'#888', // 2
'#FFF', // 1
'#f84'
];
function createMips(colors) {
const ctx = document.createElement('canvas').getContext('2d');
const numMips = colors.length;
return colors.map((color, i) => {
const size = 2 ** (numMips - i - 1);
ctx.canvas.width = size;
ctx.canvas.height = size;
ctx.fillStyle = color;
ctx.fillRect(0, 0, size, size);
return ctx.getImageData(0, 0, size, size);
});
}
function main() {
const m4 = twgl.m4;
const canvas = document.createElement("canvas");
const size = 2 ** (colors.length - 1);
canvas.width = size;
canvas.height = size;
const gl = canvas.getContext("webgl2");
if (!gl) {
alert("Sorry, this example requires WebGL 2.0"); // eslint-disable-line
return;
}
const texProgramInfo = twgl.createProgramInfo(gl, [vs, fsTex]);
const gradProgramInfo = twgl.createProgramInfo(gl, [vs, fsTexGrad]);
const texImage = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texImage);
const data = createMips(colors);
data.forEach(({width, height, data}, level) => {
gl.texImage2D(gl.TEXTURE_2D, level, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
});
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST);
for (let prgInfo of [texProgramInfo, gradProgramInfo]) {
for (let i = 0; i < colors.length; ++i) {
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.clearColor(0.3, 0.3, 0.3, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
const s = 2 ** i;
const uniforms = {
u_texMat: [
s, 0, 0,
0, s, 0,
0, 0, 1,
],
ddx: [s / size, 0],
ddy: [0, 0],
};
gl.useProgram(prgInfo.program);
twgl.setUniforms(prgInfo, uniforms);
gl.drawArrays(gl.TRIANGLES, 0, 6);
const c = document.createElement('canvas');
c.width = 32;
c.height = 32;
const ctx = c.getContext('2d', {willReadFrequently: true});
ctx.drawImage(gl.canvas, 0, 0);
document.body.appendChild(c);
}
document.body.appendChild(document.createElement('hr'));
}
}
main();
{"name":"WebGL: Test textureGrad vs texture","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