Recent I see some very nice visual effects done in GLSL fragment shader here. I love them very much and I started learning GLSL fragment shaders afterwards.
I think that they are great but they must run on GPU. Only some browser vendors provide API to access the GPU (Actually, that API is called WebGL) so these visuals can’t run on some browsers that don’t offer the WebGL API.
In order to overcome these, I tried to port GLSL fragment shaders to javascript and draw the result using HTML5 canvas. The canvas API has a much broader browser support (and a flash fallback is available).
The demos I created are un-optimized and maybe a bit slow. After all, GLSL shaders are supposed to run on a GPU. However, it’s still worth to convert some of the GLSL shaders to achieve some nice effect such as post-processing of photos.
Here’s the demo:
- http://jsfiddle.net/licson0729/eBjQ8/
- http://jsfiddle.net/licson0729/YJqB9/
- http://jsfiddle.net/licson0729/7Qe34/
- http://jsfiddle.net/licson0729/T3hb7/
- http://jsfiddle.net/licson0729/9QVxA/
The techniques I used is to render the pixels one by one, with the render function be the one in the GLSL fragment shader. Also, we need to change the schematics (vec2, vec3, etc.) to its JavaScript equivalent.
Here’s the format of the code:
//The requestAnimFrame fallback for better and smoother animation window.requestAnimFrame = (function () { return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) { window.setTimeout(callback, 1000 / 60); }; })(); //Prepare our canvas var canvas = document.querySelector('#render'); var w = window.innerWidth; var h = window.innerHeight; canvas.width = w; canvas.height = h; var ctx = canvas.getContext('2d'); var time = Date.now(); var buffer = ctx.createImageData(w, h);//The back buffer we used to paint the result into the canvas //The main rencer function function render(time, fragcoord) { /* put the GLSL fragment shader's JavaScript equivalent here. */ return [0,0,0,0]; //the final colour value }; function animate() { var delta = (Date.now() - time) / 1000; buffer = ctx.createImageData(w, h); ctx.clearRect(0, 0, w, h); for (var x = 0; x < w; x++) { for (var y = 0; y < h; y++) { var ret = render(delta, [x, y]); var i = (y * buffer.width + x) * 4; buffer.data[i] = ret[0] * 255; buffer.data[i + 1] = ret[1] * 255; buffer.data[i + 2] = ret[2] * 255; buffer.data[i + 3] = ret[3] * 255; } } ctx.putImageData(buffer, 0, 0); requestAnimFrame(animate); }; window.onresize = function () { w = window.innerWidth; h = window.innerHeight; canvas.width = w; canvas.height = h; }; animate();
Hope you like it and encouraged you to start learning about computer graphics.
I wonder if you could split the work up with webworkers?
This looks like a great thing to benchmark different techniques with.
Found this js-to-shader thing which is interesting too
http://typedarray.org/wp-content/projects/shaderdsl-slides/#the-other-web-pl
Yeah passing these stuff into web workers are possible, but then there may have some issue around synchronization. Also, passing data to and from web workers can be slow, especially these are video frames. Such problems can be solved if using transferable objects, but that is still only available in Chrome so while it is possible, there may have serious problems with the rendering.
Hy Licson,
In fact RapydScript, is a translator from Python to Javascript.
It’s in fact a dialect of Python. It’s main advantage is that it integrates
totaly with third parties Javascript libraries.
The main site is here :
http://pyjeon.pythonanywhere.com/rapydscript
I have published a page of samples here :
http://salvatore.pythonanywhere.com/RapydScript
Regards
Salvatore
Than you very much 🙂
I have implement it (partly) in RapydScript
http://salvatore.pythonanywhere.com/RapydBox
Regards
That’s great! Maybe you can find some more good shaders to implement @ http://glsl.heroku.com/.
Besides, what’s RapydScript? It looks like python run inside a browser. 😉