Created
October 26, 2016 10:26
-
-
Save n-yoda/cf61b8ead959c9eae4d4683ababa0dec to your computer and use it in GitHub Desktop.
WebGL Image Processing Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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