Skip to content

Instantly share code, notes, and snippets.

@gre
Created April 5, 2015 19:52
Show Gist options
  • Save gre/f3efcede1d084f324568 to your computer and use it in GitHub Desktop.
Save gre/f3efcede1d084f324568 to your computer and use it in GitHub Desktop.
wip refactoring of glsl-transition
var baboon = require("baboon-image");
var lena = require("lena");
var createTexture = require("gl-texture2d");
var createTransition = require("./glsl-transition");
// from "glsl-transitions"
var CubeTransition = {
"id" : "ee15128c2b87d0e74dee",
"name" : "cube",
"owner" : "gre",
"glsl" : "#ifdef GL_ES\nprecision highp float;\n#endif\nuniform sampler2D from, to;\nuniform float progress;\nuniform vec2 resolution;\n\nuniform float persp;\nuniform float unzoom;\nuniform float reflection;\nuniform float floating;\n\nvec2 project (vec2 p) {\n return p * vec2(1.0, -1.2) + vec2(0.0, -floating/100.);\n}\n\nbool inBounds (vec2 p) {\n return all(lessThan(vec2(0.0), p)) && all(lessThan(p, vec2(1.0)));\n}\n\nvec4 bgColor (vec2 p, vec2 pfr, vec2 pto) {\n vec4 c = vec4(0.0, 0.0, 0.0, 1.0);\n pfr = project(pfr);\n if (inBounds(pfr)) {\n c += mix(vec4(0.0), texture2D(from, pfr), reflection * mix(1.0, 0.0, pfr.y));\n }\n pto = project(pto);\n if (inBounds(pto)) {\n c += mix(vec4(0.0), texture2D(to, pto), reflection * mix(1.0, 0.0, pto.y));\n }\n return c;\n}\n\n// p : the position\n// persp : the perspective in [ 0, 1 ]\n// center : the xcenter in [0, 1] \\ 0.5 excluded\nvec2 xskew (vec2 p, float persp, float center) {\n float x = mix(p.x, 1.0-p.x, center);\n return (\n (\n vec2( x, (p.y - 0.5*(1.0-persp) * x) / (1.0+(persp-1.0)*x) )\n - vec2(0.5-distance(center, 0.5), 0.0)\n )\n * vec2(0.5 / distance(center, 0.5) * (center<0.5 ? 1.0 : -1.0), 1.0)\n + vec2(center<0.5 ? 0.0 : 1.0, 0.0)\n );\n}\n\nvoid main() {\n vec2 op = gl_FragCoord.xy / resolution.xy;\n float uz = unzoom * 2.0*(0.5-distance(0.5, progress));\n vec2 p = -uz*0.5+(1.0+uz) * op;\n vec2 fromP = xskew(\n (p - vec2(progress, 0.0)) / vec2(1.0-progress, 1.0),\n 1.0-mix(progress, 0.0, persp),\n 0.0\n );\n vec2 toP = xskew(\n p / vec2(progress, 1.0),\n mix(pow(progress, 2.0), 1.0, persp),\n 1.0\n );\n if (inBounds(fromP)) {\n gl_FragColor = texture2D(from, fromP);\n }\n else if (inBounds(toP)) {\n gl_FragColor = texture2D(to, toP);\n }\n else {\n gl_FragColor = bgColor(op, fromP, toP);\n }\n}",
"uniforms" : {
"persp" : 0.7,
"unzoom" : 0.3,
"reflection" : 0.4,
"floating" : 3.0
}
};
var transition;
var from, to;
var shell = require("gl-now")();
shell.on("gl-init", function() {
var gl = shell.gl;
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
transition = createTransition(gl, CubeTransition.glsl);
to = createTexture(gl, baboon.transpose(1, 0));
from = createTexture(gl, lena.transpose(1, 0));
});
shell.on("gl-render", function () {
transition.render((Date.now() / 1000) % 1, from, to, CubeTransition.uniforms);
});
var createShader = require("gl-shader");
var vertexShader = 'attribute vec2 position; void main() { gl_Position = vec4(2.0*position-1.0, 0.0, 1.0);}';
/**
* A GLSL Transition is a fragment shader that MUST have 4 uniforms:
* uniform sampler2D from, to;
* uniform float progress;
* uniform vec2 resolution;
*
* A GLSL Transition draws a transition between from and to textures
* when progress moves between 0 and 1.
*
* A GLSL Transition is allowed (and encouraged) to have extra uniforms.
*/
function GlslTransition (gl, fragmentShader) {
this.gl = gl;
this.shader = createShader(gl, vertexShader, fragmentShader);
this.buffer = gl.createBuffer();
}
GlslTransition.prototype = {
dispose: function () {
this.shader.dispose();
this.gl.deleteBuffer(this.buffer);
this.gl = null;
this.shader = null;
this.buffer = null;
},
render: function (progress, from, to, extraUniforms) {
var gl = this.gl;
var shader = this.shader;
var unit = 0;
shader.bind();
this._checkViewport();
shader.uniforms.progress = progress;
shader.uniforms.from = from.bind(unit++);
shader.uniforms.to = to.bind(unit++);
for (var key in extraUniforms) {
var value = extraUniforms[key];
if (value && value.bind) {
shader.uniforms[key] = value.bind(unit++);
}
else if (shader.uniforms[key] !== value) {
shader.uniforms[key] = value;
}
}
gl.drawArrays(gl.TRIANGLES, 0, 6);
},
_checkViewport: function () {
var gl = this.gl;
var canvas = gl.canvas;
var w = canvas.width, h = canvas.height;
if (this._w!==w || this._h!==h) {
this._syncViewport(w, h);
this._w = w;
this._h = h;
}
},
_syncViewport: function (w, h) {
var gl = this.gl;
var shader = this.shader;
var buffer = this.buffer;
var x1 = 0, x2 = w, y1 = 0, y2 = h;
shader.uniforms.resolution = new Float32Array([ w, h ]);
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
shader.attributes.position.pointer();
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
x1, y1,
x2, y1,
x1, y2,
x1, y2,
x2, y1,
x2, y2
]), gl.STATIC_DRAW);
gl.viewport(x1, y1, x2, y2);
}
};
module.exports = function createTransition (gl, fragmentShader) {
return new GlslTransition(gl, fragmentShader);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment