Skip to content

Instantly share code, notes, and snippets.

@n-yoda
Created October 26, 2016 10:26
Show Gist options
  • Save n-yoda/cf61b8ead959c9eae4d4683ababa0dec to your computer and use it in GitHub Desktop.
Save n-yoda/cf61b8ead959c9eae4d4683ababa0dec to your computer and use it in GitHub Desktop.
WebGL Image Processing Example
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>WebGL Image Processing</title>
</head>
<body>
<input style="display:block;" type="file" id="texture"/>
<canvas style="display:block;" id="canvas" width="512" height="512"></canvas>
<textarea id="log" style="display:block; width:100%; height:20em"></textarea>
<script type="x-shader/x-vertex" id="vert">
attribute vec2 pos;
varying vec2 uv;
void main(void) {
gl_Position = vec4(pos.x * 2.0 - 1.0, 1.0 - pos.y * 2.0, 0, 1);
uv = vec2(pos.x, pos.y);
}
</script>
<script type="x-shader/x-fragment" id="frag">
precision highp float;
varying vec2 uv;
uniform vec2 size;
uniform sampler2D tex;
vec4 boxBlur(sampler2D tex, vec2 uv) {
const int range = 50;
vec2 texelSize = 1.0 / size;
vec4 c = vec4(0.0, 0.0, 0.0, 0.0);
for (int i = -range; i <= range; ++ i) {
for (int j = -range; j <= range; ++ j) {
c += texture2D(tex, uv + vec2(i, j) * texelSize);
}
}
int loopCount = (range * 2 + 1) * (range * 2 + 1);
return c / float(loopCount);
}
void main(void) {
gl_FragColor = boxBlur(tex, uv);
}
</script>
<script>
var canvas = document.getElementById('canvas');
var logArea = document.getElementById('log');
var file = document.getElementById("texture");
function log() {
console.log.apply(console, arguments);
var s = '';
for (var i = 0; i < arguments.length; i++) {
if (i > 0) s += ' ';
s += arguments[i];
}
logArea.textContent = s + '\n' + logArea.textContent;
}
var gl = canvas.getContext('webgl');
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
var vert = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vert, document.getElementById("vert").textContent);
gl.compileShader(vert);
if (!gl.getShaderParameter(vert, gl.COMPILE_STATUS)) {
log(gl.getShaderInfoLog(vert))
}
var frag = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(frag, document.getElementById("frag").textContent);
gl.compileShader(frag);
if (!gl.getShaderParameter(frag, gl.COMPILE_STATUS)) {
log(gl.getShaderInfoLog(frag))
}
var prog = gl.createProgram();
gl.attachShader(prog, vert);
gl.attachShader(prog, frag);
gl.linkProgram(prog);
gl.validateProgram(prog);
if (gl.getProgramParameter(prog, gl.LINK_STATUS)) {
log(gl.getProgramInfoLog(prog));
}
gl.useProgram(prog);
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
// TODO: gl.LINEAR_MIPMAP_LINEA
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.uniform1i(gl.getUniformLocation(prog, 'tex'), 0);
var buffer = gl.createBuffer();
var verts = Float32Array.from([
0, 0, 0, 1, 1, 1,
0, 0, 1, 1, 1, 0,
]);
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, verts.buffer, gl.STATIC_DRAW);
var pos = gl.getAttribLocation(prog, "pos");
gl.enableVertexAttribArray(pos);
gl.vertexAttribPointer(pos, 2, gl.FLOAT, gl.FALSE, 0 /*tight*/, 0);
file.addEventListener('change', function() {
log('file change');
var img = new Image();
var url = URL.createObjectURL(file.files[0]);
img.onload = function() {
log('img onload', img.width, img.height);
canvas.width = img.width;
canvas.height = img.height;
log('drawingBuffer', gl.drawingBufferWidth, gl.drawingBufferHeight);
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
gl.clearColor(1.0, 1.0, 1.0, 0.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, img);
gl.uniform2f(gl.getUniformLocation(prog, 'size'), img.width, img.height);
// TODO: NPOT padding and gl.generateMipmap(gl.TEXTURE_2D);
gl.drawArrays(gl.TRIANGLES, 0, 6);
URL.revokeObjectURL(url);
};
img.src = url;
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment