From 0104c684b88c0984c0dace211d8b7180dd489430 Mon Sep 17 00:00:00 2001 From: Jiri Swen Date: Mon, 27 Feb 2023 14:26:07 +0100 Subject: [PATCH 1/2] WebGL formatting improvements --- src/modules/webgl-demo.js | 112 +++++++++++++++++------------------ src/modules/webgl-flap.js | 88 ++++++++++++++-------------- src/modules/webgl-freak.js | 80 +++++++++++++------------ src/modules/webgl-wave.js | 79 ++++++++++++------------- src/webgl.js | 117 +++++++++++++++++++------------------ 5 files changed, 239 insertions(+), 237 deletions(-) diff --git a/src/modules/webgl-demo.js b/src/modules/webgl-demo.js index 278021a..10b2d6a 100644 --- a/src/modules/webgl-demo.js +++ b/src/modules/webgl-demo.js @@ -23,97 +23,95 @@ proto.margin = 0; proto.uniforms['amp'] = 1; // The vertex shader transforms vertex coordinates to on-screen pixels -proto.vertexShader = [ +proto.vertexShader = glsl` // x, y position for each vertex - "attribute vec2 pos;", + attribute vec2 pos; // timestamp in MS - "uniform float time;", + uniform float time; // Effect amplitude - "uniform float amp;", + uniform float amp; // Logo width, height ratio for correct rendering - "uniform vec2 ratio;", + uniform vec2 ratio; // Mouse position [x,y], where center is [0,0] - "uniform vec2 mousePos;", + uniform vec2 mousePos; // Send the vector to the fragment shader - "varying vec4 position;", + varying vec4 position; // Timestamp in ms from vertex shader - "varying float timeVar;", + varying float timeVar; // The amplitude of your effect (when mouse-overed) (0-1) - "varying float ampF;", + varying float ampF; - // This function runs for _every_ vector in the shape - "void main()", - "{", - // This variable is shared with the fragment shader - // The 4th position is used for clipping-- irrelevant here, keep it at 1 - "position = vec4(pos.x*ratio.x,pos.y*ratio.y,0.0,1.0);", + // This function runs for _every_ vertex in the shape + void main() { + // This variable is shared with the fragment shader + // The 4th position is used for clipping-- irrelevant here, keep it at 1 + position = vec4(pos.x*ratio.x,pos.y*ratio.y,0.0,1.0); - // Send needed variables to fragment shader - "timeVar = time;", - "ampF = amp;", + // Send needed variables to fragment shader + timeVar = time; + ampF = amp; - // Manipulate the x-position of this vertex based on time - "position.x *= cos(time*.005);", + // Manipulate the x-position of this vertex based on time + position.x *= cos(time*.005); - // gl_Position is the default output variable - "gl_Position = position;", - "}" -].join("\n"); + // gl_Position is the default output variable + gl_Position = position; + } +` // The fragment shader gives the pixels their actual color -proto.fragmentShader = [ +proto.fragmentShader = glsl` // Some default boilerplate mumbo-jumbo - "precision mediump float;", + precision mediump float; // The color as passed from Javascript - "uniform vec3 mainCol;", + uniform vec3 mainCol; // timestamp in MS from vertex shader - "varying float timeVar;", + varying float timeVar; // The amplitude of your effect - "varying float ampF;", + varying float ampF; // The shared vector position from the vertex shader - "varying vec4 position;", + varying vec4 position; // Color definitions - "const vec4 white = vec4(1.,1.,1.,1.);", - "const vec4 transparent = vec4(0.,0.,0.,0.);", + const vec4 white = vec4(1.,1.,1.,1.); + const vec4 transparent = vec4(0.,0.,0.,0.); // This runs for _every_ pixel drawn - "void main()", - "{", - // The output color, inherit from main color - "vec4 color = vec4(mainCol,1.);", - - // Play with the colors - "color.r = mainCol.r * cos(timeVar*.002);", - "color.g = mainCol.g * cos(timeVar*.01);", - "color.b = mainCol.b * cos(timeVar*.04);", - - // What to do with the white letters - //"if(mainCol == white.rgb) {", - // ampF becomes 1 when hovered - - // Keep them white, - //"color = white;", - - // ..or make them transparent on hover - //"color = (1.-ampF) * white + ampF * transparent;", - //"}", - - // gl_FragColor is the color rendered on screen - "gl_FragColor = color;", - "}" -].join("\n"); + void main() { + // The output color, inherit from main color + vec4 color = vec4(mainCol,1.); + + // Play with the colors + color.r = mainCol.r * cos(timeVar*.002); + color.g = mainCol.g * cos(timeVar*.01); + color.b = mainCol.b * cos(timeVar*.04); + + // What to do with the white letters + //"if(mainCol == white.rgb) {", + // ampF becomes 1 when hovered + + // Keep them white, + //"color = white;", + + // ..or make them transparent on hover + //"color = (1.-ampF) * white + ampF * transparent;", + //"}", + + // gl_FragColor is the color rendered on screen (RGBA) + gl_FragColor = color; + } +` // Module specifics -- fade-in and fade-out animation on mouse enter / leave diff --git a/src/modules/webgl-flap.js b/src/modules/webgl-flap.js index f6fdf2c..9b30ad0 100644 --- a/src/modules/webgl-flap.js +++ b/src/modules/webgl-flap.js @@ -10,50 +10,52 @@ proto.author = 'Sjoerd'; proto.uniforms['amp'] = 1; -proto.vertexShader = [ - "attribute vec2 pos;", - "uniform float time;", - "uniform float amp;", - "uniform vec2 mousePos;", - "varying vec2 mousePosF;", - "varying float ampF;", - "varying float timeF;", - "varying float flap;", - "uniform vec2 ratio;", - "varying vec3 position;", - "void main()", - "{", - "float a = amp * 3.1415 * 2.;", - "float curve = (1. - cos(a)) * .5;", - "flap = sin(time / 100.) * pow(pos.x, 2.) * pow(amp, .3);", - "position = vec3(pos.x * cos(flap), pos.y, 1.0 - curve * (1. - cos(pos.y)) - flap * (1. - amp*.5));", - "position = vec3(position.x, position.y * cos(a) + position.z * sin(a), position.z * cos(a) - position.y * sin(a));", - "position = vec3(position.xy / ((2.5 - position.z) / 1.5) * ratio, 0.);", - "mousePosF = mousePos;", - "ampF = amp;", - "timeF = time;", - "gl_Position = vec4(position,1.0);", - "}" -].join("\n"); +// todo: ga gwn dit proberen te runnen in een shader sandbox -proto.fragmentShader = [ - "precision mediump float;", - "uniform vec3 mainCol;", - "varying float ampF;", - "varying vec2 mousePosF;", - "varying float timeF;", - "varying vec3 position;", - "void main()", - "{", - "float mouseDist = length(mousePosF);", - "vec3 color = mainCol;", - "float lighten = sin(timeF / 100.) * pow(position.x, 1.) * pow(ampF, .3) * -1.;", - "color.r = 1. - (1. - mainCol.r) * (1. - ampF * lighten);", - "color.g = 1. - (1. - mainCol.g) * (1. - ampF * lighten);", - "color.b = 1. - (1. - mainCol.b) * (1. - ampF * lighten);", - "gl_FragColor = vec4(color , 1.0);", - "}" -].join("\n"); +proto.vertexShader = glsl` + attribute vec2 pos; + uniform float time; + uniform float amp; + uniform vec2 mousePos; + varying vec2 mousePosF; + varying float ampF; + varying float timeF; + varying float flap; + uniform vec2 ratio; + varying vec3 position; + + void main() { + float a = amp * 3.1415 * 2.; + float curve = (1. - cos(a)) * .5; + flap = sin(time / 100.) * pow(pos.x, 2.) * pow(amp, .3); + position = vec3(pos.x * cos(flap), pos.y, 1.0 - curve * (1. - cos(pos.y)) - flap * (1. - amp*.5)); + position = vec3(position.x, position.y * cos(a) + position.z * sin(a), position.z * cos(a) - position.y * sin(a)); + position = vec3(position.xy / ((2.5 - position.z) / 1.5) * ratio, 0.); + mousePosF = mousePos; + ampF = amp; + timeF = time; + gl_Position = vec4(position,1.0); + } +` + +proto.fragmentShader = glsl` + precision mediump float; + uniform vec3 mainCol; + varying float ampF; + varying vec2 mousePosF; + varying float timeF; + varying vec3 position; + + void main() { + float mouseDist = length(mousePosF); + vec3 color = mainCol; + float lighten = sin(timeF / 100.) * pow(position.x, 1.) * pow(ampF, .3) * -1.; + color.r = 1. - (1. - mainCol.r) * (1. - ampF * lighten); + color.g = 1. - (1. - mainCol.g) * (1. - ampF * lighten); + color.b = 1. - (1. - mainCol.b) * (1. - ampF * lighten); + gl_FragColor = vec4(color , 1.0); + } +` proto.initModule = function(){ this.logo.element.addEventListener('mouseenter', this.enter.bind(this)); diff --git a/src/modules/webgl-freak.js b/src/modules/webgl-freak.js index 9c97982..b49fe1a 100644 --- a/src/modules/webgl-freak.js +++ b/src/modules/webgl-freak.js @@ -12,50 +12,48 @@ proto.margin = 100; proto.uniforms['amp'] = 1; -proto.vertexShader = [ - "attribute vec2 pos;", - "uniform float time;", - "uniform float scale;", - "uniform float amp;", - "uniform vec2 mousePos;", - "varying vec2 mousePosF;", - "varying float ampF;", - "uniform vec2 ratio;", - "varying vec3 position;", - "void main()", - "{", - "position = vec3(pos*(1.-amp),0.) + amp * vec3(pos.x*mousePos.x+pos.x*sin((pos.y*time)/200.),-mousePos.y*pos.y+pos.y*cos(pos.x*time/1000.),pos.y*cos(time/2000.));", - "position.xy *= ratio;", - "position.xy *= scale;", - "mousePosF = mousePos;", - "ampF = amp;", - "gl_Position = vec4(position,1.0);", - "}" -].join("\n"); +proto.vertexShader = glsl` + attribute vec2 pos; + uniform float time; + uniform float scale; + uniform float amp; + uniform vec2 mousePos; + varying vec2 mousePosF; + varying float ampF; + uniform vec2 ratio; + varying vec3 position; -proto.fragmentShader = [ - "precision mediump float;", - "uniform vec3 mainCol;", - "varying float ampF;", - "varying vec2 mousePosF;", - "varying vec3 position;", - "const vec4 white = vec4(1.,1.,1.,1.);", - "const vec4 transparent = vec4(0.,0.,0.,0.);", - "void main()", - "{", - "float mouseDist = length(mousePosF);", - "vec4 color = vec4(mainCol,1.);", - "color.r = (1.-ampF) * mainCol.r + ampF * (mainCol.r + mouseDist * 1. + position.x);", - "color.g = (1.-ampF) * mainCol.g + ampF * (mainCol.g + position.z);", - "color.b = (1.-ampF) * mainCol.b + ampF * (mainCol.b + position.y);", + void main() { + position = vec3(pos*(1.-amp),0.) + amp * vec3(pos.x*mousePos.x+pos.x*sin((pos.y*time)/200.),-mousePos.y*pos.y+pos.y*cos(pos.x*time/1000.),pos.y*cos(time/2000.)); + position.xy *= ratio; + position.xy *= scale; + mousePosF = mousePos; + ampF = amp; + gl_Position = vec4(position,1.0); + } +` - "if(mainCol == white.rgb) {", - "color = (1.-ampF) * white + ampF * transparent;", - "}", +proto.fragmentShader = glsl` + precision mediump float; + uniform vec3 mainCol; + varying float ampF; + varying vec2 mousePosF; + varying vec3 position; + const vec4 white = vec4(1.,1.,1.,1.); + const vec4 transparent = vec4(0.,0.,0.,0.); - "gl_FragColor = color;", - "}" -].join("\n"); + void main() { + float mouseDist = length(mousePosF); + vec4 color = vec4(mainCol,1.); + color.r = (1.-ampF) * mainCol.r + ampF * (mainCol.r + mouseDist * 1. + position.x); + color.g = (1.-ampF) * mainCol.g + ampF * (mainCol.g + position.z); + color.b = (1.-ampF) * mainCol.b + ampF * (mainCol.b + position.y); + if(mainCol == white.rgb) { + color = (1.-ampF) * white + ampF * transparent; + } + gl_FragColor = color; + } +` proto.initModule = function(){ this.logo.element.addEventListener('mouseenter', this.enter.bind(this)); diff --git a/src/modules/webgl-wave.js b/src/modules/webgl-wave.js index ef24f32..2034898 100644 --- a/src/modules/webgl-wave.js +++ b/src/modules/webgl-wave.js @@ -10,46 +10,47 @@ proto.author = 'Sjoerd'; proto.uniforms['amp'] = 1; -proto.vertexShader = [ - "attribute vec2 pos;", - "uniform float time;", - "uniform float amp;", - "uniform vec2 mousePos;", - "varying vec2 mousePosF;", - "varying float ampF;", - "varying float timeF;", - "uniform vec2 ratio;", - "varying vec3 position;", - "void main()", - "{", - "float offset = .02 * cos(time/100. - pos.x*5. + pos.y*15.);", - "position = vec3(pos,0.) + amp * vec3(pos.x*offset,pos.y*offset,0.);", - "position.xy *= ratio;", - "mousePosF = mousePos;", - "ampF = amp;", - "timeF = time;", - "gl_Position = vec4(position,1.0);", - "}" -].join("\n"); +proto.vertexShader = glsl` + attribute vec2 pos; + uniform float time; + uniform float amp; + uniform vec2 mousePos; + varying vec2 mousePosF; + varying float ampF; + varying float timeF; + uniform vec2 ratio; + varying vec3 position; -proto.fragmentShader = [ - "precision mediump float;", - "uniform vec3 mainCol;", - "varying float ampF;", - "varying vec2 mousePosF;", - "varying float timeF;", - "varying vec3 position;", - "void main()", - "{", - "float mouseDist = length(mousePosF);", - "vec3 color = mainCol;", - "float lighten = .15*sin(timeF/100. - position.x*5. + position.y*15.);", - "color.r = mainCol.r + ampF * lighten;", - "color.g = mainCol.g + ampF * lighten;", - "color.b = mainCol.b + ampF * lighten;", - "gl_FragColor = vec4(color , 1.0);", - "}" -].join("\n"); + void main() { + float offset = .02 * cos(time/100. - pos.x*5. + pos.y*15.); + position = vec3(pos,0.) + amp * vec3(pos.x*offset,pos.y*offset,0.); + position.xy *= ratio; + position.z *= .001; + mousePosF = mousePos; + ampF = amp; + timeF = time; + gl_Position = vec4(position,1.0); + } +` + +proto.fragmentShader = glsl` + precision mediump float; + uniform vec3 mainCol; + varying float ampF; + varying vec2 mousePosF; + varying float timeF; + varying vec3 position; + + void main() { + float mouseDist = length(mousePosF); + vec3 color = mainCol; + float lighten = .15*sin(timeF/100. - position.x*5. + position.y*15.); + color.r = mainCol.r + ampF * lighten; + color.g = mainCol.g + ampF * lighten; + color.b = mainCol.b + ampF * lighten; + gl_FragColor = vec4(color , 1.0); + } +` proto.initModule = function(){ this.logo.element.addEventListener('mouseenter', this.enter.bind(this)); diff --git a/src/webgl.js b/src/webgl.js index b500728..d75fc29 100644 --- a/src/webgl.js +++ b/src/webgl.js @@ -1,4 +1,4 @@ -Q42Logo.WebGL = function(logo){ +Q42Logo.WebGL = function(logo) { this.logo = logo; }; @@ -16,44 +16,42 @@ Q42Logo.WebGL.prototype = { 'mainCol': 3 }, - vertexShader: [ - "attribute vec2 pos;", - "uniform float time;", - "uniform float scale;", - "uniform vec2 ratio;", - "uniform vec2 mousePos;", - "void main()", - "{", - "gl_Position = vec4(pos.x*ratio.x*scale,pos.y*ratio.y*scale,0.0,1.0);", - "}" - ].join("\n"), - - fragmentShader: [ - "precision mediump float;", - "uniform vec3 mainCol;", - "void main()", - "{", - "gl_FragColor = vec4(mainCol.r, mainCol.g, mainCol.b, 1.0);", - "}" - ].join("\n"), - - init: function(){ + vertexShader: glsl` + attribute vec2 pos; + uniform float time; + uniform float scale; + uniform vec2 ratio; + uniform vec2 mousePos; + void main() { + gl_Position = vec4(pos.x*ratio.x*scale,pos.y*ratio.y*scale,.0,1.0); + } + `, + + fragmentShader: glsl` + precision mediump float; + uniform vec3 mainCol; + void main() { + gl_FragColor = vec4(mainCol.r, mainCol.g, mainCol.b, 1.0); + } + `, + + init: function() { this.element = document.createElement('canvas'); this.element.className = !this.margin ? 'fill' : ''; this.gl = this.element.getContext('webgl') || this.element.getContext('experimental-webgl'); this.error = !this.gl; - if(this.error) return; + if (this.error) return; this.animating = false; this.scale = 1; - if(this.margin) this.element.style.pointerEvents = 'none'; + if (this.margin) this.element.style.pointerEvents = 'none'; this['uniformValues'] = this.uniformValues = {}; this.uniformRefs = {}; this.uniformArgs = {}; var color = [0,0,0]; - switch(this.logo.theme) { + switch (this.logo.theme) { case 'green': color = [132/255, 187/255, 37/255]; break; @@ -71,7 +69,7 @@ Q42Logo.WebGL.prototype = { this.draw = this.draw.bind(this); this.mousemove = this.mousemove.bind(this); - if(this.initModule instanceof Function) this.initModule(); + if (this.initModule instanceof Function) this.initModule(); this.setupGL(); this.logo.element.appendChild(this.element); @@ -79,20 +77,20 @@ Q42Logo.WebGL.prototype = { this.logo.element.addEventListener('touchmove', this.mousemove); }, - setSize: function(){ - if(this.error) return; + setSize: function() { + if (this.error) return; var elWidth = this.logo.element.clientWidth; var elHeight = this.logo.element.clientHeight || elWidth * this.logo.aspect; var width = (elWidth + this.margin * 2) * this.logo.ratio; var height = (elHeight + this.margin * 2) * this.logo.ratio; - if(this.margin) { + if (this.margin) { this.element.style.margin = -this.margin + 'px'; - if(this['uniformValues']['scale']) { - var min = Math.min(elWidth,elHeight); - if(elHeight / elWidth > 1) min *= this.logo.aspect; - if(min > elHeight) min = elHeight; - this['uniformValues']['scale'][0] = this.scale = min/(min+this.margin*2); + if (this['uniformValues']['scale']) { + var min = Math.min(elWidth, elHeight); + if (elHeight / elWidth > 1) min *= this.logo.aspect; + if (min > elHeight) min = elHeight; + this['uniformValues']['scale'][0] = this.scale = min / (min + this.margin * 2); } } @@ -104,8 +102,8 @@ Q42Logo.WebGL.prototype = { this.render(); }, - mousemove: function(e){ - if(!this.uniformValues['mousePos']) return; + mousemove: function(e) { + if (!this.uniformValues['mousePos']) return; e = e.touches && e.touches[0] || e; var rect = e.target.getBoundingClientRect(); var width = this.logo.element.clientWidth + this.margin; @@ -115,7 +113,7 @@ Q42Logo.WebGL.prototype = { }, // GL part - setupGL: function(){ + setupGL: function() { var gl = this.gl; this.program = gl.createProgram(); this.getShader(this.program, gl.VERTEX_SHADER, this.vertexShader); @@ -124,10 +122,10 @@ Q42Logo.WebGL.prototype = { // uniforms this.uniformRefs.ratio = gl.getUniformLocation(this.program, 'ratio'); - for(var x in this.uniforms) { + for (var x in this.uniforms) { this.uniformRefs[x] = gl.getUniformLocation(this.program, x); - if(!this.uniformRefs[x]) continue; - if(!this.uniformValues[x]) + if (!this.uniformRefs[x]) continue; + if (!this.uniformValues[x]) this.uniformValues[x] = new Float32Array(this.uniforms[x]); this.uniformArgs[x] = [this.uniformRefs].concat(new Array(this.uniforms[x])); } @@ -147,7 +145,7 @@ Q42Logo.WebGL.prototype = { var shader = gl.createShader(type); gl.shaderSource(shader, source); gl.compileShader(shader); - if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { console.error(gl.getShaderInfoLog(shader)); gl.deleteProgram(program); return; @@ -156,44 +154,45 @@ Q42Logo.WebGL.prototype = { gl.deleteShader(shader); }, - render: function(){ + render: function() { cancelAnimationFrame(this.af); - if(this.animating) + if (this.animating) this.af = requestAnimationFrame(this.render); this.draw(); }, - draw: function(){ + draw: function() { var gl = this.gl; var min = Math.min(this.element.width, this.element.height); - if(this.element.height / this.element.width > 1) min*=this.logo.aspect; - if(min > this.element.height) min = this.element.height; + if (this.element.height / this.element.width > 1) min *= this.logo.aspect; + if (min > this.element.height) min = this.element.height; - if(this.uniformValues['time']) + if (this.uniformValues['time']) this.uniformValues['time'][0] = 0; // For dynamic uniforms in modules - if(this.updateValues instanceof Function) this.updateValues(); + if (this.updateValues instanceof Function) this.updateValues(); gl.viewport(0, 0, this.gl.drawingBufferWidth, this.gl.drawingBufferHeight); gl.useProgram(this.program); // send uniforms - gl.uniform2f(this.uniformRefs.ratio, min/this.element.width, min/this.element.height); - for(var x in this.uniforms) { - if(!this.uniformRefs[x]) continue; - gl['uniform'+this.uniforms[x]+'f'].apply(gl, [this.uniformRefs[x]].concat(Array.prototype.slice.call(this.uniformValues[x]))); + gl.uniform2f(this.uniformRefs.ratio, min / this.element.width, min / this.element.height); + for (var x in this.uniforms) { + if (!this.uniformRefs[x]) continue; + gl['uniform' + this.uniforms[x] + 'f'].apply(gl, [this.uniformRefs[x]].concat(Array.prototype.slice.call(this.uniformValues[x]))); } // For white lettering var attr = gl.getAttribLocation(this.program, 'pos'); - if(this.logo.theme == 'green') { + if (this.logo.theme == 'green') { gl.uniform3f(this.uniformRefs['mainCol'], 1, 1, 1); gl.bindBuffer(gl.ARRAY_BUFFER, this.quadBuffer); gl.vertexAttribPointer(attr, 2, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(attr); - gl.drawArrays(gl.TRIANGLES, 0, this.whiteQuad.length/2); + // white quad wordt met te weinig vertices getekend, daardoor clipt hij soms op andere punten + gl.drawArrays(gl.TRIANGLES, 0, this.whiteQuad.length / 2); gl.disableVertexAttribArray(attr); gl.uniform3f(this.uniformRefs['mainCol'], this.uniformValues['mainCol'][0], this.uniformValues['mainCol'][1], this.uniformValues['mainCol'][2]); } @@ -203,13 +202,17 @@ Q42Logo.WebGL.prototype = { gl.bindBuffer(gl.ARRAY_BUFFER, this.triangleBuffer); gl.vertexAttribPointer(attr, 3, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(attr); - gl.drawArrays(gl.TRIANGLES, 0, this.vertices.length/3); + gl.drawArrays(gl.TRIANGLES, 0, this.vertices.length / 3); gl.disableVertexAttribArray(attr); } - }; Q42Logo.WebGL.prototype.vertices = new Float32Array(Q42Logo.WebGL.prototype.verticesString.split(',')); // for minification Q42Logo['webgl'] = Q42Logo.WebGL; + +/** + * No-op template tag function which tells some extensions to highlight/lint this string as GLSL. Usage: glsl`void main() {...}`) + */ +function glsl(x) { return x } From ba10fb1fcd176cae162c9075089843b53ac47af4 Mon Sep 17 00:00:00 2001 From: Jiri Swen Date: Mon, 27 Feb 2023 14:38:23 +0100 Subject: [PATCH 2/2] Also improve glsl formatting for 'bouncing' webgl anim --- src/modules/webgl-bouncing.js | 117 +++++++++++++++++----------------- 1 file changed, 58 insertions(+), 59 deletions(-) diff --git a/src/modules/webgl-bouncing.js b/src/modules/webgl-bouncing.js index eddf4bc..05dc0d7 100644 --- a/src/modules/webgl-bouncing.js +++ b/src/modules/webgl-bouncing.js @@ -12,75 +12,74 @@ proto.author = 'Katja'; // 1: float, 2: vec2(x,y), 3: vec3(x,y,z)/(r,g,b), 4: vec4(x,y,z,w)/(r,g,b,a) proto.uniforms['amp'] = 1; -proto.vertexShader = [ - "attribute vec2 pos;", - "uniform float time;", - "varying float timeVar;", - "uniform float amp;", - "uniform vec2 mousePos;", - "varying vec2 mousePosF;", - "varying float ampF;", - "varying float timeF;", - "uniform vec2 ratio;", - "varying vec4 position;", - "void main()", - "{", - // This variable is shared with the fragment shader - // The 4th position is used for clipping-- irrelevant here, keep it at 1 - "position = vec4(pos.x*ratio.x,pos.y*ratio.y,0.0,1.0);", - - // Share time with fragment shader - "timeVar = time;", - "ampF = amp;", - //"position = vec4(pos.x*ratio.x*.5, pos.y*ratio.y*.5, 0.0, 1.0);", - // Manipulate the position of this vertex based on time - "position.xy *= 1.0 - ampF * .5;", - "float bla = ampF * abs(cos(time*.005));", - "position.y += bla * .6 * (position.y + 1.0);", - "position.y += ampF * position.y * -.3;", - "position.y += bla * .7;", - "position.y += ampF * max(-.7, min(-.7, position.y));", - - // gl_Position is the default output variable - "gl_Position = position;", - "}" -].join("\n"); +proto.vertexShader = glsl` + attribute vec2 pos; + uniform float time; + varying float timeVar; + uniform float amp; + uniform vec2 mousePos; + varying vec2 mousePosF; + varying float ampF; + varying float timeF; + uniform vec2 ratio; + varying vec4 position; + + void main() { + // This variable is shared with the fragment shader + // The 4th position is used for clipping-- irrelevant here, keep it at 1 + position = vec4(pos.x*ratio.x,pos.y*ratio.y,0.0,1.0); + // Share time with fragment shader + timeVar = time; + ampF = amp; + // position = vec4(pos.x*ratio.x*.5, pos.y*ratio.y*.5, 0.0, 1.0); + // Manipulate the position of this vertex based on time + position.xy *= 1.0 - ampF * .5; + float bla = ampF * abs(cos(time*.005)); + position.y += bla * .6 * (position.y + 1.0); + position.y += ampF * position.y * -.3; + position.y += bla * .7; + position.y += ampF * max(-.7, min(-.7, position.y)); + + // gl_Position is the default output variable + gl_Position = position; + } +` // The fragment shader gives the pixels their actual colour -proto.fragmentShader = [ +proto.fragmentShader = glsl` // Some default boilerplate mumbo-jumbo - "precision mediump float;", + precision mediump float; // The colour as passed from Javascript - "uniform vec3 mainCol;", - "varying float ampF;", + uniform vec3 mainCol; + varying float ampF; - // timestamp in MS from vertex shader - "varying float timeVar;", + // timestamp in MS from vertex shader + varying float timeVar; // The shared vector position from the vertex shader - "varying vec4 position;", + varying vec4 position; // This runs for _every_ pixel drawn - "void main()", - "{", - //amp == 1 mouse over, amp == 0 mouse leave - "vec3 initialColor = vec3(132.0/255.0, 187.0/255.0, 37.0/255.0);", - // Play with the colours - "float red = initialColor.r * (1.0 - ampF) + ampF * abs(cos(timeVar*.0012));", - "float green = initialColor.g * (1.0 - ampF) + ampF * abs(cos(timeVar*.0016));", - "float blue = initialColor.b * (1.0 - ampF) + ampF * abs(cos(timeVar*.0029));", - - //make letters white - "if(mainCol == vec3(1.0,1.0,1.0)) {", - "red = 1.0;", - "green = 1.0;", - "blue = 1.0;", - "}", - // Output is RGBA - "gl_FragColor = vec4(red, green, blue, 1.0);", - "}" -].join("\n"); + void main() { + //amp == 1 mouse over, amp == 0 mouse leave + vec3 initialColor = vec3(132.0/255.0, 187.0/255.0, 37.0/255.0); + // Play with the colours + float red = initialColor.r * (1.0 - ampF) + ampF * abs(cos(timeVar*.0012)); + float green = initialColor.g * (1.0 - ampF) + ampF * abs(cos(timeVar*.0016)); + float blue = initialColor.b * (1.0 - ampF) + ampF * abs(cos(timeVar*.0029)); + + //make letters white + if (mainCol == vec3(1.0,1.0,1.0)) { + red = 1.0; + green = 1.0; + blue = 1.0; + } + + // Output is RGBA + gl_FragColor = vec4(red, green, blue, 1.0); + } +` // Module specifics -- fade-in and fade-out animation on mouse enter / leave