Thursday, February 9, 2012

WebGL JS1K entry

As a sort of follow up to last years Itty Bitty WebGL post I decided to take a crack at actually entering the js1k competition this time around. Since the theme of the competition is "Love" I thought it would be fitting to do a minimalistic version of this awesome little "beating heart" shader.

You can see my under 1k version here.

And the not-quite-so-compressed-but-still-really-hard-to-read source code here:

c=document.getElementById('c');
c.height=300;
g=c.getContext('experimental-webgl');

b=g.createBuffer();
a=34962;
g.bindBuffer(a,b); 
g.bufferData(a,new Float32Array([0,0,2,0,0,2,0,2,2,0,2,2]),35044); 
g.vertexAttribPointer(0,2,5126,false,0,0);

p=g.createProgram();
function l(x,y){
    s=g.createShader(35633-x);
    g.shaderSource(s,y.replace(/#/g,'float ').replace(/\^/g,'vec'));
    g.compileShader(s);
    g.attachShader(p,s);
}

// See the uncompressed shader code at http://glsl.heroku.com/e#1599.2

l(0,'attribute ^2 p;void main(){gl_Position=^4(p.x-1.0,p.y-1.0,1,1);}');
l(1,'precision highp #; uniform #t;^2 r=^2(300,300);^3 h(#x,#y){#s=mod(t,1.0);s=1.0+(1.0-exp(-5.0*s)*sin(9.0*s));x*=s;y*=s;#h=abs(atan(x,y)/3.14);#d=(13.0*h-22.0*h*h+10.0*h*h*h)/(6.0-5.0*h);return mix(vec3(1.0,0,0),vec3(1.0),smoothstep(d-0.05,d,sqrt(x*x+y*y)));}void main(){^2 p=^2(-1.0+2.0*gl_FragCoord.xy/r);gl_FragColor=^4(h(p.x,p.y),1.0);}');

g.linkProgram(p);
g.useProgram(p);
g.enableVertexAttribArray(0);

u=0;
setInterval(function(){
    g.uniform1f(g.getUniformLocation(p,'t'),u+=0.02);
    g.drawArrays(4,0,6);
},16);

To be perfectly honest, I really don't care to explain the details of what's going on here. The basic setup is the same as my previous post on the subject, with the core difference being that we're now rendering a fullscreen quad. (That effectively makes this a tiny version of mr doobs GLSL Sandbox) The shader code is really just a minimal implementation of the original shader, and the only really interesting trick there is that I'm doing a string replace to simplify commonly repeated symbols like "float" and "vec".

I'm not certain that this even qualifies for the contest (since WebGL isn't enabled by default on some of the required browsers) but I had fun doing it and it was a good break from everything else going on in my life right now. (I'll be posting more on THAT shortly.)

OVERNIGHT UPDATE: So apparently I missed the line on the rules page that actually excludes WebGL from the competition (Second to last bullet under "Other things you should know"). That's a shame, but hopefully WebGL will be allowed for the next round! Doesn't matter much to me, I was just doing it for kicks anyway.

In other news, @p01 managed to cull 303 bytes out of my demo while I was sleeping which I think is deserving of a "I'm not worthy!" bow. There's some seriously clever little tricks in his version that I'm most certainly going to have to utilize the next time I try one of these! :)