@figliolia/ripples
Version:
WebGL ripples based on the clever work of Pim Schreurs
120 lines (119 loc) • 5.21 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebGL = void 0;
const ImageLoader_1 = require("./ImageLoader");
const Options_1 = require("./Options");
const Shaders_1 = require("./Shaders");
const StyleCache_1 = require("./StyleCache");
const Textures_1 = require("./Textures");
class WebGL extends Options_1.Options {
constructor(target, ...rest) {
super(...rest);
this.StyleCache = new StyleCache_1.StyleCache();
this.imageSource = null;
this.target = target;
this.canvas = document.createElement("canvas");
this.positionCanvas();
this.GL = this.createGL(this.canvas);
this.Shaders = new Shaders_1.Shaders(this.GL, this.resolution);
this.Textures = new Textures_1.Textures(this.GL);
}
initializeWebGL() {
this.Textures.initialize(this.resolution);
this.GL.bufferData(this.GL.ARRAY_BUFFER, new Float32Array([-1, -1, +1, -1, +1, +1, -1, +1]), this.GL.STATIC_DRAW);
this.Textures.setTransparent();
void this.loadImage().then(() => {
var _a;
(_a = this.onInitialized) === null || _a === void 0 ? void 0 : _a.call(this);
});
this.GL.clearColor(0, 0, 0, 0);
this.GL.blendFunc(this.GL.SRC_ALPHA, this.GL.ONE_MINUS_SRC_ALPHA);
}
hideCSSBackground() {
const inlineCSS = this.target.style.backgroundImage;
if (inlineCSS === "none") {
return;
}
this.StyleCache.set("originalInlineCSS", inlineCSS);
this.StyleCache.set("originalCSSBackgroundImage", window.getComputedStyle(this.target).backgroundImage);
this.target.style.backgroundImage = "none";
}
render() {
this.GL.bindFramebuffer(this.GL.FRAMEBUFFER, null);
this.GL.viewport(0, 0, this.canvas.width, this.canvas.height);
this.GL.enable(this.GL.BLEND);
this.GL.clear(this.GL.COLOR_BUFFER_BIT | this.GL.DEPTH_BUFFER_BIT);
this.GL.useProgram(this.Shaders.renderProgram.id);
this.bindTexture(this.Textures.backgroundTexture, 0);
this.bindTexture(this.Textures.firstTexture, 1);
this.Shaders.render(this.perturbance);
this.Textures.drawQuad();
this.GL.disable(this.GL.BLEND);
}
update() {
this.GL.viewport(0, 0, this.resolution, this.resolution);
this.GL.bindFramebuffer(this.GL.FRAMEBUFFER, this.Textures.writeFrame);
this.bindTexture(this.Textures.readTexture);
this.GL.useProgram(this.Shaders.updateProgram.id);
this.Textures.drawQuad();
this.Textures.swapBufferIndices();
}
isPercentage(str) {
return str[str.length - 1] == "%";
}
bindTexture(texture, unit = 0) {
this.GL.activeTexture(this.GL.TEXTURE0 + (unit || 0));
this.GL.bindTexture(this.GL.TEXTURE_2D, texture);
}
positionCanvas() {
this.canvas.width = this.target.offsetWidth;
this.canvas.height = this.target.offsetHeight;
this.canvas.style.position = "absolute";
this.canvas.style.top = "0";
this.canvas.style.right = "0";
this.canvas.style.bottom = "0";
this.canvas.style.left = "0";
this.canvas.style.zIndex = "-1";
this.target.appendChild(this.canvas);
}
createGL(canvas) {
return (canvas.getContext("webgl") ||
canvas.getContext("experimental-webgl"));
}
loadImage() {
return __awaiter(this, void 0, void 0, function* () {
const { backgroundImage } = window.getComputedStyle(this.target);
const newImageSource = this.imageUrl ||
this.extractUrl(this.StyleCache.get("originalCSSBackgroundImage")) ||
this.extractUrl(backgroundImage);
if (newImageSource == this.imageSource) {
return;
}
this.imageSource = newImageSource;
if (!this.imageSource) {
this.Textures.setTransparent();
return;
}
try {
const loader = new ImageLoader_1.ImageLoader(this.Textures);
const image = yield loader.load(this.imageSource, this.crossOrigin);
this.StyleCache.set("backgroundWidth", image.width);
this.StyleCache.set("backgroundHeight", image.height);
this.hideCSSBackground();
}
catch (error) {
// silence
}
});
}
}
exports.WebGL = WebGL;