glsl-transition v1.0.2
glsl-transition
render GLSL Transitions – transition effects performed with WebGL.
GLSL Transition ?
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.0 and 1.0.
A GLSL Transition is allowed (and encouraged) to have extra uniforms.
Example 1
var baboon = require("baboon-image");
var lena = require("lena");
var createTexture = require("gl-texture2d");
var createTransition = require("glsl-transition");
var CubeTransition = { // from "glsl-transitions"
"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, 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);
});
Example 2
var Q = require("q");
var Qimage = require("qimage");
var raf = require("raf");
var GlslTransitions = require("glsl-transitions").sort(function (a, b) {
return b.stars - a.stars;
});
var createTexture = require("gl-texture2d");
var createTransition = require("glsl-transition");
Q.all([
Qimage.anonymously("http://i.imgur.com/N8a9CkZ.jpg"),
Qimage.anonymously("http://i.imgur.com/MQtLWbD.jpg")
]).spread(function (fromImage, toImage) {
var canvas = document.createElement("canvas");
canvas.style.display = "block";
canvas.width = 600;
canvas.height = 400;
var gl = canvas.getContext("webgl");
if (!gl) throw new Error("webgl context is not supported.");
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
var from = createTexture(gl, fromImage);
var to = createTexture(gl, toImage);
var transitionItem, transition;
raf(function loop (t) {
raf(loop);
if (transition) {
var progress = (t/1500) % 2;
if (progress > 1) progress = 2 - progress; // backwards
transition.render(progress, from, to, transitionItem.uniforms);
}
});
function setTransition (i) {
transitionItem = GlslTransitions[i];
if (transition) transition.dispose();
transition = createTransition(gl, transitionItem.glsl);
}
var select = document.createElement("select");
select.style.width = "600px";
GlslTransitions.forEach(function (t) {
var option = document.createElement("option");
option.textContent = t.name;
select.appendChild(option);
});
select.addEventListener("change", function () {
setTransition(select.selectedIndex);
});
setTransition(select.selectedIndex);
document.body.innerHTML = "";
document.body.appendChild(select);
document.body.appendChild(canvas);
}).done();
document.body.innerHTML = "Loading...";
Example 3
GLSL Transitions performed between Videos
var raf = require("raf");
var createTexture = require("gl-texture2d");
var createTransition = require("glsl-transition");
var GlslTransitions = require("glsl-transitions").sort(function (a, b) {
return b.stars - a.stars;
});
var videos = require("./videos"); // Some logic to handle video load (this is a promise of videos)
videos.then(function (videos) {
var canvas = document.createElement("canvas");
canvas.style.display = "block";
canvas.width = 600;
canvas.height = 400;
var gl = canvas.getContext("webgl");
if (!gl) throw new Error("webgl context is not supported.");
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
var from = createTexture(gl, videos[0]);
var to = createTexture(gl, videos[1]);
var transitionItem, transition;
var duration = 1500;
videos.forEach(function (video) {
video.loop = true;
video.play();
});
raf(function loop (t) {
raf(loop);
var i = Math.floor(t / duration) % videos.length;
var j = (i + 1) % videos.length;
from.setPixels(videos[i]);
to.setPixels(videos[j]);
var progress = (t % duration) / duration;
if (transition) transition.render(progress, from, to, transitionItem.uniforms);
});
function setTransition (i) {
transitionItem = GlslTransitions[i];
if (transition) transition.dispose();
transition = createTransition(gl, transitionItem.glsl);
}
var select = document.createElement("select");
select.style.width = "600px";
GlslTransitions.forEach(function (t) {
var option = document.createElement("option");
option.textContent = t.name;
select.appendChild(option);
});
select.addEventListener("change", function () {
setTransition(select.selectedIndex);
});
setTransition(select.selectedIndex);
document.body.innerHTML = "";
document.body.appendChild(select);
document.body.appendChild(canvas);
}).done();
document.body.innerHTML = "Loading...";
9 years ago
9 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago