Skip to content

Instantly share code, notes, and snippets.

@adrianseeley
Last active April 27, 2021 18:18
Show Gist options
  • Star 17 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save adrianseeley/f768fd7a3aab2370eafc to your computer and use it in GitHub Desktop.
Save adrianseeley/f768fd7a3aab2370eafc to your computer and use it in GitHub Desktop.
WEBGL COMPUTE SHADER SETUP
<!DOCTYPE html>
<html>
<canvas id="c" width="128" height="128"></canvas>
<script src="glutil.js"></script>
<script id="vshader" type="text/plain">
attribute vec2 vtxpos;
varying vec2 texpos;
void main() {
texpos = (vtxpos / 2.) + vec2(0.5, 0.5);
gl_Position = vec4(vtxpos, 0, 1);
}
</script>
<script id="fshader" type="text/plain">
precision mediump float;
varying vec2 texpos;
uniform sampler2D tex0;
void main() {
//vec4 tcol = texture2D(tex0, vec2(1. / PIXELS_WIDE, 0. / PIXELS_TALL));
vec4 tcol = vec4(0, 0, 0, 0);
for (float x = 0.0; x < PIXELS_WIDE; x++) {
for (float y = 0.0; y < PIXELS_TALL; y++) {
tcol += texture2D(tex0, vec2(x / PIXELS_WIDE, y / PIXELS_TALL));
}
}
tcol /= 100.;
gl_FragColor = tcol;
}
</script>
<script>
var c = document.getElementById('c');
var vs = document.getElementById('vshader').textContent;
var fs = document.getElementById('fshader').textContent.split('PIXELS_WIDE').join(c.width + '.').split('PIXELS_TALL').join(c.height + '.');
var gl = c.getContext('experimental-webgl');
var program = createProgram(vs, fs);
prepScreenQuad();
gl.useProgram(program);
gl.enableVertexAttribArray(program.vertexPosArray);
gl.vertexAttribPointer(program.vtxpos, 2, gl.FLOAT, false, 0, 0);
program.vtxpos = gl.getAttribLocation(program, 'vtxpos');
program.sampler = [gl.getUniformLocation(program, 'tex0')];
program.tex = [gl.createTexture()];
program.texbuff = [new Uint8Array(4 * c.width * c.height)];
var pxlbuff = new Uint8Array(4 * c.width * c.height);
for (var i = 0; i < program.texbuff[0].length; i++) {
program.texbuff[0][i] = 1;
}
//program.texbuff[0][0] = 100;
function blit () {
//requestAnimationFrame(blit);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, program.tex[0]);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, c.width, c.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, program.texbuff[0]);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
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(program.sampler[0], 0);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
gl.readPixels(0, 0, c.width, c.height, gl.RGBA, gl.UNSIGNED_BYTE, pxlbuff);
console.log(pxlbuff[0] + ', ' + pxlbuff[1] + ', ' + pxlbuff[2] + ', ' + pxlbuff[3]);
};
blit();
</script>
</html>
window.onerror = function (msg, url, lineno) {
alert(url + '(' + lineno + '): ' + msg);
}
function createShader (str, type) {
var shader = gl.createShader(type);
gl.shaderSource(shader, str);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
throw gl.getShaderInfoLog(shader);
return shader;
}
function createProgram (vstr, fstr) {
var program = gl.createProgram();
var vshader = createShader(vstr, gl.VERTEX_SHADER);
var fshader = createShader(fstr, gl.FRAGMENT_SHADER);
gl.attachShader(program, vshader);
gl.attachShader(program, fshader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS))
throw gl.getProgramInfoLog(program);
return program;
}
function screenQuad () {
var vertexPosBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer);
var vertices = [-1, -1, 1, -1, -1, 1, 1, 1];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
vertexPosBuffer.itemSize = 2;
vertexPosBuffer.numItems = 4;
/*
2___3
|\ |
| \ |
|__\|
0 1
*/
return vertexPosBuffer;
}
function linkProgram (program) {
var vshader = createShader(program.vshaderSource, gl.VERTEX_SHADER);
var fshader = createShader(program.fshaderSource, gl.FRAGMENT_SHADER);
gl.attachShader(program, vshader);
gl.attachShader(program, fshader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
throw gl.getProgramInfoLog(program);
}
}
function loadFile (file, callback, noCache, isJson) {
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.readyState == 1) {
if (isJson)
request.overrideMimeType('application/json');
request.send();
} else if (request.readyState == 4) {
if (request.status == 200)
callback(request.responseText);
else if (request.status == 404)
throw 'File "' + file + '" does not exist.';
else
throw 'XHR error ' + request.status + '.';
}
};
var url = file;
if (noCache)
url += '?' + (new Date()).getTime();
request.open('GET', url, true);
}
function loadProgram (vs, fs, callback) {
var program = gl.createProgram();
function vshaderLoaded(str) {
program.vshaderSource = str;
if (program.fshaderSource) {
linkProgram(program);
callback(program);
}
}
function fshaderLoaded (str) {
program.fshaderSource = str;
if (program.vshaderSource) {
linkProgram(program);
callback(program);
}
}
loadFile(vs, vshaderLoaded, true);
loadFile(fs, fshaderLoaded, true);
return program;
}
(function() {
var lastTime = 0;
var vendors = ['ms', 'moz', 'webkit', 'o'];
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
window.cancelRequestAnimationFrame = window[vendors[x] + 'CancelRequestAnimationFrame'];
}
if (!window.requestAnimationFrame)
window.requestAnimationFrame = function (callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall);
lastTime = currTime + timeToCall;
return id;
};
if (!window.cancelAnimationFrame)
window.cancelAnimationFrame = function (id) {
clearTimeout(id);
};
}())
function prepScreenQuad () {
var vertexPosBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer);
var vertices = [-1, -1, 1, -1, -1, 1, 1, 1];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
vertexPosBuffer.itemSize = 2;
vertexPosBuffer.numItems = 4;
/*
2 ___ 3
|\ |
| \ |
0|__\|1
*/
return vertexPosBuffer;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment