UNPKG

demolishedtexture

Version:

Procedual texture generator for Demolished or what ever you want.Renders base64 strings and/or binary.

174 lines (173 loc) 6.01 kB
export class TextureBase { perm: Array<number>; constructor() { this.perm = this.seed(255); } vec(x: number,y?: number,z?: number,a?: number):Array<number>{ return [x,y|0,z|0,a|0] ; //filter( (v) => {return v}); } normalize(a: Array<number>): Array<number> { let l = this.length(a); l != 0 ? a = this.func(a, function(v,i) { return v / l; } ) : a = a; return a; } R(a:number,b:number):number{ return Math.abs((a * b) * 255); } abs(a: Array<number>): Array<number> { return a.map((v, i) => { return Math.abs(v) }); } func(a: Array<number>, exp: Function) { return a.map((v, i) => exp(v,i) ); } toScale(v, w) { var a = 0, b = w, c = -1, d = 1.; return (v - a) / (b - a) * (d - c) + c; }; dot(a: Array<number>, b: Array<number>): number { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; } length(a: Array<number>): number { return Math.sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]); } fade(t: number): number { return t * t * t * (t * (t * 6 - 15) + 10); } clamp(n:number, a:number, b:number):number { return n <= a ? a : n >= b ? b : n; } lerp(t: number, a: number, b: number): number { return a + t * (b - a); } grad(hash: number, x: number, y: number, z: number): number { var h = hash & 15; var u = h < 8 ? x : y, v = h < 4 ? y : h == 12 || h == 14 ? x : z; return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v); } scale(n: number): number { return (1 + n) / 2; } seed(n: number): Array<number> { var p = []; for (var a = [], b = 0; n >= b; b++)a.push(b); for (b = 0; n >= b; b++) { var c = n * Math.random(), d = a[~~c]; a.splice(c, 1, a[b]); a.splice(b, 1, d); }; for (var i = 0; i < n; i++) p[n + i] = p[i] = a[i]; return p; } noise(x: number, y: number, z: number): number { let t = this; let p = this.perm; let X = ~~(x) & 255, Y = ~~(y) & 255, Z = ~~(z) & 255; x -= ~~(x); y -= ~~(y); z -= ~~(z); let u = t.fade(x), v = t.fade(y), w = t.fade(z); let A = p[X] + Y, AA = p[A] + Z, AB = p[A + 1] + Z, B = p[X + 1] + Y, BA = p[B] + Z, BB = p[B + 1] + Z; return t.scale(t.lerp(w, t.lerp(v, t.lerp(u, t.grad(p[AA], x, y, z), t.grad(p[BA], x - 1, y, z)), t.lerp(u, t.grad(p[AB], x, y - 1, z), t.grad(p[BB], x - 1, y - 1, z))), t.lerp(v, t.lerp(u, t.grad(p[AA + 1], x, y, z - 1), t.grad(p[BA + 1], x - 1, y, z - 1)), t.lerp(u, t.grad(p[AB + 1], x, y - 1, z - 1), t.grad(p[BB + 1], x - 1, y - 1, z - 1))))); } } export class TextureGen { ctx: CanvasRenderingContext2D buffer: ImageData; helpers: TextureBase; constructor(public width: number, public height: number) { let c = document.createElement("canvas") as HTMLCanvasElement; c.width = width; c.height = height; this.ctx = c.getContext("2d"); this.ctx.fillStyle = "#0"; this.ctx.fillRect(0, 0, this.width, this.height); this.buffer = this.ctx.getImageData(0, 0, this.width, this.height); this.helpers = new TextureBase(); } /** * Generate a texture using a GLSL-Way - Pixel based * * @static * @param {number} width * @param {number} height * @param {Function} fn * @returns {TextureGen} * @memberof TextureGen */ static G(width: number, height: number, fn: Function): TextureGen { let instance = new TextureGen(width, height); instance.render(fn); return instance;//.toBase64(); } private frag = (pixel: Array<number>, x: number, y: number, w: number, h: number,v:Array<number>, fn: Function): Array<number> => { let r = pixel[0]; var g = pixel[1]; var b = pixel[2]; let t = this.helpers; var res = fn.apply( t, [[r, b, g], x, y, w, h,v]); return res; }; private render(fn: Function) { let bf = this.buffer; let f = bf.data; let w = this.width, h = this.height; let s = this.helpers.toScale; for (var i, x = 0; x < w; x++) { for (var y = 0; y < h; y++) { i = (x + y * w) * 4; var r = f[i + 0]; var g = f[i + 1]; var b = f[i + 2]; let v = [s(x, w), s(y, w), 0]; var p = this.frag([r, g, b], x, y, w, h,v, fn); f[i + 0] = p[0]; f[i + 1] = p[1]; f[i + 2] = p[2]; } } this.ctx.putImageData(bf, 0, 0); } toBase64(): string { return this.ctx.canvas.toDataURL("image/png"); } toBlob(cb:any):void{ this.ctx.canvas.toBlob(cb,"image/png"); } } export class CanvasTextureGen extends TextureGen{ constructor(x:number,y:number,w:number,h:number){ super(w,h); } private D(fn: Function):Array<number>{ let res = fn.apply( this.helpers, [this.ctx,0,0,this.width, this,this.height]); return res; } /** * Generate a texture using HTML5 Canvas API * * @static * @param {number} width * @param {number} height * @param {Function} fn * @returns {CanvasTextureGen} * @memberof CanvasTextureGen */ static G(width: number, height: number, fn: Function): CanvasTextureGen { let instance = new CanvasTextureGen(0,0,width, height); instance.D(fn); return instance;//.toBase64(); } }