UNPKG

@figliolia/ripples

Version:

WebGL ripples based on the clever work of Pim Schreurs

120 lines (119 loc) 5.21 kB
"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;